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

/**
 * VMO Website Scanner Service
 * 
 * Provides the ability to fetch, analyze, and extract content from external URLs.
 * Used for:
 * - Analyzing reference/inspiration websites during consultation
 * - Scanning existing user websites for integration
 * - Website cloning functionality (UI/UX replication)
 * - Competitor website analysis
 * 
 * @package VMO_AI_Website_Builder
 * @since 1.0.0
 */

if (!defined('ABSPATH')) exit;

class VMO_Website_Scanner {
    
    private $api_key;
    private static $instance = null;
    
    /**
     * Get singleton instance
     */
    public static function get_instance() {
        if (null === self::$instance) {
            self::$instance = new self();
        }
        return self::$instance;
    }
    
    /**
     * Constructor
     */
    private function __construct() {
        $this->api_key = get_option('vmo_openai_api_key');
        
        // Register AJAX endpoints
        add_action('wp_ajax_vmo_scan_website', array($this, 'ajax_scan_website'));
        add_action('wp_ajax_vmo_analyze_website', array($this, 'ajax_analyze_website'));
        add_action('wp_ajax_vmo_clone_website_structure', array($this, 'ajax_clone_website_structure'));
        add_action('wp_ajax_vmo_fetch_url_content', array($this, 'ajax_fetch_url_content'));
    }
    
    /**
     * Fetch raw HTML content from a URL
     * 
     * @param string $url The URL to fetch
     * @return array|WP_Error Response array with content or error
     */
    public function fetch_url($url) {
        $url = esc_url_raw($url);
        
        if (empty($url)) {
            return new WP_Error('invalid_url', 'Invalid or empty URL provided');
        }
        
        // Validate URL scheme
        $parsed = parse_url($url);
        if (!isset($parsed['scheme']) || !in_array($parsed['scheme'], ['http', 'https'])) {
            return new WP_Error('invalid_scheme', 'URL must use http or https');
        }
        
        // Set up request with browser-like headers
        $args = array(
            'timeout'     => 30,
            'redirection' => 5,
            'httpversion' => '1.1',
            'user-agent'  => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
            'headers'     => array(
                'Accept'          => 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
                'Accept-Language' => 'en-US,en;q=0.5',
                'Accept-Encoding' => 'gzip, deflate',
                'Connection'      => 'keep-alive',
            ),
            'sslverify'   => true,
        );
        
        $response = wp_remote_get($url, $args);
        
        if (is_wp_error($response)) {
            error_log('VMO Website Scanner: Failed to fetch URL - ' . $response->get_error_message());
            return $response;
        }
        
        $status_code = wp_remote_retrieve_response_code($response);
        if ($status_code !== 200) {
            return new WP_Error('http_error', "HTTP Error: {$status_code}");
        }
        
        $body = wp_remote_retrieve_body($response);
        $content_type = wp_remote_retrieve_header($response, 'content-type');
        
        return array(
            'url'          => $url,
            'status_code'  => $status_code,
            'content_type' => $content_type,
            'html'         => $body,
            'fetched_at'   => current_time('mysql'),
        );
    }
    
