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

class VMO_Jurisdiction_Engine {
    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_jurisdiction_profiles';

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

    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,
            normalized_location VARCHAR(255) DEFAULT NULL,
            country VARCHAR(120) DEFAULT NULL,
            region VARCHAR(120) DEFAULT NULL,
            city VARCHAR(120) DEFAULT NULL,
            service_scope VARCHAR(50) DEFAULT 'local',
            profile_hash VARCHAR(64) DEFAULT NULL,
            profile_json LONGTEXT NULL,
            is_active TINYINT(1) DEFAULT 1,
            created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
            updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
            PRIMARY KEY (id),
            KEY idx_user_id (user_id),
            KEY idx_session_id (session_id),
            KEY idx_active (is_active)
        ) {$charset_collate};";

        dbDelta($sql);
    }

    public function resolve_and_save_from_consultation($user_id, $session_id, $consultation_state) {
        $profile = $this->resolve_profile($consultation_state);

        if (empty($profile)) {
            return array();
        }

        return $this->save_profile($user_id, $session_id, $profile);
    }

    public function resolve_profile($consultation_state, $business_type = '', $context = array()) {
        $location = '';
        $industry = '';
        $offerings = array();
        $ecommerce = false;
        $donations = false;

        if (is_array($consultation_state)) {
            $extracted = isset($consultation_state['extracted_information']) && is_array($consultation_state['extracted_information'])
                ? $consultation_state['extracted_information']
                : array();
            $business_profile = isset($consultation_state['business_profile']) && is_array($consultation_state['business_profile'])
                ? $consultation_state['business_profile']
                : array();
            $identity = isset($business_profile['identity']) && is_array($business_profile['identity'])
                ? $business_profile['identity']
                : array();
            $web_requirements = isset($business_profile['web_requirements']) && is_array($business_profile['web_requirements'])
                ? $business_profile['web_requirements']
                : array();

            $location = $this->first_non_empty(array(
                $extracted['location'] ?? '',
                $identity['hq_location'] ?? '',
                $context['location'] ?? '',
            ));
            $business_type = $this->first_non_empty(array(
                $business_type,
                $extracted['businessType'] ?? '',
                $extracted['business_type'] ?? '',
                $identity['business_type'] ?? '',
                $identity['legal_structure'] ?? '',
                $context['business_type'] ?? '',
            ));
            $industry = $this->first_non_empty(array(
                $extracted['industry'] ?? '',
                $identity['industry'] ?? '',
                $context['industry'] ?? '',
            ));
            $offerings = $this->normalize_list($extracted['offerings'] ?? array());
            $ecommerce = !empty($extracted['needsEcommerce']) || !empty($web_requirements['ecommerce']);
            $donations = !empty($web_requirements['donations'])
                || in_array(strtolower((string)($extracted['payment_collection_mode'] ?? '')), array('donation', 'donations', 'tithes', 'offering'), true);
        } else {
            $location = (string) $consultation_state;
            $industry = (string) ($context['industry'] ?? '');
            $offerings = $this->normalize_list($context['offerings'] ?? array());
            $ecommerce = !empty($context['ecommerce']);
            $donations = !empty($context['donations']);
        }

        $parsed = $this->parse_location($location);
        $tags = $this->collect_compliance_tags($business_type, $industry, $offerings, $ecommerce, $donations, $parsed);
        $policies = $this->collect_required_policies($tags, $ecommerce, $donations);
        $warning_level = $this->determine_warning_level($tags);

        return array(
            'normalized_location' => $parsed['normalized_location'],
            'country' => $parsed['country'],
            'region' => $parsed['region'],
            'city' => $parsed['city'],
            'service_scope' => $this->determine_service_scope($context, $parsed),
            'compliance_sensitivity_tags' => $tags,
            'required_policy_suggestions' => $policies,
            'legal_warning_level' => $warning_level,
            'notes' => $this->build_notes($parsed, $tags, $warning_level),
        );
    }

    public function save_profile($user_id, $session_id, array $profile) {
        $user_id = (int) $user_id;
        $session_id = (string) $session_id;
        if ($user_id <= 0 || $session_id === '') {
            return $profile;
        }

        $profile_hash = md5(wp_json_encode($profile));
        $existing = $this->get_active_profile($session_id, $user_id);
        if (!empty($existing['profile_hash']) && $existing['profile_hash'] === $profile_hash) {
            return $existing;
        }

        $this->wpdb->update(
            $this->table_name,
            array(
                'is_active' => 0,
                'updated_at' => current_time('mysql'),
            ),
            array(
                'user_id' => $user_id,
                'session_id' => $session_id,
                'is_active' => 1,
            ),
            array('%d', '%s'),
            array('%d', '%s', '%d')
        );

        $this->wpdb->insert(
            $this->table_name,
            array(
                'user_id' => $user_id,
                'session_id' => $session_id,
                'normalized_location' => $profile['normalized_location'] ?? '',
                'country' => $profile['country'] ?? '',
                'region' => $profile['region'] ?? '',
                'city' => $profile['city'] ?? '',
                'service_scope' => $profile['service_scope'] ?? 'local',
                'profile_hash' => $profile_hash,
                'profile_json' => wp_json_encode($profile),
                'is_active' => 1,
                'created_at' => current_time('mysql'),
                'updated_at' => current_time('mysql'),
            ),
            array('%d', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%d', '%s', '%s')
        );

        $profile['id'] = (int) $this->wpdb->insert_id;
        $profile['profile_hash'] = $profile_hash;

        return $profile;
    }

    public function get_active_profile($session_id, $user_id = 0) {
        $session_id = (string) $session_id;
        if ($session_id === '') {
            return array();
        }

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

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

        $profile = json_decode($row['profile_json'], true);
        if (!is_array($profile)) {
            $profile = array();
        }

        $profile['id'] = (int) $row['id'];
        $profile['profile_hash'] = (string) ($row['profile_hash'] ?? '');

        return $profile;
    }

    private function parse_location($location) {
        $location = trim(wp_strip_all_tags((string) $location));
        $parts = array_values(array_filter(array_map('trim', explode(',', $location))));

        $country = '';
        $region = '';
        $city = '';

        $country_map = array(
            'united states' => 'United States',
            'usa' => 'United States',
            'us' => 'United States',
            'united kingdom' => 'United Kingdom',
            'uk' => 'United Kingdom',
            'england' => 'United Kingdom',
            'canada' => 'Canada',
            'australia' => 'Australia',
            'nigeria' => 'Nigeria',
            'ireland' => 'Ireland',
            'germany' => 'Germany',
            'france' => 'France',
            'spain' => 'Spain',
            'italy' => 'Italy',
            'netherlands' => 'Netherlands',
            'belgium' => 'Belgium',
            'sweden' => 'Sweden',
            'norway' => 'Norway',
            'denmark' => 'Denmark',
            'switzerland' => 'Switzerland',
            'united arab emirates' => 'United Arab Emirates',
            'uae' => 'United Arab Emirates',
        );

        if (!empty($parts)) {
            $last = strtolower(end($parts));
            foreach ($country_map as $needle => $label) {
                if ($last === $needle || strpos($last, $needle) !== false) {
                    $country = $label;
                    break;
                }
            }
        }

        if (count($parts) >= 3) {
            $city = $parts[0];
            $region = $parts[1];
            if ($country === '') {
                $country = $parts[2];
            }
        } elseif (count($parts) === 2) {
            $city = $parts[0];
            if ($country !== '') {
                $region = $parts[1];
            } else {
                $region = $parts[1];
            }
        } elseif (count($parts) === 1) {
            if ($country !== '') {
                $region = $parts[0];
            } else {
                $city = $parts[0];
            }
        }

        return array(
            'normalized_location' => $location,
            'country' => $country,
            'region' => $region,
            'city' => $city,
        );
    }

    private function collect_compliance_tags($business_type, $industry, array $offerings, $ecommerce, $donations, array $parsed) {
        $tags = array();
        $business_text = strtolower(trim($business_type . ' ' . $industry . ' ' . implode(' ', $offerings)));

        if ($ecommerce) {
            $tags[] = 'consumer_rights';
        }
        if ($donations) {
            $tags[] = 'donation_compliance';
        }
        if (preg_match('/medical|health|clinic|doctor|therapy|wellness|dentist/', $business_text)) {
            $tags[] = 'healthcare';
            $tags[] = 'sensitive_personal_data';
        }
        if (preg_match('/finance|loan|insurance|broker|investment|crypto|tax/', $business_text)) {
            $tags[] = 'financial_promotions';
            $tags[] = 'regulated_advice';
        }
        if (preg_match('/law|attorney|legal/', $business_text)) {
            $tags[] = 'legal_services';
            $tags[] = 'regulated_advice';
        }
        if (preg_match('/education|school|academy|daycare|children|kids|tutor/', $business_text)) {
            $tags[] = 'child_privacy';
        }
        if (preg_match('/real estate|property|mortgage/', $business_text)) {
            $tags[] = 'real_estate_disclosures';
        }

        $country = strtolower((string) ($parsed['country'] ?? ''));
        $region = strtolower((string) ($parsed['region'] ?? ''));
        if (in_array($country, array('united kingdom', 'germany', 'france', 'spain', 'italy', 'netherlands', 'belgium', 'sweden', 'norway', 'denmark', 'ireland', 'switzerland'), true)) {
            $tags[] = 'gdpr';
            $tags[] = 'cookie_consent';
        }
        if ($country === 'canada') {
            $tags[] = 'pipeda';
        }
        if ($country === 'nigeria') {
            $tags[] = 'ndpr';
        }
        if ($country === 'united states' && preg_match('/california|ca\b/', $region)) {
            $tags[] = 'ccpa';
        }

        return array_values(array_unique(array_filter($tags)));
    }

    private function collect_required_policies(array $tags, $ecommerce, $donations) {
        $policies = array('privacy_policy', 'terms_of_service');

        if (in_array('cookie_consent', $tags, true) || in_array('gdpr', $tags, true)) {
            $policies[] = 'cookie_policy';
        }
        if ($ecommerce) {
            $policies[] = 'refund_policy';
            $policies[] = 'shipping_and_returns';
        }
        if ($donations) {
            $policies[] = 'donation_policy';
        }
        if (in_array('regulated_advice', $tags, true) || in_array('financial_promotions', $tags, true) || in_array('legal_services', $tags, true)) {
            $policies[] = 'professional_disclaimer';
        }
        if (in_array('healthcare', $tags, true)) {
            $policies[] = 'medical_disclaimer';
        }
        if (in_array('child_privacy', $tags, true)) {
            $policies[] = 'child_privacy_notice';
        }

        return array_values(array_unique($policies));
    }

    private function determine_warning_level(array $tags) {
        $high_risk_tags = array('regulated_advice', 'financial_promotions', 'legal_services', 'healthcare');
        $medium_risk_tags = array('child_privacy', 'consumer_rights', 'gdpr', 'ccpa', 'pipeda', 'ndpr', 'real_estate_disclosures');

        foreach ($high_risk_tags as $tag) {
            if (in_array($tag, $tags, true)) {
                return 'high';
            }
        }
        foreach ($medium_risk_tags as $tag) {
            if (in_array($tag, $tags, true)) {
                return 'medium';
            }
        }

        return 'low';
    }

    private function determine_service_scope($context, array $parsed) {
        $scope_text = '';
        if (is_array($context)) {
            $scope_text = strtolower((string) ($context['service_scope'] ?? $context['service_area'] ?? ''));
        }

        if (strpos($scope_text, 'international') !== false || strpos($scope_text, 'global') !== false || strpos($scope_text, 'worldwide') !== false) {
            return 'international';
        }
        if (strpos($scope_text, 'national') !== false || strpos($scope_text, 'countrywide') !== false) {
            return 'national';
        }
        if (!empty($parsed['country']) && empty($parsed['city'])) {
            return 'national';
        }

        return 'local';
    }

    private function build_notes(array $parsed, array $tags, $warning_level) {
        $notes = array();

        if (!empty($parsed['country'])) {
            $notes[] = 'Jurisdiction resolved to ' . $parsed['country'] . '.';
        } else {
            $notes[] = 'Jurisdiction could not be confidently resolved from the provided location.';
        }
        if (!empty($tags)) {
            $notes[] = 'Compliance-sensitive areas detected: ' . implode(', ', $tags) . '.';
        }
        if ($warning_level === 'high') {
            $notes[] = 'Local professional review is strongly recommended before legal or regulated content goes live.';
        }

        return $notes;
    }

    private function normalize_list($value) {
        if (!is_array($value)) {
            if ($value === null || $value === '') {
                return array();
            }
            $value = preg_split('/[,\n]+/', (string) $value);
        }

        return array_values(array_filter(array_map(function ($item) {
            return trim(wp_strip_all_tags((string) $item));
        }, $value)));
    }

    private function first_non_empty(array $values) {
        foreach ($values as $value) {
            if (is_string($value) && trim($value) !== '') {
                return trim($value);
            }
        }

        return '';
    }
}

if (!function_exists('vmo_get_jurisdiction_engine')) {
    function vmo_get_jurisdiction_engine() {
        return VMO_Jurisdiction_Engine::get_instance();
    }
}
