-- Complete Database Setup for Web Hosting Panel
-- This script creates all necessary database structures for WHP
-- Run this script after MySQL server is installed and running

-- Create the whp database if it doesn't exist
CREATE DATABASE IF NOT EXISTS whp CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
USE whp;

-- ================================================
-- CORE DATABASE MANAGEMENT TABLES
-- ================================================

-- Table to track databases created by users
CREATE TABLE IF NOT EXISTS user_databases (
    id INT AUTO_INCREMENT PRIMARY KEY,
    database_name VARCHAR(64) NOT NULL UNIQUE,
    owner_username VARCHAR(32) NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    size_bytes BIGINT DEFAULT 0,
    INDEX idx_owner (owner_username),
    INDEX idx_database (database_name)
);

-- Table to track database users created by panel users
CREATE TABLE IF NOT EXISTS database_users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(32) NOT NULL,
    host VARCHAR(255) DEFAULT '%',
    database_name VARCHAR(64) NOT NULL,
    privileges TEXT NOT NULL,
    created_by VARCHAR(32) NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    UNIQUE KEY unique_user_host_db (username, host, database_name),
    INDEX idx_created_by (created_by),
    INDEX idx_database (database_name)
);

-- Table to store user passwords for MySQL authentication
CREATE TABLE IF NOT EXISTS user_passwords (
    id INT AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(32) NOT NULL UNIQUE,
    password_hash VARCHAR(255) NOT NULL,
    mysql_password VARCHAR(255) NOT NULL,
    postgresql_password VARCHAR(255) DEFAULT NULL,
    last_updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    INDEX idx_username (username)
);

-- ================================================
-- USER RESOURCE MANAGEMENT TABLES
-- ================================================

-- Create client_allowances table (updated to use username directly)
CREATE TABLE IF NOT EXISTS client_allowances (
    id INT AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(32) NOT NULL UNIQUE,
    max_cpu_allowance DECIMAL(4,2) DEFAULT 0.5,
    max_memory_allowance INT DEFAULT 512,
    max_domains INT DEFAULT 1,
    max_disk_space INT DEFAULT 1000,
    max_email_accounts INT DEFAULT 0,
    api_enabled BOOLEAN DEFAULT FALSE,
    api_rate_limit INT DEFAULT 100,
    max_email_storage_mb INT DEFAULT 1000,
    account_type ENUM('full', 'domain_dns', 'mail_dns') NOT NULL DEFAULT 'full' COMMENT 'Account type restricting feature access',
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    INDEX idx_username (username)
);

-- Create container_types table
CREATE TABLE IF NOT EXISTS container_types (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(64) NOT NULL UNIQUE,
    description TEXT,
    base_image VARCHAR(255) NOT NULL,
    min_cpu DECIMAL(3,2) DEFAULT 0.25,
    min_memory INT DEFAULT 256,
    startup_env TEXT COMMENT 'JSON object of startup environment variables',
    user_variables TEXT COMMENT 'JSON object of user-configurable variables',
    mount_options TEXT COMMENT 'JSON object of mount options and volumes',
    last_image_pull TIMESTAMP NULL DEFAULT NULL COMMENT 'Last time the base image was pulled',
    image_digest VARCHAR(255) NULL DEFAULT NULL COMMENT 'Current image digest/hash',
    listen_port INT DEFAULT 80 COMMENT 'Port that containers listen on for HAProxy backend configuration',
    listen_port_tls TINYINT(1) DEFAULT 0 COMMENT 'If set, this port uses TLS/SSL for HAProxy backend',
    active BOOLEAN DEFAULT TRUE,
    eol_date DATE NULL DEFAULT NULL COMMENT 'End of life date for this container type',
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    INDEX idx_name (name),
    INDEX idx_active (active)
);

-- Create domains table (updated to use username instead of user_id)
-- container_type_id is now nullable - domains don't get container types until assigned through Sites
CREATE TABLE IF NOT EXISTS domains (
    id INT AUTO_INCREMENT PRIMARY KEY,
    domain_name VARCHAR(255) NOT NULL UNIQUE,
    username VARCHAR(32) NOT NULL,
    container_type_id INT DEFAULT NULL,
    cpu_allowance DECIMAL(4,2) DEFAULT 0.25,
    memory_allowance INT DEFAULT 256,
    active BOOLEAN DEFAULT TRUE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    FOREIGN KEY (container_type_id) REFERENCES container_types(id) ON DELETE SET NULL,
    INDEX idx_domain_name (domain_name),
    INDEX idx_username (username),
    INDEX idx_container_type (container_type_id),
    INDEX idx_active (active)
);

-- Create containers table
CREATE TABLE IF NOT EXISTS containers (
    id INT AUTO_INCREMENT PRIMARY KEY,
    container_id VARCHAR(255) NOT NULL UNIQUE,
    domain_id INT NOT NULL,
    ip_address VARCHAR(45) DEFAULT NULL,
    port INT DEFAULT NULL,
    status VARCHAR(20) DEFAULT 'stopped',
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    FOREIGN KEY (domain_id) REFERENCES domains(id) ON DELETE CASCADE,
    INDEX idx_container_id (container_id),
    INDEX idx_domain_id (domain_id),
    INDEX idx_status (status)
);

-- Create environment variable templates table (for future reference/documentation)
CREATE TABLE IF NOT EXISTS container_env_templates (
    id INT AUTO_INCREMENT PRIMARY KEY,
    variable_name VARCHAR(100) NOT NULL,
    description TEXT,
    example_value VARCHAR(255),
    category ENUM('system', 'user', 'domain', 'path') DEFAULT 'system',
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    UNIQUE KEY unique_variable (variable_name)
);

-- Create user variables table for storing container-specific user configurations
CREATE TABLE IF NOT EXISTS container_user_variables (
    id INT AUTO_INCREMENT PRIMARY KEY,
    container_type_id INT NOT NULL,
    domain_id INT NOT NULL,
    variable_name VARCHAR(100) NOT NULL,
    variable_value TEXT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    FOREIGN KEY (container_type_id) REFERENCES container_types(id) ON DELETE CASCADE,
    FOREIGN KEY (domain_id) REFERENCES domains(id) ON DELETE CASCADE,
    UNIQUE KEY unique_container_variable (container_type_id, domain_id, variable_name)
);

-- ================================================
-- SITES MANAGEMENT SYSTEM
-- ================================================

-- Create sites table to manage site configurations
CREATE TABLE IF NOT EXISTS sites (
    id INT AUTO_INCREMENT PRIMARY KEY,
    site_name VARCHAR(255) NOT NULL,
    primary_domain_id INT NOT NULL,
    username VARCHAR(32) NOT NULL,
    container_type_id INT NOT NULL,
    container_mode ENUM('standalone','shared_httpd') NOT NULL DEFAULT 'standalone' COMMENT 'Container deployment mode',
    container_count INT DEFAULT 1,
    cpu_per_container DECIMAL(4,2) DEFAULT 0.25,
    memory_per_container INT DEFAULT 256,
    user_variables JSON COMMENT 'User-configured variables for the container type',
    active BOOLEAN DEFAULT TRUE,
    auto_recreate_on_update TINYINT(1) DEFAULT 0 COMMENT 'Automatically recreate containers when new image versions are available',
    is_wildcard TINYINT(1) DEFAULT 0 COMMENT 'Whether this site handles wildcard subdomains',
    -- SSL/HAProxy Configuration (Future Implementation)
    ssl_enabled TINYINT(1) DEFAULT 0 COMMENT 'SSL certificate enabled (0=No, 1=Let\'s Encrypt, 2=Custom)',
    ssl_certificate_path VARCHAR(255) DEFAULT NULL COMMENT 'Path to SSL certificate file',
    ssl_key_path VARCHAR(255) DEFAULT NULL COMMENT 'Path to SSL private key file',
    ssl_force_https TINYINT(1) DEFAULT 0 COMMENT 'Force HTTPS redirects',
    ssl_hsts_enabled TINYINT(1) DEFAULT 0 COMMENT 'Enable HSTS header',
    ssl_last_renewal TIMESTAMP NULL COMMENT 'Last SSL certificate renewal date',
    haproxy_backend_name VARCHAR(255) DEFAULT NULL COMMENT 'HAProxy backend name for this site',
    haproxy_balance_method VARCHAR(50) DEFAULT 'roundrobin' COMMENT 'HAProxy load balancing method',
    haproxy_health_check VARCHAR(255) DEFAULT NULL COMMENT 'HAProxy health check configuration',
    haproxy_ssl_redirect TINYINT(1) DEFAULT 0 COMMENT 'HAProxy SSL redirect configuration',
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    FOREIGN KEY (primary_domain_id) REFERENCES domains(id) ON DELETE CASCADE,
    FOREIGN KEY (container_type_id) REFERENCES container_types(id) ON DELETE RESTRICT,
    INDEX idx_site_name (site_name),
    INDEX idx_username (username),
    INDEX idx_primary_domain (primary_domain_id),
    INDEX idx_container_type (container_type_id),
    INDEX idx_active (active),
    INDEX idx_ssl_enabled (ssl_enabled),
    INDEX idx_haproxy_backend (haproxy_backend_name),
    INDEX idx_auto_recreate (auto_recreate_on_update),
    INDEX idx_is_wildcard (is_wildcard)
);

