<?php

/*
|--------------------------------------------------------------------------
| OwnStore - Build your own online store
| Author: TakfeDev (MKJUEL)
| All Rights Reserved
|--------------------------------------------------------------------------
*/

namespace App\Services\Ai;

use App\Models\Setting;
use App\Services\AiService;
use Illuminate\Support\Facades\Log; 
use Exception;

class AiProductAssistant
{
    protected $aiService;

    public function __construct(AiService $aiService)
    {
        $this->aiService = $aiService;
    }

    public function processInstruction(array $history, array $currentData, array $referenceData = [])
    {
        // 1. Check if suggestions are enabled in Admin Panel
        $suggestionsEnabled = filter_var(Setting::where('key', 'ai_product_suggestions')->value('value') ?? true, FILTER_VALIDATE_BOOLEAN);

        $allowedKeysArray = [
            'title', 'description', 'price', 'stock', 'moq', 
            'shipping_time', 'delivery_via', 'refund_policy', 
            'coupon_code', 'discount_percentage', 'is_free_shipping',
            'category_id', 'subcategory_id', 'currency_code',
            'variations', 'customization_options', 'specifications'
        ];
        
        $allowedKeysString = implode(', ', $allowedKeysArray);
        $referenceJson = json_encode($referenceData);

        // 2. Fetch Dynamic Admin Prompt
        $basePrompt = Setting::where('key', 'ai_product_assistant_prompt')->value('value');
        if (empty(trim($basePrompt))) {
            $basePrompt = "You are a highly advanced eCommerce AI Co-Pilot for a B2B/B2C marketplace.\nYour job is to help the seller fill out the product creation form accurately.\nListen to the user's instructions and automatically update the relevant form fields.\n\nIf the user uploads a raw document (like a CSV, TXT, or JSON file) as part of their message, carefully extract all relevant product details from it (such as Title, Price, Description, Stock, etc.) and intelligently map them to the allowed form fields.\n\nRules:\n1. If the user asks a general question, provide the answer in 'reply' and leave 'updates' as an empty object {}.\n2. Ensure all HTML you generate for the 'description' field uses clean semantic tags (<h2>, <p>, <ul>, <li>).\n3. Do NOT invent data that isn't in the attached document unless explicitly asked to generate/write something.";
        }

        // 3. Conditionally build the Smart Suggestions instructions
        $suggestionInstruction = $suggestionsEnabled 
            ? "--- SMART SUGGESTIONS ---
            Based on the current form state or the user's last request, provide 1 to 5 short, actionable prompts the user could ask you next. 
            Keep them very brief (e.g. 'Generate a description', 'Set price to $50', 'Add size variations').
            If no suggestions make sense, return an empty array []."
            : "--- SMART SUGGESTIONS ---
            Do NOT provide any suggestions. Always return an empty array [] for the 'suggestions' field.";

        // 4. Append strict JSON and Formatting rules
        $systemPrompt = $basePrompt . "
        
        --- SYSTEM DATA CONTEXT ---
        CURRENT FORM STATE:
        " . json_encode($currentData) . "
        
        AVAILABLE REFERENCE DATA (Categories & Currencies):
        {$referenceJson}

        ALLOWED FIELDS YOU CAN UPDATE:
        [{$allowedKeysString}]

        --- TOKEN SAVING RULE (CRITICAL) ---
        ONLY return fields in the 'updates' object that actually need to change based on the user's request. 
        Return a delta update.

        --- COMPLEX FIELD INSTRUCTIONS ---
        - category_id & subcategory_id: Match the user's intent to the closest Category ID in the REFERENCE DATA. Return integers.
        - currency_code: Use the exact 'code' (e.g., USD, EUR) from REFERENCE DATA.
        - variations: Must be an array of objects. Format: [{\"name\": \"Color\", \"options\": [{\"value\": \"Red\", \"additional_price\": 0}]}]
        - customization_options: Must be an array of objects. Format: [{\"type\": \"Custom Logo\", \"moq\": \"100\"}]
        - specifications: Must be an array of objects. Format: [{\"name\": \"Material\", \"value\": \"100% Cotton\"}]

        {$suggestionInstruction}

        --- STRICT RESPONSE FORMAT (CRITICAL) ---
        YOU MUST OUTPUT ONLY VALID JSON. 
        DO NOT include any conversational text before or after the JSON.
        DO NOT use markdown formatting like ```json.
        Ensure all internal double quotes are properly escaped.

        {
            \"reply\": \"Your conversational response.\",
            \"updates\": {
                \"field_name\": \"new_value\"
            },
            \"suggestions\": []
        }";

        $messages = [['role' => 'system', 'content' => $systemPrompt]];
        
        foreach ($history as $msg) {
            $messages[] = ['role' => $msg['role'], 'content' => $msg['content']];
        }

        $rawResponse = $this->aiService->generateChat($messages);

        // --- EXTREME JSON EXTRACTION LOGIC ---
        // Find the first '{' and the last '}' to strip out any garbage text the AI might have added
        $start = strpos($rawResponse, '{');
        $end = strrpos($rawResponse, '}');

        if ($start !== false && $end !== false) {
            $cleanJsonString = substr($rawResponse, $start, $end - $start + 1);
        } else {
            $cleanJsonString = $rawResponse; // Fallback
        }

        $decoded = json_decode($cleanJsonString, true);

        if (json_last_error() !== JSON_ERROR_NONE) {
            // Log the raw response so we can see exactly what the AI messed up
            Log::error('AI JSON Parse Error: ' . json_last_error_msg());
            Log::error('Raw AI Output: ' . $rawResponse);
            throw new Exception("AI returned invalid data format. Please try again.");
        }

        // Security Filter
        if (isset($decoded['updates']) && is_array($decoded['updates'])) {
            $filteredUpdates = [];
            foreach ($decoded['updates'] as $key => $value) {
                if (in_array($key, $allowedKeysArray)) {
                    $filteredUpdates[$key] = $value;
                }
            }
            $decoded['updates'] = $filteredUpdates;
        } else {
            $decoded['updates'] = [];
        }

        // Ensure suggestions exists
        if (!$suggestionsEnabled) {
            $decoded['suggestions'] = [];
        } elseif (!isset($decoded['suggestions']) || !is_array($decoded['suggestions'])) {
            $decoded['suggestions'] = [];
        }

        return $decoded;
    }
}