<?php

namespace Core\App\Services;

/**
 * AI Landing Page Service
 * Uses the active AI provider (from ai_settings table) to generate
 * and iteratively update landing page HTML via conversation.
 */
class AiLandingPageService
{
    private AiService $ai;

    public function __construct(?AiService $ai = null)
    {
        $this->ai = $ai ?: AiService::fromActiveProvider();
    }

    /* =====================================================
       Generate or update landing page from conversation
       $messages = [{role: 'user'|'assistant', content: '...'}]
    ===================================================== */
    public function generateFromConversation(
        array   $product,
        array   $messages,
        ?string $existingHtml = null
    ): string {
        $systemPrompt = $this->buildSystemPrompt($product, $existingHtml);
        $userPrompt   = $this->buildConversationPrompt($messages, $existingHtml);

        $html = $this->ai->generate($userPrompt, [
            'system'     => $systemPrompt,
            'max_tokens' => 8000,
        ]);

        // Extract HTML block if AI wrapped it in markdown code fences
        return $this->extractHtml($html);
    }

    public function generateFromStructure(array $product, array $structure, array $context = []): string
    {
        $existingHtml = $context['existing_html'] ?? null;
        $systemPrompt = $this->buildSystemPrompt($product, is_string($existingHtml) ? $existingHtml : null);
        $planJson = !empty($context['plan']) ? json_encode($context['plan'], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) : '{}';
        $structureJson = json_encode($structure, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
        $conceptsJson = !empty($context['concepts']) ? json_encode($context['concepts'], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) : '[]';
        $sectionBlueprintJson = !empty($context['section_blueprint']) ? json_encode($context['section_blueprint'], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) : '{}';
        $scorecardJson = !empty($context['scorecard']) ? json_encode($context['scorecard'], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) : '{}';
        $selectedConcept = trim((string)($context['selected_concept'] ?? ''));
        $lockedSectionsJson = !empty($context['locked_sections']) ? json_encode($context['locked_sections'], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) : '[]';
        $variantLabel = trim((string)($context['variant_label'] ?? ''));

        $prompt = <<<PROMPT
You are generating a commercially usable landing page from structured analysis.

Build plan:
{$planJson}

Structure JSON:
{$structureJson}

Concepts JSON:
{$conceptsJson}

Section blueprint JSON:
{$sectionBlueprintJson}

Scorecard JSON:
{$scorecardJson}

Selected concept:
{$selectedConcept}

Locked sections:
{$lockedSectionsJson}

Variant label:
{$variantLabel}

Instructions:
- Respect the section order and section types from the structure.
- Preserve the screenshot-inspired colors, spacing mood, CTA style, and hierarchy.
- Improve weak copy while keeping the same conversion intent.
- Add a strong hero, benefits, trust signals, FAQ if present, and a closing CTA.
- If a checkout/order section exists, use the real iframe placeholder {{ORDER_FORM}} and buttons with data-lp-order="1".
- Any section listed as locked must keep its role, intention, and key text stable. You may polish formatting but do not rewrite it radically.
- Output the final complete HTML document only.
PROMPT;

        $html = $this->ai->generate($prompt, [
            'system' => $systemPrompt,
            'max_tokens' => 8000,
            'temperature' => 0.45,
        ]);

        return $this->extractHtml($html);
    }

    public function evaluateGeneratedHtml(array $product, array $structure, string $html): array
    {
        $prompt = <<<PROMPT
Evaluate this landing page against the intended structure and conversion quality.
Return JSON only:
{
  "score": 0,
  "issues": ["string"],
  "strengths": ["string"],
  "improvements": ["string"]
}

Product:
{$this->json($product)}

Structure:
{$this->json($structure)}

HTML:
{$html}
PROMPT;

        return $this->ai->generateJson($prompt, [
            'max_tokens' => 1400,
            'temperature' => 0.2,
        ]);
    }

    public function improveGeneratedHtml(
        array $product,
        array $structure,
        string $html,
        array $evaluation,
        array $plan = []
    ): string {
        $systemPrompt = $this->buildSystemPrompt($product, $html);
        $prompt = <<<PROMPT
Improve the following landing page HTML using the evaluation report and build plan.
Keep the same overall identity, but fix weak sections, incomplete CTAs, structure mismatches, or missing conversion elements.

Build plan:
{$this->json($plan)}

Structure:
{$this->json($structure)}

Evaluation:
{$this->json($evaluation)}

Current HTML:
{$html}

Output the improved full HTML document only.
PROMPT;

        $improved = $this->ai->generate($prompt, [
            'system' => $systemPrompt,
            'max_tokens' => 8000,
            'temperature' => 0.35,
        ]);

        return $this->extractHtml($improved);
    }

    /* =====================================================
       System prompt — shapes AI behaviour
    ===================================================== */
    private function buildSystemPrompt(array $product, ?string $existingHtml): string
    {
        $productName  = htmlspecialchars($product['title'] ?? $product['name'] ?? 'Product', ENT_QUOTES, 'UTF-8');
        $productDesc  = strip_tags((string)($product['short_description'] ?? $product['description'] ?? ''));
        $productPrice = (string)($product['sale_price'] ?? $product['price'] ?? '');
        $currency     = (string)($product['currency'] ?? 'DZD');

        $dialectLine = $this->ai->buildDialectInstruction('ar');

        $context = $existingHtml
            ? "You are currently modifying an existing landing page. The user will give you instructions and you must apply them to produce an improved full page."
            : "You are building a new landing page from scratch.";

        return <<<PROMPT
{$dialectLine}

You are an expert conversion-rate optimisation specialist and front-end developer.
Your job is to write complete, standalone, production-ready HTML landing pages.

{$context}

Product Information:
- Name: {$productName}
- Description: {$productDesc}
- Price: {$productPrice} {$currency}

Rules:
1. Always output a COMPLETE, valid HTML document (<!DOCTYPE html> ... </html>).
2. Include all CSS inline in a <style> tag inside <head> — no external CSS files.
3. Use modern, clean design: strong hero, benefits, CTA, social proof, FAQ.
4. Optimise every element for CONVERSION (clear CTAs, urgency, trust signals).
5. Make the page fully responsive (mobile-first).
6. Arabic RTL support: if product name or description contains Arabic, set dir="rtl" lang="ar".
7. Do NOT include any JavaScript that could be a security risk.
8. Output ONLY the raw HTML — no markdown, no explanations, no code fences.
9. For ALL "Order Now" / "اطلب الآن" / CTA buttons that should trigger the order form, add the attribute data-lp-order="1".
10. To embed a REAL connected order form (when user requests "order box" / "صندوق الطلب" / "نموذج الطلب"), NEVER build a fake/custom HTML form manually.
    ALWAYS use this exact iframe inside a dedicated section such as <section id="lp-order-section"> ... </section>, and ALWAYS pass the theme and accent color matching the page design:
    <iframe src="{{ORDER_FORM}}?theme=dark&color=%23f59e0b" data-lp-order-frame="1" style="width:100%;min-height:760px;border:none;border-radius:16px;" loading="lazy" title="Order Form" sandbox="allow-forms allow-scripts allow-same-origin"></iframe>

    ORDER FORM URL PARAMETERS — always match the page design:
    a) theme=dark  → dark background form (for dark landing pages)
       theme=light → white background form (for light landing pages)
    b) color=%23RRGGBB → accent/CTA color (URL-encoded hex). Always extract the dominant CTA color from the landing page and encode it.
       Examples: orange=%23f59e0b, blue=%232563eb, green=%2310b981, purple=%238b5cf6, red=%23e11d48
    c) hide=FIELD,FIELD → comma-separated list of fields to remove from the form.
       Supported values: city, wilaya, address, qty, shipping
       Example: hide=city,address  (removes commune/city and address fields)
       Example: hide=wilaya,city   (removes both state and city — fastest checkout)
       Use hide= ONLY when the user explicitly asks to remove a field (e.g. "no city", "remove address", "بدون البلدية", "بدون الولاية").

    Full example (dark page, orange CTA, no city field):
    src="{{ORDER_FORM}}?theme=dark&color=%23f59e0b&hide=city"

    Full example (light page, blue CTA, fastest checkout — name+phone only):
    src="{{ORDER_FORM}}?theme=light&color=%232563eb&hide=wilaya,city,address,shipping"