-- Create site_domains table to link additional domains/subdomains to sites
CREATE TABLE IF NOT EXISTS site_domains (
    id INT AUTO_INCREMENT PRIMARY KEY,
    site_id INT NOT NULL,
    domain_id INT NOT NULL,
    fqdn VARCHAR(255) DEFAULT NULL,
    is_primary BOOLEAN DEFAULT FALSE,
    is_wildcard TINYINT(1) DEFAULT 0 COMMENT 'Whether this domain entry is a wildcard',
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (site_id) REFERENCES sites(id) ON DELETE CASCADE,
    FOREIGN KEY (domain_id) REFERENCES domains(id) ON DELETE CASCADE,
    UNIQUE KEY unique_site_domain (site_id, domain_id, fqdn),
    INDEX idx_site_id (site_id),
    INDEX idx_domain_id (domain_id),
    INDEX idx_is_primary (is_primary)
);

-- Create site_containers table to track individual containers for each site
CREATE TABLE IF NOT EXISTS site_containers (
    id INT AUTO_INCREMENT PRIMARY KEY,
    site_id INT NOT NULL,
    container_id VARCHAR(255) NOT NULL UNIQUE,
    container_number INT NOT NULL COMMENT 'Container number within the site (1, 2, 3, etc.)',
    ip_address VARCHAR(45) DEFAULT NULL,
    port INT DEFAULT NULL,
    status VARCHAR(20) DEFAULT 'stopped',
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    FOREIGN KEY (site_id) REFERENCES sites(id) ON DELETE CASCADE,
    UNIQUE KEY unique_site_container_number (site_id, container_number),
    INDEX idx_site_id (site_id),
    INDEX idx_container_id (container_id),
    INDEX idx_status (status)
);

-- Add indexes for better performance
CREATE INDEX IF NOT EXISTS idx_sites_username_active ON sites (username, active);
CREATE INDEX IF NOT EXISTS idx_site_containers_site_status ON site_containers (site_id, status);
CREATE INDEX IF NOT EXISTS idx_site_domains_site_primary ON site_domains (site_id, is_primary);


-- ================================================
-- ANNOUNCEMENTS SYSTEM
-- ================================================

-- Create announcements table
CREATE TABLE IF NOT EXISTS announcements (
    id INT AUTO_INCREMENT PRIMARY KEY,
    title VARCHAR(255) NOT NULL,
    content TEXT NOT NULL,
    markdown_content TEXT NOT NULL,
    created_by VARCHAR(32) NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    active BOOLEAN DEFAULT TRUE,
    priority INT DEFAULT 0,
    pinned BOOLEAN DEFAULT FALSE,
    INDEX idx_active (active),
    INDEX idx_priority (priority),
    INDEX idx_pinned (pinned),
    INDEX idx_created_by (created_by),
    INDEX idx_created_at (created_at)
);

-- ================================================
-- INITIAL DATA
-- ================================================

-- Insert initial database data if tables are empty
INSERT IGNORE INTO user_databases (database_name, owner_username) VALUES 
('test_db', 'root'),
('whp', 'root');

-- Insert initial database users if table is empty
INSERT IGNORE INTO database_users (username, database_name, privileges, created_by) VALUES 
('test_user', 'test_db', 'ALL', 'root'),
('whp_user', 'whp', 'ALL', 'root');

-- Insert root password record if it doesn't exist
INSERT IGNORE INTO user_passwords (username, password_hash, mysql_password) VALUES 
('root', 'system_password_hash', 'mysql_password'); 

-- Insert actual container types from repo.anhonesthost.net
INSERT IGNORE INTO container_types (name, description, base_image, min_cpu, min_memory, startup_env, user_variables, mount_options, listen_port, listen_port_tls, active) VALUES 
('PHP 7.4', 'Apache with PHP 7.4', 'repo.anhonesthost.net/cloud-hosting-platform/cac:php74', 0.25, 256, 
'{"uid": "${WHP_UID}", "user": "${WHP_USER}", "domain": "${WHP_DOMAIN}"}',
'{}',
'{"volumes": [{"source": "${WHP_HOME}/${WHP_DOMAIN}", "target": "/home/${WHP_USER}", "type": "bind"}]}',
443, 1, 1),

('PHP 8.0', 'Apache with PHP 8.0', 'repo.anhonesthost.net/cloud-hosting-platform/cac:php80', 0.25, 256, 
'{"uid": "${WHP_UID}", "user": "${WHP_USER}", "domain": "${WHP_DOMAIN}"}',
'{}',
'{"volumes": [{"source": "${WHP_HOME}/${WHP_DOMAIN}", "target": "/home/${WHP_USER}", "type": "bind"}]}',
443, 1, 1),

('PHP 8.1', 'Apache with PHP 8.1', 'repo.anhonesthost.net/cloud-hosting-platform/cac:php81', 0.25, 256, 
'{"uid": "${WHP_UID}", "user": "${WHP_USER}", "domain": "${WHP_DOMAIN}"}',
'{}',
'{"volumes": [{"source": "${WHP_HOME}/${WHP_DOMAIN}", "target": "/home/${WHP_USER}", "type": "bind"}]}',
443, 1, 1),

('PHP 8.2', 'Apache with PHP 8.2', 'repo.anhonesthost.net/cloud-hosting-platform/cac:php82', 0.25, 256, 
'{"uid": "${WHP_UID}", "user": "${WHP_USER}", "domain": "${WHP_DOMAIN}"}',
'{}',
'{"volumes": [{"source": "${WHP_HOME}/${WHP_DOMAIN}", "target": "/home/${WHP_USER}", "type": "bind"}]}',
443, 1, 1),

('PHP 8.3', 'Apache with PHP 8.3', 'repo.anhonesthost.net/cloud-hosting-platform/cac:php83', 0.25, 256, 
'{"uid": "${WHP_UID}", "user": "${WHP_USER}", "domain": "${WHP_DOMAIN}"}',
'{}',
'{"volumes": [{"source": "${WHP_HOME}/${WHP_DOMAIN}", "target": "/home/${WHP_USER}", "type": "bind"}]}',
443, 1, 1),

('PHP 8.4', 'Apache with PHP 8.4', 'repo.anhonesthost.net/cloud-hosting-platform/cac:php84', 0.25, 256, 
'{"uid": "${WHP_UID}", "user": "${WHP_USER}", "domain": "${WHP_DOMAIN}"}',
'{}',
'{"volumes": [{"source": "${WHP_HOME}/${WHP_DOMAIN}", "target": "/home/${WHP_USER}", "type": "bind"}]}',
443, 1, 1),

('PHP 8.5', 'Apache with PHP 8.5', 'repo.anhonesthost.net/cloud-hosting-platform/cac:php85', 0.25, 256,
'{"uid": "${WHP_UID}", "user": "${WHP_USER}", "domain": "${WHP_DOMAIN}"}',
'{}',
'{"volumes": [{"source": "${WHP_HOME}/${WHP_DOMAIN}", "target": "/home/${WHP_USER}", "type": "bind"}]}',
443, 1, 1),

('Static Apache', 'Default Apache container for static content only', 'repo.anhonesthost.net/cloud-hosting-platform/whp-default:latest', 0.25, 256,
'{}',
'{}',
'{"volumes": [{"source": "${WHP_HOME}/${WHP_DOMAIN}", "target": "/usr/local/apache2/htdocs", "type": "bind"}]}',
80, 0, 1),

-- PHP-FPM-only container types (for use with shared Apache httpd container)
('PHP-FPM 7.4', 'PHP-FPM only (shared httpd)', 'repo.anhonesthost.net/cloud-hosting-platform/cac-fpm:php74', 0.10, 128,
'{"uid": "${WHP_UID}", "user": "${WHP_USER}", "domain": "${WHP_DOMAIN}", "FPM_LISTEN": "9000", "CONTAINER_ROLE": "fpm_only"}',
'{}',
'{"volumes": [{"source": "${WHP_HOME}/${WHP_DOMAIN}", "target": "/home/${WHP_USER}", "type": "bind"}]}',
9000, 0, 1),

