<?php

namespace App\Http\Controllers;

use App\Helper\Helper;
use Illuminate\Http\Request;
use Illuminate\Support\MessageBag;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Session;

class PromptController extends Controller
{
    public function index(Request $request)
    {
        $errors = new MessageBag();
        $prompts = [];

        $url = env('API_URL') . "prompts";
        try {
            $response = Helper::GetApi($url);
            if ($response->success) {
                $prompts = $response->data;
            } else {
                foreach ($response->errors as $key => $message) {
                    $errors->add($key, $message);
                }
            }
        } catch (\Throwable $ex) {
            $errors->add("error", $ex->getMessage());
        }

        return view('prompts.index', compact('prompts', 'errors'));
    }

    public function create()
    {
        if(!(Session::get('level') >= 9)){
            return abort(403);
        }
        $inherit_list = new InheritApiController;
        $label_list = $inherit_list->getLabel();
        usort($label_list, function ($a, $b) {
            return strcasecmp($a->title, $b->title);
        });
        return view('prompts.create', compact('label_list'));
    }

    public function store(Request $request)
    {
        if(!(Session::get('level') >= 9)){
            return abort(403);
        }
        $errors = new MessageBag();

        $payload = [
            'title' => $request->input('title'),
            'description' => $request->input('description'),
            'initial_greeting' => $request->input('initial_greeting'),
            'user_id' => auth()->id(), // pass logged-in user id
            'voice_name' => $request->input('voice_name'),
        ];

        $url = env('API_URL') . "prompts";
        try {
            $response = Helper::PostApi($url, $payload);
            if ($response->success) {
                return redirect()->route('prompts.index')->with('success', 'Prompt added successfully');
            } else {
                foreach ($response->errors as $key => $message) {
                    $errors->add($key, $message);
                }
            }
        } catch (\Throwable $ex) {
            $errors->add("error", $ex->getMessage());
        }

        return back()->withInput()->with('errors', $errors);
    }

    public function show($id)
    {
        $errors = new MessageBag();

        $url = env('API_URL') . "prompts/{$id}";

        try {
            $response = Helper::GetApi($url);

            if ($response->success) {
                $prompt = $response->data->prompt ?? null;
                $functions = $response->data->functions ?? [];

                return response()->json([
                    'success' => true,
                    'message' => 'Prompt data retrieved successfully.',
                    'data' => [
                        'prompt' => $prompt,
                        'functions' => $functions,
                    ],
                ], 200);
            } else {
                foreach ($response->errors as $key => $message) {
                    $errors->add($key, $message);
                }

                return response()->json([
                    'success' => false,
                    'message' => 'Failed to fetch prompt data.',
                    'errors' => $errors->toArray(),
                ], 400);
            }
        } catch (\Throwable $ex) {
            return response()->json([
                'success' => false,
                'message' => 'An unexpected error occurred.',
                'errors' => ['exception' => $ex->getMessage()],
            ], 500);
        }
    }


