<?php

namespace App\Http\Controllers;

use App\Model\Client\Prompt;
use App\Model\Client\PromptFunction;
use App\Model\Dids;
use App\Model\Client\SmsProviders;
use App\Model\Sms;
use App\Model\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Validator;
use Plivo\RestClient;
use Twilio\Rest\Client as TwilioClient;

class AiCallSmsController extends Controller
{
    /**
     * Send SMS from AI call trigger
     * Uses Redis cache to fetch prompt and function data
     *
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function sendSmsFromCall(Request $request)
    {
        // Log incoming request
        $this->logToFile('=== New SMS Request ===');
        $this->logToFile('Request Data: ' . json_encode($request->all()));
        $this->logToFile('IP: ' . $request->ip());
        
        Log::info('AI SMS from Call - Request received', [
            'payload' => $request->all(),
            'ip' => $request->ip()
        ]);

        // Validate request
        $validator = Validator::make($request->all(), [
            'key' => 'required',
            'function_name' => 'required|string',
            'number_to_send_sms' => 'required|numeric'
        ]);

        if ($validator->fails()) {
            $this->logToFile('ERROR: Validation failed - ' . json_encode($validator->errors()));
            
            Log::warning('AI SMS from Call - Validation failed', [
                'errors' => $validator->errors()
            ]);

            return response()->json([
                'success' => false,
                'message' => 'Validation failed',
                'errors' => $validator->errors()
            ], 400);
        }

        $key = $request->input('key');
        $functionName = $request->input('function_name');
        $numberToSendSms = $request->input('number_to_send_sms');

        try {
            // Step 1: Fetch all cache data from Redis
            $this->logToFile('Step 1: Fetching Redis cache data');
            
            Log::info('AI SMS from Call - Fetching cache data');
            $cacheList = externalRedisCacheList();

            if (empty($cacheList)) {
                $this->logToFile('ERROR: Redis cache is empty');
                
                Log::error('AI SMS from Call - Redis cache is empty');

                return response()->json([
                    'success' => false,
                    'message' => 'No cache data available'
                ], 404);
            }

            // Step 2: Find the cache entry by key
            if (!isset($cacheList[$key])) {
                $this->logToFile("ERROR: Cache key not found: {$key}");
                $this->logToFile('Available keys: ' . implode(', ', array_keys($cacheList)));
                
                Log::error('AI SMS from Call - Cache key not found', [
                    'key' => $key,
                    'available_keys' => array_keys($cacheList)
                ]);

                return response()->json([
                    'success' => false,
                    'message' => "Cache entry not found for key: {$key}"
                ], 404);
            }

            $cacheData = $cacheList[$key];
            
            $this->logToFile("Step 2: Cache entry found for key: {$key}");
            $this->logToFile('Has functions: ' . (isset($cacheData['functions']) && !empty($cacheData['functions']) ? 'Yes' : 'No'));

            Log::info('AI SMS from Call - Cache entry found', [
                'key' => $key,
                'has_functions' => isset($cacheData['functions']) && !empty($cacheData['functions'])
            ]);

            // Validate cache structure
            if (!isset($cacheData['functions']) || !is_array($cacheData['functions'])) {
                Log::error('AI SMS from Call - Invalid cache structure', [
                    'key' => $key,
                    'cache_data' => $cacheData
                ]);

                return response()->json([
                    'success' => false,
                    'message' => 'Invalid cache data structure'
                ], 500);
            }

            // Step 3: Find the SMS function with matching name
            $smsFunction = null;
            foreach ($cacheData['functions'] as $func) {
                if (
                    isset($func['type']) && $func['type'] === 'sms'
                    && isset($func['name']) && $func['name'] === $functionName
                ) {
                    $smsFunction = $func;
                    break;
                }
            }

            if (!$smsFunction) {
                Log::error('AI SMS from Call - SMS function not found', [
                    'key' => $key,
                    'function_name' => $functionName,
                    'available_functions' => array_map(function ($f) {
                        return ['type' => $f['type'] ?? null, 'name' => $f['name'] ?? null];
                    }, $cacheData['functions'])
                ]);

                return response()->json([
                    'success' => false,
                    'message' => "SMS function '{$functionName}' not found in cache"
                ], 404);
            }

            // Validate message content
            if (empty($smsFunction['message'])) {
                Log::error('AI SMS from Call - Message content missing', [
                    'key' => $key,
                    'function_name' => $functionName
                ]);

                return response()->json([
                    'success' => false,
                    'message' => 'SMS function does not have a message configured'
                ], 400);
            }

            // Step 4: Parse key to get client_id and prompt_id
            // Key format: client_campaign_lead_prompt
            $keyParts = explode('_', $key);
            if (count($keyParts) < 4) {
                $this->logToFile("ERROR: Invalid key format: {$key}");
                $this->logToFile('Expected format: client_campaign_lead_prompt');
                
                Log::error('AI SMS from Call - Invalid key format', [
                    'key' => $key,
                    'expected_format' => 'client_campaign_lead_prompt'
                ]);

                return response()->json([
                    'success' => false,
                    'message' => 'Invalid key format. Expected: client_campaign_lead_prompt'
                ], 400);
            }

            $clientId = $keyParts[0];
            $promptId = $keyParts[3];
            
            $this->logToFile("Step 4: Parsed - Client ID: {$clientId}, Prompt ID: {$promptId}");

            Log::info('AI SMS from Call - Parsed key', [
                'client_id' => $clientId,
                'prompt_id' => $promptId
            ]);

            // Step 5: Fetch DID number from prompt_functions table
            $promptFunction = PromptFunction::on("mysql_$clientId")
                ->where('prompt_id', $promptId)
                ->where('type', 'sms')
                ->where('name', $functionName)
                ->first();

            if (!$promptFunction || empty($promptFunction->did_number)) {
                Log::error('AI SMS from Call - DID number not found in prompt_functions', [
                    'client_id' => $clientId,
                    'prompt_id' => $promptId,
                    'function_name' => $functionName
                ]);

                return response()->json([
                    'success' => false,
                    'message' => 'DID number not configured for this SMS function'
                ], 400);
            }

            $didNumber = $promptFunction->did_number;
            
            $this->logToFile("Step 5: DID number fetched: {$didNumber}");

            Log::info('AI SMS from Call - DID number fetched', [
                'did_number' => $didNumber
            ]);

            // Step 6: Fetch voip_provider from did table
            $didRecord = Dids::on("mysql_$clientId")
                ->where('cli', $didNumber)
                ->first();

            if (!$didRecord || empty($didRecord->voip_provider)) {
                Log::error('AI SMS from Call - VoIP provider not found in did table', [
                    'did_number' => $didNumber
                ]);

                return response()->json([
                    'success' => false,
                    'message' => 'VoIP provider not configured for this DID'
                ], 400);
            }

            $voipProvider = $didRecord->voip_provider;
            
            $this->logToFile("Step 6: VoIP provider fetched: {$voipProvider}");

            Log::info('AI SMS from Call - VoIP provider fetched', [
                'voip_provider' => $voipProvider
            ]);

            // Step 7: Fetch SMS provider credentials from sms_providers table
            $smsProvider = SmsProviders::on("mysql_$clientId")
                ->where('provider', $voipProvider)
                ->where('status', '1')
                ->first();

            if (!$smsProvider) {
                Log::error('AI SMS from Call - SMS provider credentials not found', [
                    'voip_provider' => $voipProvider
                ]);

                return response()->json([
                    'success' => false,
                    'message' => "SMS provider '{$voipProvider}' not configured or inactive"
                ], 400);
            }

            $authId = $smsProvider->auth_id;
            $apiKey = $smsProvider->api_key;
            
            $this->logToFile("Step 7: Provider credentials fetched for: {$voipProvider}");
            $this->logToFile("Auth ID: {$authId}");

            Log::info('AI SMS from Call - Provider credentials fetched', [
                'provider' => $voipProvider,
                'auth_id' => $authId
            ]);

            // Step 8: Send SMS using provider-specific logic
            $this->logToFile("Step 8: Sending SMS via {$voipProvider}");
            $this->logToFile("From: {$didNumber}, To: {$numberToSendSms}");
            $this->logToFile("Message: " . substr($smsFunction['message'], 0, 50) . '...');
            
            $result = $this->sendSmsViaProvider(
                $voipProvider,
                $authId,
                $apiKey,
                $didNumber,
                $numberToSendSms,
                $smsFunction['message'],
                $clientId
            );
            
            $this->logToFile('=== Request Completed Successfully ===');
            $this->logToFile('');

            return $result;

        } catch (\Exception $e) {
            $this->logToFile('=== EXCEPTION OCCURRED ===');
            $this->logToFile('Error: ' . $e->getMessage());
            $this->logToFile('File: ' . $e->getFile() . ':' . $e->getLine());
            $this->logToFile('');
            
            Log::error('AI SMS from Call - Exception occurred', [
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString()
            ]);

            return response()->json([
                'success' => false,
                'message' => 'An error occurred while sending SMS',
                'error' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * Send SMS via specific provider
     * Logic adapted from Sms::sendSms()
     */
    private function sendSmsViaProvider($provider, $authId, $apiKey, $from, $to, $message, $clientId)
    {
        try {
            $responseId = null;

            switch ($provider) {
                case 'didforsale':
                    $responseId = $this->sendViaDIDForSale($authId, $apiKey, $from, $to, $message);
                    break;

                case 'plivo':
                    $responseId = $this->sendViaPlivo($authId, $apiKey, $from, $to, $message);
                    break;

                case 'telnyx':
                    $responseId = $this->sendViaTelnyx($apiKey, $from, $to, $message);
                    break;

                case 'twilio':
                    $responseId = $this->sendViaTwilio($authId, $apiKey, $from, $to, $message);
                    break;

                default:
                    Log::error('AI SMS from Call - Unsupported provider', [
                        'provider' => $provider
                    ]);
                    return response()->json([
                        'success' => false,
                        'message' => "Unsupported SMS provider: {$provider}"
                    ], 400);
            }

            if ($responseId) {
                Log::info('AI SMS from Call - SMS sent successfully', [
                    'provider' => $provider,
                    'from' => $from,
                    'to' => $to,
                    'response_id' => $responseId
                ]);

                return response()->json([
                    'success' => true,
                    'message' => 'SMS sent successfully',
                    'data' => [
                        'from' => $from,
                        'to' => $to,
                        'provider' => $provider,
                        'response_id' => $responseId
                    ]
                ], 200);
            }

            return response()->json([
                'success' => false,
                'message' => 'Failed to send SMS'
            ], 500);

        } catch (\Exception $e) {
            Log::error('AI SMS from Call - Provider send failed', [
                'provider' => $provider,
                'error' => $e->getMessage()
            ]);

            return response()->json([
                'success' => false,
                'message' => 'Failed to send SMS via provider',
                'error' => $e->getMessage()
            ], 500);
        }
    }