('PHP-FPM 8.0', 'PHP-FPM only (shared httpd)', 'repo.anhonesthost.net/cloud-hosting-platform/cac-fpm:php80', 0.10, 128,
'{"uid": "${WHP_UID}", "user": "${WHP_USER}", "domain": "${WHP_DOMAIN}", "FPM_LISTEN": "9000", "CONTAINER_ROLE": "fpm_only"}',
'{}',
'{"volumes": [{"source": "${WHP_HOME}/${WHP_DOMAIN}", "target": "/home/${WHP_USER}", "type": "bind"}]}',
9000, 0, 1),

('PHP-FPM 8.1', 'PHP-FPM only (shared httpd)', 'repo.anhonesthost.net/cloud-hosting-platform/cac-fpm:php81', 0.10, 128,
'{"uid": "${WHP_UID}", "user": "${WHP_USER}", "domain": "${WHP_DOMAIN}", "FPM_LISTEN": "9000", "CONTAINER_ROLE": "fpm_only"}',
'{}',
'{"volumes": [{"source": "${WHP_HOME}/${WHP_DOMAIN}", "target": "/home/${WHP_USER}", "type": "bind"}]}',
9000, 0, 1),

('PHP-FPM 8.2', 'PHP-FPM only (shared httpd)', 'repo.anhonesthost.net/cloud-hosting-platform/cac-fpm:php82', 0.10, 128,
'{"uid": "${WHP_UID}", "user": "${WHP_USER}", "domain": "${WHP_DOMAIN}", "FPM_LISTEN": "9000", "CONTAINER_ROLE": "fpm_only"}',
'{}',
'{"volumes": [{"source": "${WHP_HOME}/${WHP_DOMAIN}", "target": "/home/${WHP_USER}", "type": "bind"}]}',
9000, 0, 1),

('PHP-FPM 8.3', 'PHP-FPM only (shared httpd)', 'repo.anhonesthost.net/cloud-hosting-platform/cac-fpm:php83', 0.10, 128,
'{"uid": "${WHP_UID}", "user": "${WHP_USER}", "domain": "${WHP_DOMAIN}", "FPM_LISTEN": "9000", "CONTAINER_ROLE": "fpm_only"}',
'{}',
'{"volumes": [{"source": "${WHP_HOME}/${WHP_DOMAIN}", "target": "/home/${WHP_USER}", "type": "bind"}]}',
9000, 0, 1),

('PHP-FPM 8.4', 'PHP-FPM only (shared httpd)', 'repo.anhonesthost.net/cloud-hosting-platform/cac-fpm:php84', 0.10, 128,
'{"uid": "${WHP_UID}", "user": "${WHP_USER}", "domain": "${WHP_DOMAIN}", "FPM_LISTEN": "9000", "CONTAINER_ROLE": "fpm_only"}',
'{}',
'{"volumes": [{"source": "${WHP_HOME}/${WHP_DOMAIN}", "target": "/home/${WHP_USER}", "type": "bind"}]}',
9000, 0, 1),

('PHP-FPM 8.5', 'PHP-FPM only (shared httpd)', 'repo.anhonesthost.net/cloud-hosting-platform/cac-fpm:php85', 0.10, 128,
'{"uid": "${WHP_UID}", "user": "${WHP_USER}", "domain": "${WHP_DOMAIN}", "FPM_LISTEN": "9000", "CONTAINER_ROLE": "fpm_only"}',
'{}',
'{"volumes": [{"source": "${WHP_HOME}/${WHP_DOMAIN}", "target": "/home/${WHP_USER}", "type": "bind"}]}',
9000, 0, 1);

-- Insert standard WHP dynamic variables
INSERT IGNORE INTO container_env_templates (variable_name, description, example_value, category) VALUES
('${WHP_USER}', 'System username of the container owner', 'john', 'user'),
('${WHP_UID}', 'User ID (UID) of the container owner', '1001', 'user'),
('${WHP_GID}', 'Group ID (GID) of the container owner', '1001', 'user'),
('${WHP_HOME}', 'Home directory path of the user', '/docker/users/john', 'path'),
('${WHP_DOMAIN}', 'Primary domain name assigned to the container', 'example.com', 'domain'),
('${WHP_SUBDOMAIN}', 'Subdomain (if applicable)', 'www', 'domain'),
('${WHP_DOMAIN_LIST}', 'Comma-separated list of all domains for this user', 'example.com,test.com', 'domain'),
('${WHP_CONTAINER_NAME}', 'Unique container name', 'john-example-com', 'system'),
('${WHP_PUBLIC_HTML}', 'Public HTML directory path', '/docker/users/john/public_html', 'path'),
('${WHP_LOGS_DIR}', 'Logs directory path', '/docker/users/john/logs', 'path'),
('${WHP_DATA_DIR}', 'User data directory path', '/docker/users/john/data', 'path');

-- Insert a sample announcement
INSERT IGNORE INTO announcements (title, content, markdown_content, created_by, priority) VALUES 
('Welcome to the Web Hosting Panel', 
'<p>Welcome to your new web hosting control panel. This panel allows you to manage your websites, databases, and other hosting features.</p><h3>Getting Started</h3><ul><li>Create databases in the Database Management section</li><li>Manage your domains in Domain Management</li><li>Check server status in the dashboard</li></ul>',
'Welcome to your new web hosting control panel. This panel allows you to manage your websites, databases, and other hosting features.\n\n### Getting Started\n\n- Create databases in the Database Management section\n- Manage your domains in Domain Management  \n- Check server status in the dashboard',
'root', 
1); 

-- ================================================
-- PROFTPD VIRTUAL USERS
-- ================================================

-- Create FTP users table for virtual user authentication
CREATE TABLE IF NOT EXISTS ftp_users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(50) UNIQUE NOT NULL,
    password VARCHAR(255) NOT NULL,
    uid INT NOT NULL,
    gid INT NOT NULL,
    homedir VARCHAR(255) NOT NULL,
    shell VARCHAR(50) DEFAULT '/bin/false',
    count INT DEFAULT 0,
    accessed DATETIME DEFAULT NULL,
    modified DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    created DATETIME DEFAULT CURRENT_TIMESTAMP,
    
    INDEX idx_username (username),
    INDEX idx_uid (uid)
);

-- Create FTP groups table for group management
CREATE TABLE IF NOT EXISTS ftp_groups (
    id INT AUTO_INCREMENT PRIMARY KEY,
    groupname VARCHAR(50) UNIQUE NOT NULL,
    gid INT NOT NULL,
    members TEXT,
    
    INDEX idx_groupname (groupname),
    INDEX idx_gid (gid)
);

-- Create FTP access log table for monitoring
CREATE TABLE IF NOT EXISTS ftp_access_log (
    id INT AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(50) NOT NULL,
    client_ip VARCHAR(45),
    action VARCHAR(50),
    filename VARCHAR(255),
    filesize BIGINT DEFAULT 0,
    timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
    
    INDEX idx_username (username),
    INDEX idx_timestamp (timestamp),
    INDEX idx_action (action)
);

-- Create FTP quotas table for per-user quotas
CREATE TABLE IF NOT EXISTS ftp_quotas (
    id INT AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(50) UNIQUE NOT NULL,
    quota_type ENUM('user', 'group', 'class', 'all') DEFAULT 'user',
    per_session ENUM('false', 'true') DEFAULT 'false',
    limit_type ENUM('soft', 'hard') DEFAULT 'soft',
    bytes_in_avail BIGINT DEFAULT 0,
    bytes_out_avail BIGINT DEFAULT 0,
    bytes_xfer_avail BIGINT DEFAULT 0,
    files_in_avail INT DEFAULT 0,
    files_out_avail INT DEFAULT 0,
    files_xfer_avail INT DEFAULT 0,
    
    INDEX idx_username (username),
    INDEX idx_quota_type (quota_type)
);

-- Insert default FTP group
INSERT IGNORE INTO ftp_groups (groupname, gid, members) VALUES 
('ftpusers', 1000, '');

-- Create indexes for better performance
CREATE INDEX IF NOT EXISTS idx_ftp_users_login ON ftp_users (username, password);
CREATE INDEX IF NOT EXISTS idx_ftp_access_user_time ON ftp_access_log (username, timestamp);

-- ================================================
-- HAPROXY INTEGRATION SCHEMA
-- ================================================

-- Update existing container types with appropriate default ports
UPDATE container_types SET listen_port = 443, listen_port_tls = 1 WHERE name IN ('PHP 7.4', 'PHP 8.0', 'PHP 8.1', 'PHP 8.2', 'PHP 8.3', 'PHP 8.4', 'PHP 8.5');
UPDATE container_types SET listen_port = 80, listen_port_tls = 0 WHERE name IN ('Static Apache');