    public function edit($id)
    {
        if(!(Session::get('level') >= 9)){
            return abort(403);
        }
        $errors = new MessageBag();
        $prompt = null;
        $inherit_list = new InheritApiController;
        $label_list = $inherit_list->getLabel();
        usort($label_list, function ($a, $b) {
            return strcasecmp($a->title, $b->title);
        });
        $template_list =  $inherit_list->getSmsTemplete();
        // echo Session::get('tokenId'); exit;
        if (!is_array($template_list)) {
            $template_list = array();
        }
        if (empty($template_list)) {
            if (empty(\Session::get('tokenId'))) {
                return redirect('/');
            }
        }

        // Get DID list for SMS function
        $did_list = $inherit_list->getDidList();
        if (!is_array($did_list)) {
            $did_list = array();
        }

        $url = env('API_URL') . "prompts/{$id}";
        try {
            $response = Helper::GetApi($url);

            if ($response->success) {
                // Now backend returns 'prompt' and 'functions' explicitly
                \Log::info('edit', [$response]);
                $prompt = $response->data->prompt ?? null;
                $functions = $response->data->functions ?? [];
            } else {
                foreach ($response->errors as $key => $message) {
                    $errors->add($key, $message);
                }
                $functions = [];
            }
        } catch (\Throwable $ex) {
            $errors->add("error", $ex->getMessage());
            $functions = [];
        }

        $url = env('API_URL') . "email-templates";
        try {
            $response = Helper::GetApi($url);
            if ($response->success) {
                $email_templates = $response->data;
            } else {
                foreach ($response->errors as $key => $message) {
                    $errors->add($key, $message);
                }
            }
        } catch (\Throwable $ex) {
            $errors->add("error", $ex->getMessage());
            $functions = [];
        }
        $template_list = collect($template_list)->sortBy('templete_name')->values()->all();
        $email_templates = collect($email_templates)->sortBy('template_name')->values()->all();

        return view('prompts.edit', compact('prompt', 'functions', 'errors', 'label_list', 'template_list', 'email_templates', 'did_list'));
    }


    public function update(Request $request, $id)
    {
        if(!(Session::get('level') >= 9)){
            return abort(403);
        }
        $errors = new MessageBag();
        $payload = [
            'title' => $request->input('title'),
            'description' => $request->input('description'),
            'initial_greeting' => $request->input('initial_greeting'),
            'voice_name' => $request->input('voice_name'),
        ];

        $url = env('API_URL') . "prompts/update/{$id}";
        try {
            $response = Helper::PostApi($url, $payload);
            if ($response->success) {
                return redirect()->route('prompts.index')->with('success', 'Prompt updated successfully');
            } else {
                foreach ($response->errors as $key => $message) {
                    $errors->add($key, $message);
                }
            }
        } catch (\Throwable $ex) {
            $errors->add("error", $ex->getMessage());
        }

        return back()->withInput()->with('errors', $errors);
    }

    public function destroy($id)
    {
        if(!(Session::get('level') >= 9)){
            return abort(403);
        }
        $errors = new MessageBag();
        $url = env('API_URL') . "prompts/delete/{$id}";
        try {
            $response = Helper::PostApi($url);
            if ($response->success) {
                return redirect()->route('prompts.index')->with('success', 'Prompt deleted successfully');
            } else {
                foreach ($response->errors as $key => $message) {
                    $errors->add($key, $message);
                }
            }
        } catch (\Throwable $ex) {
            $errors->add("error", $ex->getMessage());
        }

        return back()->with('errors', $errors);
    }

    public function saveFunctions(Request $request, $id)
    {
        if(!(Session::get('level') >= 9)){
            return abort(403);
        }
        // dd($request->all());
        $errors = new MessageBag();
        $functions = $request->input('functions', []);

        // Validation: Each function must have type and name
        foreach ($functions as $index => $func) {
            if (empty($func['type']) || empty($func['name'])) {
                $errors->add("function_{$index}", "Type and Name are required for function #{$index}");
            }
            // Optional: validate name pattern
            if (!preg_match('/^[a-zA-Z0-9_]+$/', $func['name'])) {
                $errors->add("function_{$index}_name", "Function name must contain only letters, numbers, and underscores.");
            }
        }

        if ($errors->any()) {
            return back()->withInput()->with('errors', $errors);
        }

        // Prepare payload for backend API
        $payload = [
            'functions' => $functions,
            'user_id' => auth()->id(),
        ];

        $url = env('API_URL') . "prompts/{$id}/functions";
        try {
            $response = Helper::PostApi($url, $payload);
            if ($response->success) {
                return redirect()->route('prompts.edit', $id)->with('success', 'Functions saved successfully');
            } else {
                foreach ($response->errors as $key => $message) {
                    $errors->add($key, $message);
                }
            }
        } catch (\Throwable $ex) {
            $errors->add("error", $ex->getMessage());
        }

        foreach ($response->errors as $key => $message) {
            $errors->add($key, $message);
        }
        if ($errors->any()) {
            $errorString = implode(' | ', $errors->all());
            return back()->withInput()->with('error', $errorString);
        }
    }