    private function sendViaDIDForSale($authId, $apiKey, $from, $to, $message)
    {
        $url = "https://api.didforsale.com/didforsaleapi/index.php/api/V4/SMS/SingleSend";

        $data = [
            'to' => $to,
            'from' => $from,
            'text' => $message
        ];

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            "Content-Type: application/json",
            "Authorization: Basic " . base64_encode("$authId:$apiKey")
        ]);

        $result = curl_exec($ch);
        curl_close($ch);

        $response = json_decode($result);

        if (isset($response->status) && $response->status == 'true') {
            return $response->message ?? 'success';
        }

        throw new \Exception($response->message ?? 'DIDForSale API failed');
    }

    private function sendViaPlivo($authId, $apiKey, $from, $to, $message)
    {
        $client = new RestClient($authId, $apiKey);

        // Check if SMS is enabled
        $numberResponse = $client->numbers->get($from);

        if (isset($numberResponse->properties)) {
            $numberDetails = $numberResponse->properties;
            $isSmsEnabled = $numberDetails['smsEnabled'] ?? ($numberDetails['sms_enabled'] ?? false);

            if (!$isSmsEnabled) {
                throw new \Exception("Please enable SMS on number {$from} before sending");
            }
        }

        // Send SMS
        $result = $client->messages->create([
            "src" => $from,
            "dst" => $to,
            "text" => $message
        ]);

        if ((is_object($result) && isset($result->statusCode) && $result->statusCode == 202)
            || (is_array($result) && isset($result['message_uuid']))) {
            return $result->message_uuid ?? 'success';
        }

        throw new \Exception('Plivo SMS sending failed');
    }

    private function sendViaTelnyx($apiKey, $from, $to, $message)
    {
        $url = 'https://api.telnyx.com/v2/messages';

        $data = [
            'from' => '+' . $from,
            'to' => '+' . $to,
            'text' => $message
        ];

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            'Content-Type: application/json',
            'Authorization: Bearer ' . $apiKey,
        ]);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));

        $response = curl_exec($ch);
        curl_close($ch);

        $jsonResponse = json_decode($response);

        if (isset($jsonResponse->data->id)) {
            return $jsonResponse->data->id;
        }

        throw new \Exception('Telnyx SMS sending failed');
    }

    private function sendViaTwilio($authId, $apiKey, $from, $to, $message)
    {
        $client = new TwilioClient($authId, $apiKey);

        // Check if SMS is enabled
        $incomingPhoneNumber = $client->incomingPhoneNumbers
            ->read(["phoneNumber" => $from], 1);

        if (!empty($incomingPhoneNumber)) {
            $capabilities = $incomingPhoneNumber[0]->capabilities;

            if ($capabilities->sms !== true) {
                throw new \Exception("Please enable SMS on number {$from} before sending");
            }
        } else {
            throw new \Exception("Number {$from} not found in your Twilio account");
        }

        // Send SMS
        $response = $client->messages->create(
            $to,
            [
                'from' => '+' . $from,
                'to' => $to,
                'body' => $message
            ]
        );

        return $response->sid;
    }

    /**
     * Log messages to a dedicated file for easier debugging
     * Similar to EmailWebhookController logging approach
     */
    private function logToFile($message)
    {
        $logFile = storage_path('app/ai_sms_call.log');
        $timestamp = date('Y-m-d H:i:s');
        $logMessage = "[{$timestamp}] {$message}\n";
        file_put_contents($logFile, $logMessage, FILE_APPEND);
    }
}