-- Create HAProxy domain configuration table
CREATE TABLE IF NOT EXISTS haproxy_domains (
    id INT AUTO_INCREMENT PRIMARY KEY,
    domain_name VARCHAR(255) NOT NULL,
    backend_name VARCHAR(255) NOT NULL,
    ssl_enabled TINYINT(1) DEFAULT 0,
    ssl_certificate_path VARCHAR(255) DEFAULT NULL,
    ssl_last_renewal TIMESTAMP NULL,
    is_wildcard TINYINT(1) DEFAULT 0 COMMENT 'Whether this is a wildcard domain for HAProxy config generation',
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    UNIQUE KEY unique_domain (domain_name),
    INDEX idx_backend_name (backend_name),
    INDEX idx_ssl_enabled (ssl_enabled),
    INDEX idx_is_wildcard (is_wildcard)
);

-- Create HAProxy backend servers table
CREATE TABLE IF NOT EXISTS haproxy_backend_servers (
    id INT AUTO_INCREMENT PRIMARY KEY,
    backend_name VARCHAR(255) NOT NULL,
    server_name VARCHAR(255) NOT NULL,
    server_address VARCHAR(255) NOT NULL,
    server_port INT NOT NULL,
    server_options VARCHAR(255) DEFAULT 'check',
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    UNIQUE KEY unique_backend_server (backend_name, server_name),
    INDEX idx_backend_name (backend_name)
);

-- Create SSL certificate renewal log table
CREATE TABLE IF NOT EXISTS ssl_renewal_log (
    id INT AUTO_INCREMENT PRIMARY KEY,
    domain_name VARCHAR(255) NOT NULL,
    renewal_status ENUM('success', 'failed', 'pending') NOT NULL,
    renewal_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    error_message TEXT DEFAULT NULL,
    certificate_expires TIMESTAMP NULL,
    INDEX idx_domain_name (domain_name),
    INDEX idx_renewal_status (renewal_status),
    INDEX idx_renewal_date (renewal_date)
);

-- Create system service SSL certificates table
CREATE TABLE IF NOT EXISTS system_ssl_certificates (
    id INT AUTO_INCREMENT PRIMARY KEY,
    service_name VARCHAR(50) NOT NULL,
    domain_name VARCHAR(255) NOT NULL,
    certificate_path VARCHAR(255) NOT NULL,
    private_key_path VARCHAR(255) NOT NULL,
    ssl_enabled TINYINT(1) DEFAULT 0,
    auto_renew TINYINT(1) DEFAULT 1,
    last_renewal TIMESTAMP NULL,
    expires_at TIMESTAMP NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    UNIQUE KEY unique_service_domain (service_name, domain_name),
    INDEX idx_service_name (service_name),
    INDEX idx_ssl_enabled (ssl_enabled),
    INDEX idx_auto_renew (auto_renew)
);

-- ================================================
-- EMAIL MANAGEMENT SYSTEM
-- ================================================

-- Create email_accounts table to track email addresses
CREATE TABLE IF NOT EXISTS email_accounts (
    id INT AUTO_INCREMENT PRIMARY KEY,
    email_address VARCHAR(255) NOT NULL UNIQUE,
    username VARCHAR(32) NOT NULL,
    domain_name VARCHAR(255) NOT NULL,
    password_hash VARCHAR(255) NOT NULL,
    quota_mb INT DEFAULT 100,
    active BOOLEAN DEFAULT TRUE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    INDEX idx_email_address (email_address),
    INDEX idx_username (username),
    INDEX idx_domain_name (domain_name),
    INDEX idx_active (active)
);

-- Create email_forwarders table for email forwarding
CREATE TABLE IF NOT EXISTS email_forwarders (
    id INT AUTO_INCREMENT PRIMARY KEY,
    source_email VARCHAR(255) NOT NULL,
    destination_email VARCHAR(255) NOT NULL,
    destination_type ENUM('email', 'domain') DEFAULT 'email',
    username VARCHAR(32) NOT NULL,
    active BOOLEAN DEFAULT TRUE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    UNIQUE KEY unique_forward (source_email, destination_email),
    INDEX idx_source_email (source_email),
    INDEX idx_destination_email (destination_email),
    INDEX idx_username (username),
    INDEX idx_active (active)
);

-- Create email_aliases table for email aliases
CREATE TABLE IF NOT EXISTS email_aliases (
    id INT AUTO_INCREMENT PRIMARY KEY,
    alias_email VARCHAR(255) NOT NULL,
    target_email VARCHAR(255) NOT NULL,
    username VARCHAR(32) NOT NULL,
    active BOOLEAN DEFAULT TRUE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    UNIQUE KEY unique_alias (alias_email),
    INDEX idx_alias_email (alias_email),
    INDEX idx_target_email (target_email),
    INDEX idx_username (username),
    INDEX idx_active (active)
);

-- ================================================
-- BACKUP SYSTEM TABLES
-- ================================================