    public function voicePreview(Request $request)
    {
        $text = $request->input('text');
        $voice = $request->input('voiceName', 'alloy');
        
        \Log::info("Voice Preview Request: Text=[$text], Voice=[$voice]");

        try {
            $client = new \GuzzleHttp\Client();
            $response = $client->post('https://api.openai.com/v1/audio/speech', [
                'headers' => [
                    'Authorization' => 'Bearer ' . env('OPENAI_API_KEY'),
                    'Content-Type' => 'application/json',
                ],
                'json' => [
                    'model' => 'gpt-4o-mini-tts',
                    'voice' => $voice,
                    'input' => $text,
                    'response_format' => 'mp3', // supported format
                ],
                // 'stream' => false, // Guzzle defaults to non-stream unless specified, but explicit is fine
            ]);

            $audioData = $response->getBody()->getContents();
            $audioBase64 = base64_encode($audioData);
            
            \Log::info("Voice Preview Success: Audio size=" . strlen($audioBase64));

            return response()->json([
                'success' => true,
                'audio' => $audioBase64,
                'format' => 'mp3',
            ]);
        } catch (\Exception $e) {
            \Log::error("Voice Preview Error: " . $e->getMessage());
            if ($e instanceof \GuzzleHttp\Exception\RequestException && $e->hasResponse()) {
                 \Log::error("Voice Preview API Response: " . (string) $e->getResponse()->getBody());
            }

            return response()->json([
                'success' => false,
                'message' => 'TTS generation failed',
                'error' => $e->getMessage(),
            ]);
        }
    }

