<?php

namespace classes;

class security_schema_bootstrap
{
    private static bool $initialized = false;

    public static function ensureTables(): void
    {
        if (self::$initialized) {
            return;
        }

        global $db;

        $queries = [
            "CREATE TABLE IF NOT EXISTS security_firewall_rules (
                id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
                action VARCHAR(16) NOT NULL,
                target_type VARCHAR(32) NOT NULL,
                target_value VARCHAR(255) NOT NULL,
                route_pattern VARCHAR(255) NULL,
                priority INT NOT NULL DEFAULT 100,
                reason TEXT NULL,
                enabled TINYINT(1) NOT NULL DEFAULT 1,
                expires_at DATETIME NULL,
                metadata_json LONGTEXT NULL,
                created_by INT NULL,
                created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
                updated_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
                deleted_at DATETIME NULL,
                INDEX idx_security_firewall_rules_active (enabled, deleted_at, expires_at),
                INDEX idx_security_firewall_rules_target (target_type, target_value),
                INDEX idx_security_firewall_rules_priority (priority)
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci",

            "CREATE TABLE IF NOT EXISTS security_policy_rules (
                id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
                rule_key VARCHAR(64) NOT NULL,
                enabled TINYINT(1) NOT NULL DEFAULT 1,
                threshold_count INT NOT NULL,
                window_seconds INT NOT NULL,
                mode VARCHAR(16) NOT NULL DEFAULT 'observe',
                exempt_permission_nodes_json LONGTEXT NULL,
                updated_by INT NULL,
                created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
                updated_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
                UNIQUE KEY uq_security_policy_rules_key (rule_key)
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci",

            "CREATE TABLE IF NOT EXISTS security_policy_events (
                id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
                rule_key VARCHAR(64) NOT NULL,
                subject_type VARCHAR(32) NOT NULL,
                subject_key VARCHAR(191) NOT NULL,
                route_path VARCHAR(255) NULL,
                route_template VARCHAR(255) NULL,
                method VARCHAR(16) NULL,
                source_ip VARCHAR(64) NULL,
                customer_number INT NULL,
                user_id INT NULL,
                subuser_id INT NULL,
                metadata_json LONGTEXT NULL,
                created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
                INDEX idx_security_policy_events_window (rule_key, subject_type, subject_key, created_at),
                INDEX idx_security_policy_events_created (created_at),
                INDEX idx_security_policy_events_customer (customer_number, created_at),
                INDEX idx_security_policy_events_ip (source_ip, created_at)
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci",

            "CREATE TABLE IF NOT EXISTS security_incidents (
                id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
                incident_key VARCHAR(191) NOT NULL,
                type VARCHAR(64) NOT NULL,
                severity VARCHAR(16) NOT NULL DEFAULT 'medium',
                status VARCHAR(32) NOT NULL DEFAULT 'open',
                title VARCHAR(255) NOT NULL,
                source_ip VARCHAR(64) NULL,
                customer_number INT NULL,
                user_id INT NULL,
                subuser_id INT NULL,
                route_path VARCHAR(255) NULL,
                route_template VARCHAR(255) NULL,
                method VARCHAR(16) NULL,
                related_rule_id BIGINT UNSIGNED NULL,
                related_firewall_rule_id BIGINT UNSIGNED NULL,
                occurrence_count INT NOT NULL DEFAULT 1,
                metadata_json LONGTEXT NULL,
                first_seen_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
                last_seen_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
                resolved_by INT NULL,
                resolved_at DATETIME NULL,
                created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
                updated_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
                UNIQUE KEY uq_security_incidents_key (incident_key),
                INDEX idx_security_incidents_status_seen (status, last_seen_at),
                INDEX idx_security_incidents_type_seen (type, last_seen_at),
                INDEX idx_security_incidents_customer_seen (customer_number, last_seen_at),
                INDEX idx_security_incidents_ip_seen (source_ip, last_seen_at)
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci",

            "CREATE TABLE IF NOT EXISTS security_incident_notes (
                id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
                incident_id BIGINT UNSIGNED NOT NULL,
                note TEXT NOT NULL,
                created_by INT NULL,
                created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
                INDEX idx_security_incident_notes_incident (incident_id, created_at)
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci",
        ];

        foreach ($queries as $query) {
            $db->query($query);
        }

        self::$initialized = true;
    }

    public static function tablesExist(): bool
    {
        global $db;

        $database = $db->escape_string($db->getDatabase());
        $result = $db->query(
            "SELECT COUNT(*) AS count
             FROM information_schema.tables
             WHERE table_schema = '{$database}'
               AND table_name IN (
                   'security_firewall_rules',
                   'security_policy_rules',
                   'security_policy_events',
                   'security_incidents',
                   'security_incident_notes'
               )"
        );
        $row = $result ? $result->fetch_assoc() : ['count' => 0];
        return (int)($row['count'] ?? 0) === 5;
    }
}