-- Create backup targets table
CREATE TABLE IF NOT EXISTS backup_targets (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    type ENUM('s3', 'ftp', 'sftp') NOT NULL DEFAULT 's3',
    host VARCHAR(255) DEFAULT NULL,
    port INT DEFAULT NULL,
    username VARCHAR(100) DEFAULT NULL,
    password VARCHAR(255) DEFAULT NULL,
    remote_path VARCHAR(255) DEFAULT '/',
    endpoint VARCHAR(255) DEFAULT NULL,
    bucket VARCHAR(100) DEFAULT NULL,
    access_key VARCHAR(100) DEFAULT NULL,
    secret_key VARCHAR(255) DEFAULT NULL,
    region VARCHAR(50) DEFAULT 'us-east-1',
    path_prefix VARCHAR(255) DEFAULT '',
    retention_days INT DEFAULT 30,
    max_backups INT DEFAULT 10,
    is_global BOOLEAN DEFAULT FALSE,
    owner VARCHAR(50) DEFAULT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    INDEX idx_owner (owner),
    INDEX idx_global (is_global)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- Create backup history table
CREATE TABLE IF NOT EXISTS backup_history (
    id INT AUTO_INCREMENT PRIMARY KEY,
    target_id INT NOT NULL,
    user VARCHAR(50) NOT NULL,
    backup_type ENUM('site', 'userfiles', 'database', 'wordpress', 'all') NOT NULL,
    backup_name VARCHAR(255) NOT NULL,
    backup_path VARCHAR(500) NOT NULL,
    local_path varchar(500) DEFAULT NULL COMMENT 'Path to local backup file',
    local_size bigint DEFAULT NULL COMMENT 'Size of local backup file',
    backup_size BIGINT DEFAULT 0,
    upload_method enum('single','multipart') DEFAULT 'single',
    multipart_upload_id varchar(255) DEFAULT NULL,
    status ENUM('pending', 'claimed', 'running', 'completed', 'failed', 'deleted') NOT NULL DEFAULT 'pending',
    creation_status enum('pending','creating','created','failed') DEFAULT 'pending' COMMENT 'Status of local backup creation',
    upload_status enum('pending','uploading','uploaded','failed','skipped') DEFAULT NULL COMMENT 'Status of remote upload',
    upload_started_at timestamp NULL DEFAULT NULL,
    upload_completed_at timestamp NULL DEFAULT NULL,
    upload_attempts int DEFAULT 0 COMMENT 'Number of upload attempts',
    local_deleted_at timestamp NULL DEFAULT NULL COMMENT 'When local file was deleted',
    error_message TEXT DEFAULT NULL,
    started_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    completed_at TIMESTAMP NULL DEFAULT NULL,
    metadata JSON DEFAULT NULL,
    FOREIGN KEY (target_id) REFERENCES backup_targets(id) ON DELETE CASCADE,
    INDEX idx_user (user),
    INDEX idx_status (status),
    INDEX idx_started_at (started_at),
    INDEX idx_target_user (target_id, user),
    INDEX idx_multipart_upload_id (multipart_upload_id),
    INDEX idx_creation_status (creation_status),
    INDEX idx_upload_status (upload_status),
    INDEX idx_local_deleted (local_deleted_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- Create backup schedules table
CREATE TABLE IF NOT EXISTS backup_schedules (
    id INT AUTO_INCREMENT PRIMARY KEY,
    user VARCHAR(255) NOT NULL,
    target_id INT NOT NULL,
    backup_type ENUM('site', 'userfiles', 'database', 'wordpress', 'all') NOT NULL COMMENT 'Backup type - site type auto-detects WordPress sites for combined backup',
    resource_name VARCHAR(255) DEFAULT NULL COMMENT 'Optional: specific site domain or database name. If NULL, backs up first available resource',
    schedule_type ENUM('daily', 'weekly', 'monthly') NOT NULL,
    schedule_time TIME NOT NULL DEFAULT '02:00:00',
    schedule_day INT DEFAULT NULL, -- 0=Sunday, 1=Monday, etc. for weekly; 1-31 for monthly
    max_retention INT NOT NULL DEFAULT 30, -- max number of backups to keep
    is_active BOOLEAN DEFAULT TRUE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    last_run_at TIMESTAMP NULL,
    next_run_at TIMESTAMP NULL,
    INDEX idx_user (user),
    INDEX idx_target_id (target_id),
    INDEX idx_next_run (next_run_at, is_active),
    FOREIGN KEY (target_id) REFERENCES backup_targets(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- Create backup queue table for async processing
CREATE TABLE IF NOT EXISTS backup_queue (
    id INT AUTO_INCREMENT PRIMARY KEY,
    target_id INT NOT NULL,
    user VARCHAR(50) NOT NULL,
    backup_type ENUM('site', 'userfiles', 'database', 'wordpress', 'all') NOT NULL,
    backup_name VARCHAR(255) NOT NULL,
    priority ENUM('low', 'normal', 'high') DEFAULT 'normal',
    status ENUM('queued', 'processing', 'completed', 'failed') DEFAULT 'queued',
    attempts INT DEFAULT 0,
    error_message TEXT DEFAULT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    started_at TIMESTAMP NULL DEFAULT NULL,
    completed_at TIMESTAMP NULL DEFAULT NULL,
    FOREIGN KEY (target_id) REFERENCES backup_targets(id) ON DELETE CASCADE,
    INDEX idx_status_priority (status, priority),
    INDEX idx_user (user)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- Create multipart uploads tracking table
CREATE TABLE IF NOT EXISTS multipart_uploads (
    id int(11) NOT NULL AUTO_INCREMENT,
    backup_id int(11) NOT NULL,
    upload_id varchar(255) NOT NULL,
    bucket varchar(255) NOT NULL,
    `key` varchar(500) NOT NULL,
    file_path varchar(500) NOT NULL,
    file_size bigint NOT NULL,
    chunk_size int NOT NULL,
    total_parts int NOT NULL,
    completed_parts text DEFAULT NULL COMMENT 'JSON array of completed part ETags',
    status enum('in_progress','completed','aborted','failed') DEFAULT 'in_progress',
    started_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    completed_at timestamp NULL DEFAULT NULL,
    PRIMARY KEY (id),
    KEY idx_backup_id (backup_id),
    KEY idx_upload_id (upload_id),
    KEY idx_status (status),
    KEY idx_started_at (started_at),
    KEY idx_stale_uploads (status, updated_at),
    CONSTRAINT fk_multipart_backup FOREIGN KEY (backup_id) REFERENCES backup_history (id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

-- Create backup upload queue table
CREATE TABLE IF NOT EXISTS backup_upload_queue (
    id int(11) NOT NULL AUTO_INCREMENT,
    backup_id int(11) NOT NULL,
    priority int DEFAULT 5 COMMENT 'Upload priority (1=highest, 10=lowest)',
    status enum('queued','processing','completed','failed','cancelled') DEFAULT 'queued',
    worker_id varchar(100) DEFAULT NULL COMMENT 'ID of worker processing this upload',
    started_at timestamp NULL DEFAULT NULL,
    completed_at timestamp NULL DEFAULT NULL,
    error_message text DEFAULT NULL,
    retry_count int DEFAULT 0,
    next_retry_at timestamp NULL DEFAULT NULL,
    created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    PRIMARY KEY (id),
    UNIQUE KEY uk_backup_id (backup_id),
    KEY idx_status_priority (status, priority),
    KEY idx_worker_id (worker_id),
    KEY idx_next_retry (next_retry_at),
    CONSTRAINT fk_upload_queue_backup FOREIGN KEY (backup_id) REFERENCES backup_history (id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

-- Create backup local storage management table
CREATE TABLE IF NOT EXISTS backup_local_storage (
    id int(11) NOT NULL AUTO_INCREMENT,
    storage_path varchar(500) NOT NULL COMMENT 'Base path for local backup storage',
    max_size_gb int DEFAULT 100 COMMENT 'Maximum storage size in GB',
    current_size_bytes bigint DEFAULT 0 COMMENT 'Current used space in bytes',
    cleanup_policy enum('immediate','after_upload','age_based','size_based') DEFAULT 'after_upload',
    retention_hours int DEFAULT 24 COMMENT 'Hours to keep local backups (for age_based)',
    low_watermark_gb int DEFAULT 80 COMMENT 'Start cleanup when this size reached (for size_based)',
    is_active tinyint(1) DEFAULT 1,
    created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    PRIMARY KEY (id),
    KEY idx_active (is_active)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

-- Insert default local storage configuration
INSERT INTO backup_local_storage (storage_path, max_size_gb, cleanup_policy, retention_hours)
VALUES ('/docker/backups/local', 100, 'after_upload', 24);

-- ================================================
-- WORDPRESS MANAGEMENT TABLES
-- ================================================

-- Container types that support WP-CLI
CREATE TABLE IF NOT EXISTS wp_cli_containers (
    id INT PRIMARY KEY AUTO_INCREMENT,
    container_image VARCHAR(100) UNIQUE NOT NULL,
    is_active BOOLEAN DEFAULT TRUE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

-- WordPress site installations
CREATE TABLE IF NOT EXISTS wordpress_sites (
    id INT PRIMARY KEY AUTO_INCREMENT,
    user VARCHAR(100) NOT NULL,
    domain VARCHAR(255) NOT NULL,
    container_name VARCHAR(255) NOT NULL,
    site_path VARCHAR(500) DEFAULT '/home/{user}/public_html',
    admin_email VARCHAR(255),
    admin_username VARCHAR(100),
    database_name VARCHAR(64) DEFAULT NULL,
    wp_version VARCHAR(20),
    status ENUM('active', 'inactive', 'maintenance') DEFAULT 'active',
    auto_update_core BOOLEAN DEFAULT FALSE,
    auto_update_plugins BOOLEAN DEFAULT FALSE,
    auto_update_themes BOOLEAN DEFAULT FALSE,
    auto_backup_before_update BOOLEAN DEFAULT TRUE,
    preferred_backup_target_id INT DEFAULT NULL,
    backup_target_id INT DEFAULT NULL,
    is_staging BOOLEAN DEFAULT FALSE,
    parent_site_id INT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    UNIQUE KEY unique_domain (domain),
    INDEX idx_user (user),
    INDEX idx_database_name (database_name),
    INDEX idx_backup_target (backup_target_id),
    INDEX idx_preferred_backup_target (preferred_backup_target_id),
    INDEX idx_container (container_name),
    FOREIGN KEY (parent_site_id) REFERENCES wordpress_sites(id) ON DELETE SET NULL,
    FOREIGN KEY (preferred_backup_target_id) REFERENCES backup_targets(id) ON DELETE SET NULL,
    FOREIGN KEY (backup_target_id) REFERENCES backup_targets(id) ON DELETE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

-- Recommended plugins catalog
CREATE TABLE IF NOT EXISTS wp_recommended_plugins (
    id INT PRIMARY KEY AUTO_INCREMENT,
    slug VARCHAR(100) UNIQUE NOT NULL,
    name VARCHAR(255) NOT NULL,
    description TEXT,
    category VARCHAR(50),
    install_url VARCHAR(500),
    is_active BOOLEAN DEFAULT TRUE,
    sort_order INT DEFAULT 0,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

-- Installed plugins per site
CREATE TABLE IF NOT EXISTS wp_site_plugins (
    id INT PRIMARY KEY AUTO_INCREMENT,
    site_id INT NOT NULL,
    plugin_slug VARCHAR(100) NOT NULL,
    plugin_name VARCHAR(255),
    version VARCHAR(20),
    is_active BOOLEAN DEFAULT TRUE,
    auto_update BOOLEAN DEFAULT FALSE,
    last_updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    UNIQUE KEY unique_site_plugin (site_id, plugin_slug),
    FOREIGN KEY (site_id) REFERENCES wordpress_sites(id) ON DELETE CASCADE,
    INDEX idx_plugin (plugin_slug)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

-- Update history for tracking and rollback
CREATE TABLE IF NOT EXISTS wp_update_history (
    id INT PRIMARY KEY AUTO_INCREMENT,
    site_id INT NOT NULL,
    update_type ENUM('core', 'plugin', 'theme', 'all') NOT NULL,
    item_name VARCHAR(255),
    old_version VARCHAR(20),
    new_version VARCHAR(20),
    status ENUM('in_progress', 'completed', 'failed', 'rolled_back') NOT NULL,
    error_message TEXT,
    backup_id INT,
    started_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    completed_at TIMESTAMP NULL,
    FOREIGN KEY (site_id) REFERENCES wordpress_sites(id) ON DELETE CASCADE,
    INDEX idx_site_updates (site_id, started_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

-- Security settings per site
CREATE TABLE IF NOT EXISTS wp_security_settings (
    id INT PRIMARY KEY AUTO_INCREMENT,
    site_id INT UNIQUE NOT NULL,
    disable_file_editor BOOLEAN DEFAULT TRUE,
    disable_xmlrpc BOOLEAN DEFAULT TRUE,
    hide_wp_version BOOLEAN DEFAULT FALSE,
    disable_directory_browsing BOOLEAN DEFAULT TRUE,
    limit_login_attempts BOOLEAN DEFAULT TRUE,
    security_headers_enabled BOOLEAN DEFAULT TRUE,
    block_php_uploads BOOLEAN DEFAULT TRUE,
    force_strong_passwords BOOLEAN DEFAULT FALSE,
    two_factor_enabled BOOLEAN DEFAULT FALSE,
    change_login_url VARCHAR(50) DEFAULT NULL,
    database_prefix VARCHAR(20) DEFAULT 'wp_',
    last_security_scan TIMESTAMP NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    FOREIGN KEY (site_id) REFERENCES wordpress_sites(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

-- One-time login tokens
CREATE TABLE IF NOT EXISTS wp_login_tokens (
    id INT PRIMARY KEY AUTO_INCREMENT,
    site_id INT NOT NULL,
    token VARCHAR(64) UNIQUE NOT NULL,
    admin_username VARCHAR(100) NOT NULL,
    expires_at TIMESTAMP NOT NULL,
    used BOOLEAN DEFAULT FALSE,
    used_at TIMESTAMP NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (site_id) REFERENCES wordpress_sites(id) ON DELETE CASCADE,
    INDEX idx_token (token, expires_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

-- Add some default recommended plugins
INSERT INTO wp_recommended_plugins (slug, name, description, category, install_url, sort_order) VALUES
('wordfence', 'Wordfence Security', 'Comprehensive security plugin with firewall and malware scanner', 'Security', 'wordfence', 10),
('all-in-one-seo-pack', 'All in One SEO', 'Complete SEO solution for WordPress', 'SEO', 'all-in-one-seo-pack', 20),
('updraftplus', 'UpdraftPlus', 'Backup and restoration plugin', 'Backup', 'updraftplus', 30),
('w3-total-cache', 'W3 Total Cache', 'Improve site performance and user experience', 'Performance', 'w3-total-cache', 40),
('contact-form-7', 'Contact Form 7', 'Create and manage multiple contact forms', 'Forms', 'contact-form-7', 50),
('really-simple-ssl', 'Really Simple SSL', 'Lightweight SSL plugin', 'Security', 'really-simple-ssl', 60)
ON DUPLICATE KEY UPDATE name = VALUES(name);

-- Enable WP-CLI for common container types
INSERT INTO wp_cli_containers (container_image, is_active) VALUES
('PHP 7.4', TRUE),
('PHP 8.0', TRUE),
('PHP 8.1', TRUE),
('PHP 8.2', TRUE),
('PHP 8.3', TRUE),
('PHP 8.4', TRUE)
ON DUPLICATE KEY UPDATE is_active = VALUES(is_active);

-- ================================================
-- CPANEL IMPORT SYSTEM TABLES
-- ================================================

-- Table for tracking cPanel imports
CREATE TABLE IF NOT EXISTS cpanel_imports (
    id INT AUTO_INCREMENT PRIMARY KEY,
    import_id VARCHAR(64) NOT NULL UNIQUE,
    username VARCHAR(32) NOT NULL,
    backup_file VARCHAR(512) NOT NULL,
    status ENUM('pending', 'running', 'completed', 'failed') NOT NULL DEFAULT 'pending',
    progress INT DEFAULT 0,
    error_message TEXT NULL,
    log LONGTEXT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    completed_at TIMESTAMP NULL,
    INDEX idx_username (username),
    INDEX idx_status (status),
    INDEX idx_created (created_at),
    INDEX idx_username_status (username, status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

-- Table for tracking imported domains from cPanel backups
CREATE TABLE IF NOT EXISTS cpanel_imported_domains (
    id INT AUTO_INCREMENT PRIMARY KEY,
    import_id VARCHAR(64) NOT NULL,
    domain VARCHAR(255) NOT NULL,
    domain_type ENUM('primary', 'addon', 'subdomain', 'parked') NOT NULL,
    original_path VARCHAR(512) NULL,
    whp_site_id INT NULL,
    ssl_imported BOOLEAN DEFAULT FALSE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    INDEX idx_import_id (import_id),
    INDEX idx_domain (domain),
    INDEX idx_whp_site_id (whp_site_id),
    INDEX idx_domain_type (domain_type),
    FOREIGN KEY (import_id) REFERENCES cpanel_imports(import_id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

-- Table for tracking imported databases from cPanel backups
CREATE TABLE IF NOT EXISTS cpanel_imported_databases (
    id INT AUTO_INCREMENT PRIMARY KEY,
    import_id VARCHAR(64) NOT NULL,
    original_db_name VARCHAR(255) NOT NULL,
    whp_db_name VARCHAR(255) NOT NULL,
    whp_db_user VARCHAR(255) NOT NULL,
    whp_db_password VARCHAR(255) NOT NULL,
    size_bytes BIGINT DEFAULT 0,
    import_status ENUM('pending', 'completed', 'failed') DEFAULT 'pending',
    error_message TEXT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    INDEX idx_import_id (import_id),
    INDEX idx_original_name (original_db_name),
    INDEX idx_whp_db_name (whp_db_name),
    INDEX idx_import_status (import_status),
    FOREIGN KEY (import_id) REFERENCES cpanel_imports(import_id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

-- Table for tracking imported MySQL users from cPanel backups
CREATE TABLE IF NOT EXISTS cpanel_imported_mysql_users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    import_id VARCHAR(64) NOT NULL,
    original_username VARCHAR(255) NOT NULL,
    whp_username VARCHAR(255) NOT NULL,
    whp_password VARCHAR(255) NOT NULL,
    host VARCHAR(255) DEFAULT 'localhost',
    privileges TEXT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    INDEX idx_import_id (import_id),
    INDEX idx_original_username (original_username),
    INDEX idx_whp_username (whp_username),
    FOREIGN KEY (import_id) REFERENCES cpanel_imports(import_id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

-- Table for tracking file imports from cPanel backups
CREATE TABLE IF NOT EXISTS cpanel_imported_files (
    id INT AUTO_INCREMENT PRIMARY KEY,
    import_id VARCHAR(64) NOT NULL,
    domain VARCHAR(255) NOT NULL,
    source_path VARCHAR(512) NOT NULL,
    destination_path VARCHAR(512) NOT NULL,
    file_count INT DEFAULT 0,
    total_size_bytes BIGINT DEFAULT 0,
    import_status ENUM('pending', 'completed', 'failed') DEFAULT 'pending',
    error_message TEXT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    INDEX idx_import_id (import_id),
    INDEX idx_domain (domain),
    INDEX idx_status (import_status),
    FOREIGN KEY (import_id) REFERENCES cpanel_imports(import_id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

-- Table for tracking additional domains assigned to sites
CREATE TABLE IF NOT EXISTS site_domains (
    id INT AUTO_INCREMENT PRIMARY KEY,
    site_id INT NOT NULL,
    domain VARCHAR(255) NOT NULL,
    domain_type ENUM('primary', 'additional', 'subdomain') NOT NULL DEFAULT 'additional',
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    UNIQUE KEY unique_site_domain (site_id, domain),
    INDEX idx_site_id (site_id),
    INDEX idx_domain (domain),
    INDEX idx_domain_type (domain_type)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

-- Cleanup procedure for old import records (older than 30 days)
DELIMITER //
CREATE PROCEDURE IF NOT EXISTS CleanupOldCpanelImports()
BEGIN
    DECLARE done INT DEFAULT FALSE;
    DECLARE import_id_to_delete VARCHAR(64);
    DECLARE cur CURSOR FOR 
        SELECT import_id FROM cpanel_imports 
        WHERE created_at < DATE_SUB(NOW(), INTERVAL 30 DAY)
        AND status IN ('completed', 'failed');
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;

    OPEN cur;
    
    read_loop: LOOP
        FETCH cur INTO import_id_to_delete;
        IF done THEN
            LEAVE read_loop;
        END IF;
        
        -- Delete all related records (cascade will handle most)
        DELETE FROM cpanel_imports WHERE import_id = import_id_to_delete;
    END LOOP;
    
    CLOSE cur;
END//
DELIMITER ;

-- Create event to run cleanup weekly (if event scheduler is enabled)
CREATE EVENT IF NOT EXISTS cleanup_old_cpanel_imports
ON SCHEDULE EVERY 1 WEEK
STARTS CURRENT_TIMESTAMP + INTERVAL 1 DAY
DO CALL CleanupOldCpanelImports();

-- Note: cPanel import functionality tables created successfully

-- ================================================
-- API SYSTEM TABLES
-- ================================================

-- API Keys table for system-to-system authentication
CREATE TABLE IF NOT EXISTS api_keys (
    id INT AUTO_INCREMENT PRIMARY KEY,
    key_name VARCHAR(255) NOT NULL,
    api_key VARCHAR(64) NOT NULL UNIQUE,
    api_secret VARCHAR(128) NOT NULL,
    created_by VARCHAR(50) NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    last_used_at TIMESTAMP NULL,
    is_active BOOLEAN DEFAULT TRUE,
    permissions JSON DEFAULT NULL,
    rate_limit_per_hour INT DEFAULT 1000,
    usage_count INT DEFAULT 0,
    ip_whitelist TEXT DEFAULT NULL,
    notes TEXT DEFAULT NULL,
    INDEX idx_api_key (api_key),
    INDEX idx_created_by (created_by),
    INDEX idx_active (is_active),
    INDEX idx_last_used (last_used_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

-- API usage logs for monitoring and rate limiting
CREATE TABLE IF NOT EXISTS api_usage_logs (
    id INT AUTO_INCREMENT PRIMARY KEY,
    api_key_id INT NOT NULL,
    endpoint VARCHAR(255) NOT NULL,
    method VARCHAR(10) NOT NULL,
    ip_address VARCHAR(45) NOT NULL,
    user_agent TEXT DEFAULT NULL,
    request_data JSON DEFAULT NULL,
    response_code INT NOT NULL,
    response_time_ms INT DEFAULT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (api_key_id) REFERENCES api_keys(id) ON DELETE CASCADE,
    INDEX idx_api_key_id (api_key_id),
    INDEX idx_endpoint (endpoint),
    INDEX idx_created_at (created_at),
    INDEX idx_ip_address (ip_address)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

-- SSO tokens for auto-login functionality
CREATE TABLE IF NOT EXISTS sso_tokens (
    id INT AUTO_INCREMENT PRIMARY KEY,
    token VARCHAR(64) NOT NULL UNIQUE,
    username VARCHAR(50) NOT NULL,
    api_key_id INT NOT NULL,
    redirect_url VARCHAR(500) DEFAULT NULL,
    expires_at TIMESTAMP NOT NULL,
    used_at TIMESTAMP NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    ip_address VARCHAR(45) NOT NULL,
    FOREIGN KEY (api_key_id) REFERENCES api_keys(id) ON DELETE CASCADE,
    INDEX idx_token (token),
    INDEX idx_username (username),
    INDEX idx_expires_at (expires_at),
    INDEX idx_api_key_id (api_key_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

-- API tokens for temporary authentication (WebSocket connections, etc.)
CREATE TABLE IF NOT EXISTS api_tokens (
    id INT AUTO_INCREMENT PRIMARY KEY,
    token VARCHAR(128) NOT NULL UNIQUE,
    username VARCHAR(50) NOT NULL,
    expires_at DATETIME NOT NULL,
    ip_address VARCHAR(45) NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    INDEX idx_token (token),
    INDEX idx_username (username),
    INDEX idx_expires (expires_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

-- Note: API columns are now included in initial client_allowances table definition

-- Note: API system tables created successfully

-- ================================================
-- Terminal Access Tables
-- ================================================

-- Create table to log terminal access
CREATE TABLE IF NOT EXISTS terminal_access_log (
    id INT AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(255) NOT NULL,
    container_id VARCHAR(255) NOT NULL,
    container_user VARCHAR(255) NOT NULL,
    shell VARCHAR(50) NOT NULL DEFAULT 'bash',
    connected_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    disconnected_at TIMESTAMP NULL,
    commands_executed INT DEFAULT 0,
    INDEX idx_username (username),
    INDEX idx_container (container_id),
    INDEX idx_connected (connected_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

-- Create table for user terminal preferences
CREATE TABLE IF NOT EXISTS terminal_preferences (
    username VARCHAR(255) PRIMARY KEY,
    default_shell VARCHAR(50) DEFAULT 'bash',
    theme VARCHAR(50) DEFAULT 'dark',
    font_size INT DEFAULT 14,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

-- ================================================
-- PostgreSQL Support Tables
-- ================================================

-- PostgreSQL databases tracking table
CREATE TABLE IF NOT EXISTS postgresql_databases (
    id INT AUTO_INCREMENT PRIMARY KEY,
    database_name VARCHAR(255) NOT NULL UNIQUE,
    owner_username VARCHAR(100) NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    size_mb DECIMAL(10,2) DEFAULT 0,
    encoding VARCHAR(50) DEFAULT 'UTF8',
    INDEX idx_owner (owner_username),
    INDEX idx_dbname (database_name)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

-- PostgreSQL users tracking table
CREATE TABLE IF NOT EXISTS postgresql_users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(100) NOT NULL UNIQUE,
    owner_username VARCHAR(100) NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    can_create_db BOOLEAN DEFAULT FALSE,
    connection_limit INT DEFAULT -1,
    INDEX idx_owner (owner_username),
    INDEX idx_username (username)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

-- PostgreSQL user database access table
CREATE TABLE IF NOT EXISTS postgresql_user_database_access (
    id INT AUTO_INCREMENT PRIMARY KEY,
    pg_user_id INT NOT NULL,
    pg_database_id INT NOT NULL,
    privileges TEXT,
    granted_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    UNIQUE KEY unique_user_db (pg_user_id, pg_database_id),
    FOREIGN KEY (pg_user_id) REFERENCES postgresql_users(id) ON DELETE CASCADE,
    FOREIGN KEY (pg_database_id) REFERENCES postgresql_databases(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;


-- WordPress Update Queue Table (from migration 2025.09.19)
CREATE TABLE IF NOT EXISTS wp_update_queue (
    id INT AUTO_INCREMENT PRIMARY KEY,
    site_id INT NOT NULL,
    update_id INT NOT NULL,
    update_type VARCHAR(20) NOT NULL COMMENT 'core, plugins, themes, all',
    backup_id INT DEFAULT NULL COMMENT 'ID of backup that must complete first',
    status ENUM('waiting_for_backup', 'ready', 'processing', 'completed', 'failed') DEFAULT 'waiting_for_backup',
    error_message TEXT DEFAULT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    started_at TIMESTAMP NULL DEFAULT NULL,
    completed_at TIMESTAMP NULL DEFAULT NULL,

    INDEX idx_status (status),
    INDEX idx_backup_id (backup_id),
    INDEX idx_site_id (site_id),
    INDEX idx_created_at (created_at),

    FOREIGN KEY (site_id) REFERENCES wordpress_sites(id) ON DELETE CASCADE,
    FOREIGN KEY (update_id) REFERENCES wp_update_history(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

-- Delegated Users System (from migration 2025.08.62)
CREATE TABLE IF NOT EXISTS delegated_users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(32) NOT NULL UNIQUE,
    password_hash VARCHAR(255) NOT NULL,
    parent_username VARCHAR(32) NOT NULL,
    display_name VARCHAR(100) DEFAULT NULL,
    email VARCHAR(255) DEFAULT NULL,

    -- Permission flags for what this delegated user can access
    can_manage_domains BOOLEAN DEFAULT FALSE,
    can_manage_sites BOOLEAN DEFAULT FALSE,
    can_manage_databases BOOLEAN DEFAULT FALSE,
    can_manage_email BOOLEAN DEFAULT FALSE,
    can_manage_files BOOLEAN DEFAULT FALSE,
    can_manage_backups BOOLEAN DEFAULT FALSE,
    can_view_terminal BOOLEAN DEFAULT FALSE,
    can_manage_wordpress BOOLEAN DEFAULT FALSE,

    -- Resource restrictions
    allowed_domains TEXT DEFAULT NULL COMMENT 'JSON array of specific domains they can access (null = all parent domains)',
    max_domains INT DEFAULT NULL COMMENT 'Maximum domains they can create (null = unlimited within parent allowance)',
    max_databases INT DEFAULT NULL COMMENT 'Maximum databases they can create',
    max_email_accounts INT DEFAULT NULL COMMENT 'Maximum email accounts they can create',

    -- Status and tracking
    is_active BOOLEAN DEFAULT TRUE,
    last_login TIMESTAMP NULL DEFAULT NULL,
    failed_login_attempts INT DEFAULT 0,
    locked_until TIMESTAMP NULL DEFAULT NULL,

    -- Metadata
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    created_by VARCHAR(32) NOT NULL COMMENT 'Who created this delegated user',

    INDEX idx_parent_username (parent_username),
    INDEX idx_username (username),
    INDEX idx_is_active (is_active),
    INDEX idx_created_by (created_by),

    CONSTRAINT chk_delegated_username_format CHECK (username REGEXP '^[a-zA-Z0-9][a-zA-Z0-9._-]*[a-zA-Z0-9]$'),
    CONSTRAINT chk_username_length CHECK (CHAR_LENGTH(username) >= 3 AND CHAR_LENGTH(username) <= 32)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

-- Delegated user sessions for session management
CREATE TABLE IF NOT EXISTS delegated_user_sessions (
    id INT AUTO_INCREMENT PRIMARY KEY,
    session_id VARCHAR(128) NOT NULL UNIQUE,
    delegated_user_id INT NOT NULL,
    ip_address VARCHAR(45) NOT NULL,
    user_agent TEXT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    last_activity TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    expires_at TIMESTAMP NOT NULL,

    INDEX idx_session_id (session_id),
    INDEX idx_delegated_user_id (delegated_user_id),
    INDEX idx_expires_at (expires_at),

    FOREIGN KEY (delegated_user_id) REFERENCES delegated_users(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

-- Delegated user activity log for audit trail (from migration 2025.08.62)
CREATE TABLE IF NOT EXISTS delegated_user_activity (
    id INT AUTO_INCREMENT PRIMARY KEY,
    delegated_user_id INT NOT NULL,
    action VARCHAR(100) NOT NULL,
    resource_type VARCHAR(50) DEFAULT NULL COMMENT 'domain, database, email, etc.',
    resource_id VARCHAR(100) DEFAULT NULL COMMENT 'specific resource identifier',
    details TEXT DEFAULT NULL COMMENT 'JSON details about the action',
    ip_address VARCHAR(45) NOT NULL,
    user_agent TEXT,
    result ENUM('success', 'failure', 'unauthorized') NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,

    INDEX idx_delegated_user_id (delegated_user_id),
    INDEX idx_action (action),
    INDEX idx_resource_type (resource_type),
    INDEX idx_created_at (created_at),
    INDEX idx_result (result),

    FOREIGN KEY (delegated_user_id) REFERENCES delegated_users(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

-- Permissions System (from migration 001_backup_system.sql and others)
CREATE TABLE IF NOT EXISTS permissions (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(100) NOT NULL UNIQUE,
    description TEXT,
    category VARCHAR(50) DEFAULT 'general',
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE IF NOT EXISTS user_permissions (
    id INT AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(32) NOT NULL,
    permission_id INT NOT NULL,
    granted_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    granted_by VARCHAR(32) DEFAULT NULL,
    UNIQUE KEY unique_user_permission (username, permission_id),
    FOREIGN KEY (permission_id) REFERENCES permissions(id) ON DELETE CASCADE,
    INDEX idx_username (username)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- Add backup permissions
INSERT INTO permissions (name, description, category) VALUES
    ('backup_manage_global', 'Manage global backup targets', 'backup'),
    ('backup_view_all', 'View all user backups', 'backup'),
    ('backup_download_all', 'Download all user backups', 'backup'),
    ('backup_delete_all', 'Delete all user backups', 'backup'),
    ('backup_manage_own', 'Manage own backup targets', 'backup'),
    ('backup_create', 'Create backups', 'backup'),
    ('backup_download_own', 'Download own backups', 'backup'),
    ('backup_delete_own', 'Delete own backups', 'backup')
ON DUPLICATE KEY UPDATE description = VALUES(description);

-- Grant backup permissions to root
INSERT INTO user_permissions (username, permission_id)
SELECT 'root', id FROM permissions WHERE name IN (
    'backup_manage_global',
    'backup_view_all',
    'backup_download_all',
    'backup_delete_all',
    'backup_manage_own',
    'backup_create',
    'backup_download_own',
    'backup_delete_own'
)
ON DUPLICATE KEY UPDATE username = VALUES(username);

-- ================================================
-- DNS CHALLENGE TRACKING (WILDCARD SSL)
-- ================================================

-- DNS-01 ACME challenge tracking for wildcard SSL certificates
CREATE TABLE IF NOT EXISTS dns_challenges (
    id INT AUTO_INCREMENT PRIMARY KEY,
    site_id INT NOT NULL,
    domain_name VARCHAR(255) NOT NULL COMMENT 'Base domain (e.g., domain.tld)',
    challenge_fqdn VARCHAR(255) NOT NULL COMMENT 'Full TXT record name (_acme-challenge.domain.tld)',
    challenge_token TEXT NOT NULL COMMENT 'TXT record value from ACME',
    status ENUM('pending', 'created', 'verified', 'completed', 'failed') NOT NULL DEFAULT 'pending',
    error_message TEXT DEFAULT NULL,
    requested_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    verified_at TIMESTAMP NULL DEFAULT NULL,
    completed_at TIMESTAMP NULL DEFAULT NULL,
    FOREIGN KEY (site_id) REFERENCES sites(id) ON DELETE CASCADE,
    INDEX idx_site_id (site_id),
    INDEX idx_domain_name (domain_name),
    INDEX idx_status (status),
    INDEX idx_requested_at (requested_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

-- ================================================
-- Site Builder Projects
-- Tracks which WHP sites have site-builder projects (1:1 relationship with sites)
-- ================================================
CREATE TABLE IF NOT EXISTS site_builder_projects (
    id INT AUTO_INCREMENT PRIMARY KEY,
    site_id INT NOT NULL COMMENT 'FK to sites.id - the WHP site this project belongs to',
    username VARCHAR(32) NOT NULL COMMENT 'Owner username for quick lookups',
    name VARCHAR(255) NOT NULL DEFAULT 'Untitled Site' COMMENT 'Project display name',
    page_count INT DEFAULT 1 COMMENT 'Number of pages in the project',
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    UNIQUE KEY unique_site_project (site_id),
    INDEX idx_username (username),
    FOREIGN KEY (site_id) REFERENCES sites(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

-- ================================================
-- DELEGATED USER TRIGGER AND VIEW (from migration 2025.08.62)
-- ================================================

-- Add trigger to automatically clean up expired delegated sessions
DELIMITER //
CREATE TRIGGER IF NOT EXISTS cleanup_expired_delegated_sessions
    BEFORE INSERT ON delegated_user_sessions
    FOR EACH ROW
BEGIN
    DELETE FROM delegated_user_sessions
    WHERE expires_at < NOW();
END//
DELIMITER ;

-- Create view for active delegated users with parent info
CREATE VIEW IF NOT EXISTS active_delegated_users AS
SELECT
    du.id,
    du.username,
    du.parent_username,
    du.display_name,
    du.email,
    du.can_manage_domains,
    du.can_manage_sites,
    du.can_manage_databases,
    du.can_manage_email,
    du.can_manage_files,
    du.can_manage_backups,
    du.can_view_terminal,
    du.can_manage_wordpress,
    du.allowed_domains,
    du.max_domains,
    du.max_databases,
    du.max_email_accounts,
    du.last_login,
    du.created_at,
    du.created_by,
    ca.max_domains as parent_max_domains,
    ca.max_email_accounts as parent_max_email_accounts
FROM delegated_users du
LEFT JOIN client_allowances ca ON ca.username = du.parent_username
WHERE du.is_active = TRUE;

-- ================================================
-- CONTAINER CRASH EVENTS (for haproxy-crash-monitor.sh daemon)
-- ================================================

CREATE TABLE IF NOT EXISTS container_crash_events (
    id INT AUTO_INCREMENT PRIMARY KEY,
    container_name VARCHAR(100) NOT NULL DEFAULT 'haproxy-manager',
    event_type VARCHAR(20) NOT NULL COMMENT 'die, oom, kill, restart',
    exit_code INT DEFAULT NULL,
    oom_killed TINYINT(1) NOT NULL DEFAULT 0,
    cause VARCHAR(50) NOT NULL COMMENT 'OOM_DOCKER, OOM_KERNEL, SEGFAULT, SIGKILL_EXTERNAL, PROCESS_ERROR, CLEAN_SHUTDOWN, ABORT, UNKNOWN_EXIT_N',
    restart_count INT DEFAULT NULL,
    downtime_seconds INT DEFAULT NULL,
    memory_usage VARCHAR(100) DEFAULT NULL COMMENT 'Container memory usage at time of crash',
    host_memory_free VARCHAR(100) DEFAULT NULL COMMENT 'Host memory state at time of crash',
    dmesg_excerpt TEXT DEFAULT NULL COMMENT 'Relevant kernel log entries',
    container_logs TEXT DEFAULT NULL COMMENT 'Last 50 lines of container logs before crash',
    docker_inspect_json TEXT DEFAULT NULL COMMENT 'Full docker inspect State JSON',
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    INDEX idx_container_crash_name (container_name),
    INDEX idx_container_crash_cause (cause),
    INDEX idx_container_crash_created (created_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

-- ================================================
-- SETUP COMPLETE
-- ================================================

SELECT 'WHP database setup completed successfully!' as status; 