11. Keep brand colours neutral unless the user specifies colours.
12. All images should use placeholder URLs: https://placehold.co/WxH/format.
PROMPT;
    }

    /* =====================================================
       Build the prompt from conversation history
    ===================================================== */
    private function buildConversationPrompt(array $messages, ?string $existingHtml): string
    {
        if (empty($messages)) {
            return 'Generate a complete, high-converting landing page for this product.';
        }

        // For providers that support multi-turn via a single prompt string:
        // Build a transcript so the AI understands the full context
        $transcript = '';

        if ($existingHtml) {
            $transcript .= "=== CURRENT LANDING PAGE HTML ===\n";
            $transcript .= $existingHtml . "\n\n";
            $transcript .= "=== CONVERSATION HISTORY ===\n";
        }

        foreach ($messages as $msg) {
            $role    = strtoupper($msg['role'] ?? 'USER');
            $content = $msg['content'] ?? '';
            $transcript .= "[{$role}]: {$content}\n";
        }

        $transcript .= "\nBased on the above conversation, produce the complete updated HTML landing page now.";

        return $transcript;
    }

    /* =====================================================
       Extract clean HTML from AI response
    ===================================================== */
    private function extractHtml(string $raw): string
    {
        $raw = trim(preg_replace('/^\xEF\xBB\xBF/u', '', $raw));

        if (preg_match('/```(?:html)?\s*([\s\S]+?)\s*```/i', $raw, $m)) {
            $raw = trim($m[1]);
        }

        if (preg_match('/(?:<!DOCTYPE\s+html[^>]*>|<html\b)/i', $raw, $m, PREG_OFFSET_CAPTURE)) {
            $raw = ltrim(substr($raw, $m[0][1]));
        }

        if (preg_match('/<\/html\s*>/i', $raw, $m, PREG_OFFSET_CAPTURE)) {
            $raw = substr($raw, 0, $m[0][1] + strlen($m[0][0]));
        }

        if (stripos($raw, '<html') === false) {
            $raw = '<!DOCTYPE html><html lang="ar" dir="rtl"><head>'
                . '<meta charset="UTF-8">'
                . '<meta name="viewport" content="width=device-width,initial-scale=1">'
                . '</head><body>' . $raw . '</body></html>';
        } elseif (stripos($raw, '<!doctype') === false) {
            $raw = '<!DOCTYPE html>\n' . $raw;
        }

        $normalized = $this->normalizeHtmlDocument($raw);
        return $normalized ?: $raw;
    }

    private function normalizeHtmlDocument(string $html): string
    {
        if (!class_exists('\DOMDocument')) {
            return trim($html);
        }

        $previous = libxml_use_internal_errors(true);
        try {
            $dom = new \DOMDocument('1.0', 'UTF-8');
            $dom->preserveWhiteSpace = false;
            $dom->formatOutput = false;

            $wrapped = mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8');
            if (!@$dom->loadHTML($wrapped, LIBXML_NOWARNING | LIBXML_NOERROR)) {
                return trim($html);
            }

            $htmlNode = $dom->getElementsByTagName('html')->item(0);
            if ($htmlNode instanceof \DOMElement) {
                if (!$htmlNode->hasAttribute('lang')) {
                    $htmlNode->setAttribute('lang', 'ar');
                }
                if (!$htmlNode->hasAttribute('dir')) {
                    $htmlNode->setAttribute('dir', 'rtl');
                }
            }

            $output = trim($dom->saveHTML());
            if ($output !== '' && stripos($output, '<!doctype') === false) {
                $output = '<!DOCTYPE html>\n' . $output;
            }
            return $output;
        } catch (\Throwable $e) {
            return trim($html);
        } finally {
            libxml_clear_errors();
            libxml_use_internal_errors($previous);
        }
    }

    private function json(array $data): string
    {
        return json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
    }
}
