<?php
if (!defined('ABSPATH')) {
    exit;
}

class VMO_Website_QA {
    private static $instance = null;
    private $wpdb;
    private $table_name;

    public static function get_instance() {
        if (self::$instance === null) {
            self::$instance = new self();
        }

        return self::$instance;
    }

    private function __construct() {
        global $wpdb;

        $this->wpdb = $wpdb;
        $this->table_name = $wpdb->prefix . 'vmo_website_qa_reports';

        add_action('init', array($this, 'ensure_schema'), 6);
    }

    private function prepare_long_running_runtime() {
        if (function_exists('set_time_limit')) {
            @set_time_limit(0);
        }
        if (function_exists('ignore_user_abort')) {
            @ignore_user_abort(true);
        }
        if (function_exists('ini_set')) {
            @ini_set('memory_limit', '512M');
        }
    }

    public function ensure_schema() {
        if (!function_exists('dbDelta')) {
            require_once ABSPATH . 'wp-admin/includes/upgrade.php';
        }

        $charset_collate = $this->wpdb->get_charset_collate();
        $sql = "CREATE TABLE IF NOT EXISTS {$this->table_name} (
            id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
            user_id BIGINT UNSIGNED NOT NULL,
            session_id VARCHAR(255) NOT NULL,
            draft_key VARCHAR(191) DEFAULT NULL,
            related_post_id BIGINT UNSIGNED DEFAULT NULL,
            score TINYINT UNSIGNED DEFAULT 0,
            publish_ready TINYINT(1) DEFAULT 0,
            report_json LONGTEXT NULL,
            created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
            PRIMARY KEY (id),
            KEY idx_user_id (user_id),
            KEY idx_session_id (session_id),
            KEY idx_draft_key (draft_key),
            KEY idx_related_post_id (related_post_id)
        ) {$charset_collate};";