    /**
     * Extract structured content from HTML
     * 
     * @param string $html Raw HTML content
     * @return array Extracted content structure
     */
    public function extract_content($html) {
        if (empty($html)) {
            return array();
        }
        
        // Suppress HTML parsing warnings
        libxml_use_internal_errors(true);
        
        $doc = new DOMDocument();
        $doc->loadHTML('<?xml encoding="UTF-8">' . $html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
        
        $xpath = new DOMXPath($doc);
        
        $extracted = array(
            'title'       => '',
            'meta'        => array(),
            'headings'    => array(),
            'paragraphs'  => array(),
            'links'       => array(),
            'images'      => array(),
            'navigation'  => array(),
            'sections'    => array(),
            'footer'      => '',
            'text_content' => '',
        );
        
        // Extract title
        $title_nodes = $xpath->query('//title');
        if ($title_nodes->length > 0) {
            $extracted['title'] = trim($title_nodes->item(0)->textContent);
        }
        
        // Extract meta tags
        $meta_nodes = $xpath->query('//meta[@name or @property]');
        foreach ($meta_nodes as $meta) {
            $name = $meta->getAttribute('name') ?: $meta->getAttribute('property');
            $content = $meta->getAttribute('content');
            if ($name && $content) {
                $extracted['meta'][$name] = $content;
            }
        }
        
        // Extract headings (h1-h6)
        for ($i = 1; $i <= 6; $i++) {
            $heading_nodes = $xpath->query("//h{$i}");
            foreach ($heading_nodes as $heading) {
                $text = trim($heading->textContent);
                if (!empty($text)) {
                    $extracted['headings'][] = array(
                        'level' => $i,
                        'text'  => $text,
                    );
                }
            }
        }
        
        // Extract paragraphs
        $p_nodes = $xpath->query('//p');
        foreach ($p_nodes as $p) {
            $text = trim($p->textContent);
            if (!empty($text) && strlen($text) > 20) {
                $extracted['paragraphs'][] = $text;
            }
        }
        
        // Extract navigation links
        $nav_nodes = $xpath->query('//nav//a | //header//a');
        foreach ($nav_nodes as $link) {
            $href = $link->getAttribute('href');
            $text = trim($link->textContent);
            if (!empty($text) && !empty($href)) {
                $extracted['navigation'][] = array(
                    'text' => $text,
                    'href' => $href,
                );
            }
        }
        
        // Extract all links
        $link_nodes = $xpath->query('//a[@href]');
        foreach ($link_nodes as $link) {
            $href = $link->getAttribute('href');
            $text = trim($link->textContent);
            if (!empty($href)) {
                $extracted['links'][] = array(
                    'text' => $text ?: '[No text]',
                    'href' => $href,
                );
            }
        }
        
        // Extract images
        $img_nodes = $xpath->query('//img[@src]');
        foreach ($img_nodes as $img) {
            $src = $img->getAttribute('src');
            $alt = $img->getAttribute('alt');
            if (!empty($src)) {
                $extracted['images'][] = array(
                    'src' => $src,
                    'alt' => $alt ?: '',
                );
            }
        }
        
        // Extract sections
        $section_nodes = $xpath->query('//section | //article | //div[contains(@class, "section")]');
        foreach ($section_nodes as $section) {
            $id = $section->getAttribute('id');
            $class = $section->getAttribute('class');
            $text = trim($section->textContent);
            
            if (!empty($text) && strlen($text) > 50) {
                $extracted['sections'][] = array(
                    'id'    => $id,
                    'class' => $class,
                    'text'  => substr($text, 0, 500) . (strlen($text) > 500 ? '...' : ''),
                );
            }
        }
        
        // Extract footer
        $footer_nodes = $xpath->query('//footer');
        if ($footer_nodes->length > 0) {
            $extracted['footer'] = trim($footer_nodes->item(0)->textContent);
        }
        
        // Get all visible text content
        $body_nodes = $xpath->query('//body');
        if ($body_nodes->length > 0) {
            $extracted['text_content'] = $this->clean_text($body_nodes->item(0)->textContent);
        }
        
        libxml_clear_errors();
        
        return $extracted;
    }
    
    /**
     * Clean and normalize text content
     */
    private function clean_text($text) {
        // Remove excessive whitespace
        $text = preg_replace('/\s+/', ' ', $text);
        // Remove script/style content remnants
        $text = preg_replace('/<script[^>]*>.*?<\/script>/is', '', $text);
        $text = preg_replace('/<style[^>]*>.*?<\/style>/is', '', $text);
        // Trim
        $text = trim($text);
        return $text;
    }
    
    /**
     * Extract CSS styles from HTML (for cloning)
     * 
     * @param string $html Raw HTML content
     * @param string $base_url Base URL for resolving relative paths
     * @return array CSS information
     */
    public function extract_styles($html, $base_url) {
        libxml_use_internal_errors(true);
        
        $doc = new DOMDocument();
        $doc->loadHTML('<?xml encoding="UTF-8">' . $html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
        
        $xpath = new DOMXPath($doc);
        
        $styles = array(
            'external_stylesheets' => array(),
            'inline_styles'        => array(),
            'colors'               => array(),
            'fonts'                => array(),
        );
        
        // Extract external stylesheets
        $link_nodes = $xpath->query('//link[@rel="stylesheet"]');
        foreach ($link_nodes as $link) {
            $href = $link->getAttribute('href');
            if (!empty($href)) {
                // Resolve relative URLs
                if (strpos($href, '//') === false && strpos($href, 'http') !== 0) {
                    $href = rtrim($base_url, '/') . '/' . ltrim($href, '/');
                }
                $styles['external_stylesheets'][] = $href;
            }
        }
        
        // Extract inline styles
        $style_nodes = $xpath->query('//style');
        foreach ($style_nodes as $style) {
            $css_content = $style->textContent;
            if (!empty($css_content)) {
                $styles['inline_styles'][] = $css_content;
                
                // Extract colors
                preg_match_all('/#[0-9a-fA-F]{3,8}|rgb\([^)]+\)|rgba\([^)]+\)/i', $css_content, $color_matches);
                if (!empty($color_matches[0])) {
                    $styles['colors'] = array_merge($styles['colors'], $color_matches[0]);
                }
                
                // Extract fonts
                preg_match_all('/font-family:\s*([^;]+);/i', $css_content, $font_matches);
                if (!empty($font_matches[1])) {
                    $styles['fonts'] = array_merge($styles['fonts'], $font_matches[1]);
                }
            }
        }
        
        // Deduplicate
        $styles['colors'] = array_unique($styles['colors']);
        $styles['fonts'] = array_unique($styles['fonts']);
        
        libxml_clear_errors();
        
        return $styles;
    }
    
    /**
     * Use AI to analyze website content and structure
     * 
     * @param array $extracted_content Extracted content from extract_content()
     * @param string $purpose The purpose of analysis (e.g., 'clone', 'inspiration', 'competitor')
     * @return array AI analysis results
     */
    public function analyze_with_ai($extracted_content, $purpose = 'analysis') {
        if (empty($this->api_key)) {
            return array('error' => 'OpenAI API key not configured');
        }
        
        // ✅ TOKEN DEDUCTION v8.1.0: Charge for website analysis AI call
        $user_id = get_current_user_id();
        if (function_exists('vmo_deduct_tokens')) {
            if (!vmo_deduct_tokens($user_id, 400, 'website_analysis', 'Website AI analysis')) {
                return array('error' => 'Insufficient tokens. Please top up your balance.');
            }
        }
        
        // Build analysis prompt based on purpose
        $content_summary = wp_json_encode(array(
            'title'       => $extracted_content['title'] ?? '',
            'meta'        => array_slice($extracted_content['meta'] ?? array(), 0, 10),
            'headings'    => array_slice($extracted_content['headings'] ?? array(), 0, 20),
            'navigation'  => array_slice($extracted_content['navigation'] ?? array(), 0, 15),
            'paragraphs'  => array_slice($extracted_content['paragraphs'] ?? array(), 0, 10),
            'images'      => count($extracted_content['images'] ?? array()),
            'sections'    => count($extracted_content['sections'] ?? array()),
        ), JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
        
        $purpose_instructions = array(
            'clone' => 'Analyze this website for CLONING purposes. Identify the exact structure, layout patterns, color scheme, typography, and UI components so we can recreate a similar design.',
            'inspiration' => 'Analyze this website for INSPIRATION. Identify design elements, UX patterns, and features that could be adapted for a different business.',
            'competitor' => 'Analyze this website as a COMPETITOR. Identify their strengths, weaknesses, unique value propositions, pricing strategies, and areas where they can be outperformed.',
            'reference' => 'Analyze this website as a REFERENCE for the user. Extract all relevant business information, services, features, and content that should be preserved or enhanced.',
            'analysis' => 'Provide a comprehensive analysis of this website including structure, content strategy, UX/UI patterns, and overall effectiveness.',
        );
        
        $instruction = $purpose_instructions[$purpose] ?? $purpose_instructions['analysis'];
        
        $system_prompt = "You are VMO's Website Analysis AI. {$instruction}

Return a JSON object with:
- business_type: The type of business (e.g., 'SaaS', 'E-commerce', 'Service Provider')
- value_proposition: Main value proposition
- target_audience: Who the site is targeting
- key_features: Array of main features/services offered
- design_analysis: Object with layout_type, color_scheme, typography_style, ui_components
- content_strategy: How content is organized and presented
- call_to_actions: Main CTAs on the site
- strengths: Array of website strengths
- weaknesses: Array of areas for improvement
- clone_blueprint: (if purpose is clone) Detailed structure for replication
- recommendations: Array of actionable insights";

        $messages = array(
            array('role' => 'system', 'content' => $system_prompt),
            array('role' => 'user', 'content' => "Analyze this website content:\n\n{$content_summary}"),
        );
        
        $payload = array(
            'model' => defined('VMO_OPENAI_MODEL') ? VMO_OPENAI_MODEL : 'gpt-5.2-2025-12-11',
            'messages' => $messages,
            'max_completion_tokens' => 2000,
            'temperature' => 0.3,
        );
        
        $response = wp_remote_post('https://api.openai.com/v1/chat/completions', array(
            'headers' => array(
                'Authorization' => 'Bearer ' . $this->api_key,
                'Content-Type'  => 'application/json',
            ),
            'body'    => wp_json_encode($payload),
            'timeout' => 60,
        ));
        
        // Fallback to gpt-4o if primary fails
        if (is_wp_error($response) || wp_remote_retrieve_response_code($response) >= 400) {
            error_log('VMO Website Scanner: Primary model failed. Retrying with gpt-4o.');
            $payload['model'] = 'gpt-4o';
            unset($payload['max_completion_tokens']);
            $payload['max_tokens'] = 2000;
            
            $response = wp_remote_post('https://api.openai.com/v1/chat/completions', array(
                'headers' => array(
                    'Authorization' => 'Bearer ' . $this->api_key,
                    'Content-Type'  => 'application/json',
                ),
                'body'    => wp_json_encode($payload),
                'timeout' => 60,
            ));
        }
        
        if (is_wp_error($response)) {
            return array('error' => $response->get_error_message());
        }
        
        $body = json_decode(wp_remote_retrieve_body($response), true);
        $content = $body['choices'][0]['message']['content'] ?? '';
        
        // Try to parse as JSON
        $content = trim($content);
        $content = preg_replace('/^```json?\s*/i', '', $content);
        $content = preg_replace('/```\s*$/', '', $content);
        
        $analysis = json_decode($content, true);
        if (json_last_error() !== JSON_ERROR_NONE) {
            return array(
                'raw_analysis' => $content,
                'parse_error'  => json_last_error_msg(),
            );
        }
        
        return $analysis;
    }
    
    /**
     * Full website scan: fetch + extract + analyze
     * 
     * @param string $url URL to scan
     * @param string $purpose Purpose of scan
     * @return array Complete scan results
     */
    public function scan_website($url, $purpose = 'analysis') {
        error_log("VMO Website Scanner: Scanning {$url} for purpose: {$purpose}");
        
        // Step 1: Fetch the URL
        $fetch_result = $this->fetch_url($url);
        if (is_wp_error($fetch_result)) {
            return array(
                'success' => false,
                'error'   => $fetch_result->get_error_message(),
                'url'     => $url,
            );
        }
        
        // Step 2: Extract content
        $extracted = $this->extract_content($fetch_result['html']);
        
        // Step 3: Extract styles (for cloning)
        $styles = $this->extract_styles($fetch_result['html'], $url);
        
        // Step 4: AI Analysis
        $analysis = $this->analyze_with_ai($extracted, $purpose);
        
        return array(
            'success'    => true,
            'url'        => $url,
            'fetched_at' => $fetch_result['fetched_at'],
            'extracted'  => $extracted,
            'styles'     => $styles,
            'analysis'   => $analysis,
        );
    }
    
    /**
     * AJAX: Scan a website
     */
    public function ajax_scan_website() {
        check_ajax_referer('vmo_builder_nonce', 'security');
        
        $url = sanitize_url($_POST['url'] ?? '');
        $purpose = sanitize_text_field($_POST['purpose'] ?? 'analysis');
        
        if (empty($url)) {
            wp_send_json_error(array('message' => 'URL is required'));
        }
        
        $result = $this->scan_website($url, $purpose);
        
        if ($result['success']) {
            wp_send_json_success($result);
        } else {
            wp_send_json_error($result);
        }
    }
    
    /**
     * AJAX: Quick URL content fetch (for consultation context)
     */
    public function ajax_fetch_url_content() {
        check_ajax_referer('vmo_builder_nonce', 'security');
        
        $url = sanitize_url($_POST['url'] ?? '');
        
        if (empty($url)) {
            wp_send_json_error(array('message' => 'URL is required'));
        }
        
        $fetch_result = $this->fetch_url($url);
        if (is_wp_error($fetch_result)) {
            wp_send_json_error(array('message' => $fetch_result->get_error_message()));
        }
        
        $extracted = $this->extract_content($fetch_result['html']);
        
        // Return a condensed version for AI context
        wp_send_json_success(array(
            'url'          => $url,
            'title'        => $extracted['title'],
            'meta'         => $extracted['meta'],
            'headings'     => $extracted['headings'],
            'text_content' => substr($extracted['text_content'], 0, 10000), // Limit for context
            'navigation'   => $extracted['navigation'],
            'images_count' => count($extracted['images']),
        ));
    }
    
    /**
     * AJAX: AI-powered website analysis
     */
    public function ajax_analyze_website() {
        check_ajax_referer('vmo_builder_nonce', 'security');
        
        $url = sanitize_url($_POST['url'] ?? '');
        $purpose = sanitize_text_field($_POST['purpose'] ?? 'reference');
        
        if (empty($url)) {
            wp_send_json_error(array('message' => 'URL is required'));
        }
        
        $result = $this->scan_website($url, $purpose);
        
        if ($result['success']) {
            // Store in session for consultation context
            $session_id = sanitize_text_field($_POST['session_id'] ?? '');
            if ($session_id) {
                $this->store_scanned_website($session_id, $url, $result);
            }
            
            wp_send_json_success(array(
                'url'      => $url,
                'analysis' => $result['analysis'],
                'title'    => $result['extracted']['title'] ?? '',
                'summary'  => $this->generate_quick_summary($result),
            ));
        } else {
            wp_send_json_error($result);
        }
    }
    
    /**
     * AJAX: Clone website structure
     */
    public function ajax_clone_website_structure() {
        check_ajax_referer('vmo_builder_nonce', 'security');
        
        $url = sanitize_url($_POST['url'] ?? '');
        
        if (empty($url)) {
            wp_send_json_error(array('message' => 'URL is required'));
        }
        
        $result = $this->scan_website($url, 'clone');
        
        if (!$result['success']) {
            wp_send_json_error($result);
        }
        
        // Generate a clone blueprint
        $blueprint = $this->generate_clone_blueprint($result);
        
        wp_send_json_success(array(
            'url'       => $url,
            'blueprint' => $blueprint,
            'styles'    => $result['styles'],
            'message'   => 'Website structure analyzed. Ready to generate VMO-powered version.',
        ));
    }
    
    /**
     * Generate a quick summary of scanned website
     */
    private function generate_quick_summary($scan_result) {
        $extracted = $scan_result['extracted'] ?? array();
        $analysis = $scan_result['analysis'] ?? array();
        
        $summary = "Website: " . ($extracted['title'] ?? 'Unknown') . "\n";
        
        if (!empty($analysis['business_type'])) {
            $summary .= "Type: " . $analysis['business_type'] . "\n";
        }
        
        if (!empty($analysis['value_proposition'])) {
            $summary .= "Value Prop: " . $analysis['value_proposition'] . "\n";
        }
        
        if (!empty($analysis['key_features'])) {
            $summary .= "Features: " . implode(', ', array_slice($analysis['key_features'], 0, 5)) . "\n";
        }
        
        return $summary;
    }
    
    /**
     * Generate a clone blueprint for website replication
     */
    private function generate_clone_blueprint($scan_result) {
        $extracted = $scan_result['extracted'] ?? array();
        $analysis = $scan_result['analysis'] ?? array();
        $styles = $scan_result['styles'] ?? array();
        
        return array(
            'page_structure' => array(
                'header'     => !empty($extracted['navigation']),
                'hero'       => true, // Assume hero section
                'sections'   => count($extracted['sections'] ?? array()),
                'footer'     => !empty($extracted['footer']),
            ),
            'navigation'     => $extracted['navigation'] ?? array(),
            'content_blocks' => array_map(function($heading) {
                return array(
                    'type'    => 'section',
                    'heading' => $heading['text'],
                    'level'   => $heading['level'],
                );
            }, $extracted['headings'] ?? array()),
            'design_tokens'  => array(
                'colors'     => array_slice($styles['colors'] ?? array(), 0, 10),
                'fonts'      => array_slice($styles['fonts'] ?? array(), 0, 5),
            ),
            'features_to_include' => $analysis['key_features'] ?? array(),
            'ctas_to_include'     => $analysis['call_to_actions'] ?? array(),
            'tech_stack'          => 'React/Next.js via VMO', // VMO's stack
        );
    }
    
    /**
     * Store scanned website data in consultation context
     */
    private function store_scanned_website($session_id, $url, $scan_result) {
        global $wpdb;
        
        $user_id = get_current_user_id();
        $table = $wpdb->prefix . 'vmo_consultations';
        
        // Get existing consultation
        $consultation = $wpdb->get_row($wpdb->prepare(
            "SELECT * FROM {$table} WHERE session_id = %s AND user_id = %d",
            $session_id,
            $user_id
        ));
        
        if (!$consultation) {
            return false;
        }
        
        $data = json_decode($consultation->consultation_data ?? '{}', true);
        if (!is_array($data)) {
            $data = array();
        }
        
        // Store under scanned_websites
        if (!isset($data['scanned_websites'])) {
            $data['scanned_websites'] = array();
        }
        
        $data['scanned_websites'][$url] = array(
            'scanned_at' => current_time('mysql'),
            'title'      => $scan_result['extracted']['title'] ?? '',
            'analysis'   => $scan_result['analysis'] ?? array(),
            'summary'    => $this->generate_quick_summary($scan_result),
        );
        
        // Update consultation
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $wpdb->update(
            $table,
            array('consultation_data' => wp_json_encode($data)),
            array('session_id' => $session_id, 'user_id' => $user_id),
            array('%s'),
            array('%s', '%d')
        );
        
        return true;
    }
    
    /**
     * Get all scanned websites for a session
     */
    public function get_scanned_websites($session_id) {
        global $wpdb;
        
        $user_id = get_current_user_id();
        $table = $wpdb->prefix . 'vmo_consultations';
        
        $consultation = $wpdb->get_row($wpdb->prepare(
            "SELECT consultation_data FROM {$table} WHERE session_id = %s AND user_id = %d",
            $session_id,
            $user_id
        ));
        
        if (!$consultation) {
            return array();
        }
        
        $data = json_decode($consultation->consultation_data ?? '{}', true);
        return $data['scanned_websites'] ?? array();
    }
}

// Initialize the scanner
function vmo_website_scanner() {
    return VMO_Website_Scanner::get_instance();
}

// Auto-initialize
add_action('init', function() {
    vmo_website_scanner();
});