    public function processVoiceInteraction(Request $request)
    {
        try {
            // 1. Validation
            $request->validate([
                'audio' => 'required|file',
                'system_prompt' => 'required|string',
                'history' => 'nullable|string', // JSON string
                'voice_name' => 'nullable|string'
            ]);

            $apiKey = env('OPENAI_API_KEY');
            if (!$apiKey) {
                return response()->json(['success' => false, 'message' => 'OpenAI API Key missing']);
            }

            // Helper for specific logging
            $logPath = storage_path('logs/voice_debug.log');
            $log = function($msg, $data = []) use ($logPath) {
                $line = "[" . now()->toDateTimeString() . "] [SERVER] " . $msg;
                if (!empty($data)) {
                    $line .= " | Data: " . json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
                }
                $line .= PHP_EOL;
                file_put_contents($logPath, $line, FILE_APPEND);
            };

            // 2. Handle Audio Upload (Temp File)
            $audioFile = $request->file('audio');
            $tempPath = $audioFile->getRealPath();
            $originalName = $audioFile->getClientOriginalName();
            
            $log("Voice Transaction - Audio Recieved", [
                'size_bytes' => $audioFile->getSize(), 
                'mime' => $audioFile->getMimeType(), 
                'original_name' => $originalName
            ]);

            // 3. STT: Whisper
            $client = new \GuzzleHttp\Client();
            $sttResponse = $client->post('https://api.openai.com/v1/audio/transcriptions', [
                'headers' => [
                    'Authorization' => 'Bearer ' . $apiKey,
                ],
                'multipart' => [
                    [
                        'name'     => 'file',
                        'contents' => fopen($tempPath, 'r'),
                        'filename' => 'audio.webm'
                    ],
                    [
                        'name'     => 'model',
                        'contents' => 'whisper-1'
                    ]
                ]
            ]);
            
            $sttData = json_decode($sttResponse->getBody(), true);
            $log("Voice Transaction - STT Raw Response", $sttData);
            
            $userText = $sttData['text'] ?? '';
            $log("Voice Transaction - User Said Final: " . $userText);

            if (empty($userText)) {
                return response()->json(['success' => false, 'message' => 'Could not transcribe audio.']);
            }

            // 4. Chat: GPT
            $systemPrompt = $request->input('system_prompt');
            $log("Voice Transaction - System Prompt", ['partial' => substr($systemPrompt, 0, 200)]);

            $history = json_decode($request->input('history', '[]'), true);
            if (!is_array($history)) $history = [];
            
            $log("Voice Transaction - Input History", $history);

            // Append User Message
            $history[] = ['role' => 'user', 'content' => $userText];

            // Prepare Messages for Chat (System + History)
            $messages = [];
            $messages[] = ['role' => 'system', 'content' => strip_tags($systemPrompt)];
            foreach ($history as $msg) {
                if (in_array($msg['role'], ['user', 'assistant', 'system'])) {
                   $messages[] = ['role' => $msg['role'], 'content' => $msg['content']];
                }
            }
            
            $log("Voice Transaction - LLM Request Payload", $messages);

            $chatResponse = $client->post('https://api.openai.com/v1/chat/completions', [
                 'headers' => [
                    'Authorization' => 'Bearer ' . $apiKey,
                    'Content-Type'  => 'application/json',
                ],
                'json' => [
                    'model' => 'gpt-4o-mini',  // Faster than gpt-4o
                    'messages' => $messages,
                    'max_tokens' => 150, 
                    'temperature' => 0.7,
                ]
            ]);

            $chatData = json_decode($chatResponse->getBody(), true);
            $log("Voice Transaction - LLM Raw Response", $chatData);
            
            $aiText = $chatData['choices'][0]['message']['content'] ?? 'I did not understand.';
            $log("Voice Transaction - AI Said Final: " . $aiText);
            
            // Append AI Message to History
            $history[] = ['role' => 'assistant', 'content' => $aiText];

            // 5. TTS: OpenAI Audio
            $voiceName = $request->input('voice_name', 'alloy');
            $validVoices = ['alloy', 'ash', 'ballad', 'coral', 'echo', 'sage', 'shimmer', 'verse'];
            if(!in_array($voiceName, $validVoices)) $voiceName = 'alloy';
            
            $log("Voice Transaction - Generating TTS", ['voice' => $voiceName]);

            $ttsResponse = $client->post('https://api.openai.com/v1/audio/speech', [
                'headers' => [
                    'Authorization' => 'Bearer ' . $apiKey,
                    'Content-Type' => 'application/json',
                ],
                'json' => [
                    'model' => 'tts-1',  // Faster than gpt-4o-mini-tts
                    'voice' => $voiceName,
                    'input' => $aiText,
                    'response_format' => 'mp3',
                    'speed' => 1.15,  // Slightly faster playback
                ],
                'stream' => false,
            ]);

            $audioContent = $ttsResponse->getBody()->getContents();
            $audioBase64 = base64_encode($audioContent);

            return response()->json([
                'success' => true,
                'audio' => $audioBase64,
                'history' => $history,
                'transcription' => $userText,
                'response_text' => $aiText
            ]);

        } catch (\Exception $e) {
            \Log::error("Voice Interaction Error: " . $e->getMessage());
             return response()->json([
                'success' => false,
                'message' => 'Processing failed: ' . $e->getMessage()
            ]);
        }
    }

    public function logClientEvent(Request $request)
    {
        $message = $request->input('message');
        $data = $request->input('data');
        $ip = $request->ip();
        $time = now()->toDateTimeString();

        $logLine = "[$time] [$ip] [CLIENT] $message";
        if($data){
             $logLine .= " | Data: " . json_encode($data);
        }
        $logLine .= PHP_EOL;

        // Append to storage/logs/voice_debug.log
        $path = storage_path('logs/voice_debug.log');
        file_put_contents($path, $logLine, FILE_APPEND);

        return response()->json(['success' => true]);
    }
}