        dbDelta($sql);
    }

    public function run_qa($user_id, $session_id, $website_payload, array $business_package = array(), array $context = array()) {
        $this->prepare_long_running_runtime();

        $user_id = (int) $user_id;
        $session_id = (string) $session_id;
        $pages = $this->extract_pages($website_payload);
        $combined_content = strtolower($this->build_combined_content($pages));
        $brief_bundle = function_exists('vmo_get_master_business_brief_service')
            ? vmo_get_master_business_brief_service()->get_active_brief($session_id, $user_id)
            : array();
        $brief = isset($brief_bundle['brief']) && is_array($brief_bundle['brief']) ? $brief_bundle['brief'] : array();
        $business_name = strtolower(trim((string) ($brief['business_identity']['business_name'] ?? ($business_package['business_overview']['business_name'] ?? ''))));

        $critical = array();
        $warnings = array();
        $required_pages = array('home', 'about', 'services', 'contact');
        $required_legal_docs = $this->resolve_required_legal_docs($brief, $business_package);

        foreach ($required_pages as $required_page) {
            if (!array_key_exists($required_page, $pages)) {
                $warnings[] = ucfirst($required_page) . ' page is missing from the generated website output.';
            }
        }

        if (empty($brief)) {
            $critical[] = 'Business brief is not locked yet, so publish readiness cannot be verified against a canonical business profile.';
        }

        if ($business_name !== '' && strpos($combined_content, $business_name) === false) {
            $warnings[] = 'The generated website content does not clearly mention the business name.';
        }

        if (preg_match('/lorem ipsum|your business|my business|sample text|replace this/i', $combined_content)) {
            $critical[] = 'Generic placeholder copy is still present in the website content.';
        }

        if (preg_match('/\[(generated_image|generated_video):/i', $combined_content)) {
            $critical[] = 'Raw media placeholders are still present. Media generation or replacement has not completed.';
        }

        if (preg_match('/placeholder\.com|picsum\.photos|example\.com|via\.placeholder/i', $combined_content)) {
            $critical[] = 'Placeholder media URLs are still present in the website output.';
        }

        $media_complete = !$this->contains_incomplete_media($combined_content);
        if (!$media_complete) {
            $critical[] = 'Media completeness check failed because unresolved generated-media markers remain.';
        }

        $legal_pages_present = true;
        $missing_legal_pages = array();
        foreach ($required_legal_docs as $doc_slug) {
            if (!$this->has_legal_page($pages, $combined_content, $doc_slug)) {
                $legal_pages_present = false;
                $missing_legal_pages[] = $doc_slug;
            }
        }
        if (!$legal_pages_present) {
            $critical[] = 'Required legal pages or embedded legal content are missing: ' . implode(', ', $missing_legal_pages) . '.';
        }

        $score = max(0, 100 - (count($critical) * 20) - (count($warnings) * 5));
        $publish_ready = empty($critical);
        $checklist = array(
            'business_brief_locked' => !empty($brief),
            'website_qa_passed' => $publish_ready,
            'required_legal_pages_present' => $legal_pages_present,
            'media_complete' => $media_complete,
        );

        // AI-powered QA evaluation using the strategic/pro website model tier.
        $ai_qa_report = $this->run_ai_qa_evaluation($pages, $business_name, $context);
        if (!empty($ai_qa_report)) {
            // Merge AI findings with regex findings
            if (isset($ai_qa_report['critical_issues']) && is_array($ai_qa_report['critical_issues'])) {
                foreach ($ai_qa_report['critical_issues'] as $ai_critical) {
                    $critical[] = '[AI QA] ' . $ai_critical;
                }
            }
            if (isset($ai_qa_report['improvements']) && is_array($ai_qa_report['improvements'])) {
                foreach ($ai_qa_report['improvements'] as $ai_improvement) {
                    $warnings[] = '[AI QA] ' . $ai_improvement;
                }
            }
            // Use AI overall score if available and it's lower than regex score
            if (isset($ai_qa_report['overall_score']) && is_numeric($ai_qa_report['overall_score'])) {
                $ai_score = (int) $ai_qa_report['overall_score'];
                $score = min($score, $ai_score);
            }
            $publish_ready = $publish_ready && !empty($ai_qa_report['publish_ready']);
            $checklist['ai_qa_passed'] = !empty($ai_qa_report['publish_ready']);
            $checklist['ai_qa_dimensions'] = $ai_qa_report['dimensions'] ?? array();
        }

        $report = array(
            'score' => $score,
            'publish_ready' => $publish_ready,
            'critical_findings' => $critical,
            'warnings' => $warnings,
            'checklist' => $checklist,
            'required_legal_docs' => $required_legal_docs,
            'page_count' => count($pages),
            'pages_detected' => array_keys($pages),
            'ai_qa_report' => $ai_qa_report,
            'summary' => $publish_ready
                ? 'Website QA passed (regex + AI). The draft is ready for explicit publish approval.'
                : 'Website QA found blocking issues that must be resolved before publishing.',
        );

        $this->wpdb->insert(
            $this->table_name,
            array(
                'user_id' => $user_id,
                'session_id' => $session_id,
                'draft_key' => isset($context['draft_key']) ? (string) $context['draft_key'] : '',
                'related_post_id' => isset($context['related_post_id']) ? (int) $context['related_post_id'] : 0,
                'score' => $score,
                'publish_ready' => $publish_ready ? 1 : 0,
                'report_json' => wp_json_encode($report),
                'created_at' => current_time('mysql'),
            ),
            array('%d', '%s', '%s', '%d', '%d', '%d', '%s', '%s')
        );

        $report['report_id'] = (int) $this->wpdb->insert_id;

        return $report;
    }

    public function get_latest_report($session_id, $draft_key = '', $related_post_id = 0) {
        $session_id = (string) $session_id;
        if ($session_id === '') {
            return array();
        }

        $sql = "SELECT * FROM {$this->table_name} WHERE session_id = %s";
        $params = array($session_id);
        if ($draft_key !== '') {
            $sql .= ' AND draft_key = %s';
            $params[] = $draft_key;
        }
        if ((int) $related_post_id > 0) {
            $sql .= ' AND related_post_id = %d';
            $params[] = (int) $related_post_id;
        }
        $sql .= ' ORDER BY id DESC LIMIT 1';

        $row = $this->wpdb->get_row($this->wpdb->prepare($sql, $params), ARRAY_A);
        if (!$row) {
            return array();
        }

        $report = json_decode($row['report_json'], true);
        if (!is_array($report)) {
            $report = array();
        }
        $report['report_id'] = (int) $row['id'];

        return $report;
    }

    private function extract_pages($website_payload) {
        $pages = array();

        if (is_string($website_payload)) {
            return array('home' => $website_payload);
        }

        if (!is_array($website_payload)) {
            return $pages;
        }

        if (!empty($website_payload['website_code']) && is_string($website_payload['website_code'])) {
            $pages['home'] = $website_payload['website_code'];
        }

        $candidate_maps = array(
            $website_payload['pages_map'] ?? null,
            $website_payload['pages_generated'] ?? null,
            $website_payload['pages'] ?? null,
        );

        foreach ($candidate_maps as $candidate_map) {
            if (!is_array($candidate_map)) {
                continue;
            }
            foreach ($candidate_map as $key => $value) {
                $slug = is_string($key) ? sanitize_title($key) : sanitize_title((string) ($value['title'] ?? $value['name'] ?? $key));
                if ($slug === '') {
                    $slug = 'page-' . count($pages);
                }
                $pages[$slug] = $this->page_to_string($value);
            }
        }

        if (!empty($website_payload['pages_created']) && is_array($website_payload['pages_created'])) {
            foreach ($website_payload['pages_created'] as $page_value) {
                if (is_string($page_value)) {
                    $pages[sanitize_title($page_value)] = $page_value;
                } elseif (is_array($page_value)) {
                    $slug = sanitize_title((string) ($page_value['slug'] ?? $page_value['title'] ?? $page_value['name'] ?? 'page-' . count($pages)));
                    $pages[$slug] = $this->page_to_string($page_value);
                }
            }
        }

        if (empty($pages) && !empty($website_payload['content']) && is_string($website_payload['content'])) {
            $pages['home'] = $website_payload['content'];
        }

        return $pages;
    }

    private function resolve_required_legal_docs(array $brief, array $business_package) {
        $docs = array();

        if (!empty($business_package['document_recommendations']['website_embedded_docs']) && is_array($business_package['document_recommendations']['website_embedded_docs'])) {
            $docs = $business_package['document_recommendations']['website_embedded_docs'];
        } elseif (!empty($business_package['website_embedded_docs']) && is_array($business_package['website_embedded_docs'])) {
            $docs = $business_package['website_embedded_docs'];
        } elseif (!empty($brief['legal_policy_requirements']) && is_array($brief['legal_policy_requirements'])) {
            $docs = $brief['legal_policy_requirements'];
        }

        return array_values(array_unique(array_filter(array_map('sanitize_title', $docs))));
    }

    private function has_legal_page(array $pages, $combined_content, $doc_slug) {
        $doc_slug = sanitize_title((string) $doc_slug);
        if ($doc_slug === '') {
            return true;
        }

        foreach ($pages as $page_slug => $page_content) {
            if (strpos($page_slug, $doc_slug) !== false) {
                return true;
            }
            if (strpos(strtolower($page_content), str_replace('-', ' ', $doc_slug)) !== false) {
                return true;
            }
        }

        return strpos($combined_content, str_replace('-', ' ', $doc_slug)) !== false;
    }

    private function contains_incomplete_media($combined_content) {
        return (bool) preg_match('/data-vmo-generate=|data-vmo-sora=|\[(generated_image|generated_video):/i', $combined_content);
    }

    private function build_combined_content(array $pages) {
        $content = '';
        foreach ($pages as $page_slug => $page_content) {
            $content .= "\n<!-- {$page_slug} -->\n" . $page_content;
        }

        return $content;
    }

    private function page_to_string($value) {
        if (is_string($value)) {
            return $value;
        }
        if (is_array($value)) {
            if (!empty($value['html']) && is_string($value['html'])) {
                return $value['html'];
            }
            if (!empty($value['content']) && is_string($value['content'])) {
                return $value['content'];
            }
            return wp_json_encode($value);
        }

        return '';
    }

    /* ═══════════════════════════════════════════════════════════════
     * AI-POWERED QA EVALUATION (v9.2.0)
    * Uses the strategic/pro website model tier to evaluate website quality
     * across 6 dimensions: design, motion, mobile, content, media, uniqueness.
     * ═══════════════════════════════════════════════════════════════ */

    /**
     * Run AI-powered QA evaluation on generated website.
     *
     * @param array  $pages         Extracted page HTML keyed by slug.
     * @param string $business_name The business name to verify.
     * @param array  $context       Optional context (design_mode, etc.)
     * @return array AI evaluation report or empty array on failure.
     */
    private function run_ai_qa_evaluation(array $pages, $business_name, array $context = array()) {
        $api_key = get_option('vmo_openai_api_key');
        if (empty($api_key) || empty($pages)) {
            return array();
        }

        // ✅ Token budget check: AI QA costs ~800 tokens
        $user_id = get_current_user_id();
        if (function_exists('vmo_deduct_tokens')) {
            $token_cost = function_exists('vmo_get_token_cost') ? (int) vmo_get_token_cost('ai_qa_evaluation') : 800;
            if (!vmo_deduct_tokens($user_id, $token_cost, 'ai_qa_evaluation', 'AI-powered website QA evaluation')) {
                error_log('VMO QA: Insufficient tokens for AI QA evaluation, skipping.');
                return array();
            }
        }

        // Build the evaluation prompt using the design system QA rubric
        $qa_rubric = '';
        if (class_exists('VMO_Elite_Consultation_Prompts')) {
            $qa_rubric = VMO_Elite_Consultation_Prompts::get_instance()->get_qa_standards_prompts();
        }

        // Truncate HTML to avoid token overrun (keep first 8000 chars per page, max 3 pages)
        $html_sample = '';
        $page_count = 0;
        foreach ($pages as $slug => $html) {
            if ($page_count >= 3) break;
            $html_sample .= "\n--- PAGE: {$slug} ---\n" . mb_substr((string) $html, 0, 8000);
            $page_count++;
        }

        $design_mode = $context['design_mode'] ?? 'unknown';

        $prompt = $qa_rubric;
        $prompt .= "\nBUSINESS NAME: " . ($business_name ?: '(unknown)');
        $prompt .= "\nDESIGN MODE: " . $design_mode;
        $prompt .= "\nTOTAL PAGES: " . count($pages);
        $prompt .= "\n\nWEBSITE HTML (sampled):\n" . $html_sample;
        $prompt .= "\n\nEvaluate the website according to the rubric above. Return ONLY valid JSON matching the specified output format.";

        $model = function_exists('vmo_get_model') ? vmo_get_model('pro') : 'gpt-5.5-pro';
        $token_param = function_exists('vmo_get_token_param')
            ? vmo_get_token_param($model, 1500)
            : array('max_completion_tokens' => 1500);

        $body = array_merge(array(
            'model'    => $model,
            'messages' => array(
                array('role' => 'system', 'content' => 'You are a Senior Website QA Architect. Evaluate the website and return ONLY valid JSON. No markdown fences, no explanation outside JSON.'),
                array('role' => 'user', 'content' => $prompt),
            ),
            'temperature' => 0.2,
        ), $token_param);

        $response = wp_remote_post('https://api.openai.com/v1/chat/completions', array(
            'headers' => array(
                'Authorization' => 'Bearer ' . $api_key,
                'Content-Type'  => 'application/json',
            ),
            'body'    => wp_json_encode($body),
            'timeout' => 60,
        ));

        if (is_wp_error($response) || wp_remote_retrieve_response_code($response) >= 400) {
            error_log('VMO QA: AI evaluation API call failed.');
            return array();
        }

        $resp_body = json_decode(wp_remote_retrieve_body($response), true);
        $content = trim($resp_body['choices'][0]['message']['content'] ?? '');

        // Strip markdown code fences if present
        $content = preg_replace('/^```(?:json)?\s*/i', '', $content);
        $content = preg_replace('/\s*```$/', '', $content);

        $ai_report = json_decode($content, true);
        if (!is_array($ai_report)) {
            error_log('VMO QA: AI QA returned non-JSON response: ' . mb_substr($content, 0, 200));
            return array();
        }

        error_log('VMO QA: AI evaluation complete. Score: ' . ($ai_report['overall_score'] ?? 'N/A'));

        return $ai_report;
    }
}

if (!function_exists('vmo_get_website_qa_service')) {
    function vmo_get_website_qa_service() {
        return VMO_Website_QA::get_instance();
    }
}
