<?php

namespace classes;

/**
 * Ensures additive system session activity storage exists.
 *
 * This project uses lazy runtime schema bootstraps instead of a central
 * migration runner, so every change must be idempotent.
 */
class system_session_activity_schema_bootstrap
{
    private static bool $initialized = false;

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

        global $db;

        $queries = [
            "CREATE TABLE IF NOT EXISTS system_session_activity (
                id INT AUTO_INCREMENT PRIMARY KEY,
                session_hash CHAR(64) NOT NULL,
                session_kind VARCHAR(16) NOT NULL,
                principal_id INT NOT NULL,
                customer_number_context INT NULL,
                device_type VARCHAR(16) NOT NULL DEFAULT 'unknown',
                user_agent VARCHAR(1024) NULL,
                last_route VARCHAR(255) NULL,
                first_seen_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
                last_seen_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
                created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
                updated_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
                UNIQUE KEY uniq_system_session_activity_session_hash (session_hash),
                INDEX idx_system_session_activity_last_seen_at (last_seen_at),
                INDEX idx_system_session_activity_principal (session_kind, principal_id),
                INDEX idx_system_session_activity_customer_context (customer_number_context)
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci",
        ];

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

        self::ensureColumn(
            'system_session_activity',
            'customer_number_context',
            'ALTER TABLE system_session_activity ADD COLUMN customer_number_context INT NULL AFTER principal_id'
        );
        self::ensureColumn(
            'system_session_activity',
            'device_type',
            "ALTER TABLE system_session_activity ADD COLUMN device_type VARCHAR(16) NOT NULL DEFAULT 'unknown' AFTER customer_number_context"
        );
        self::ensureColumn(
            'system_session_activity',
            'user_agent',
            'ALTER TABLE system_session_activity ADD COLUMN user_agent VARCHAR(1024) NULL AFTER device_type'
        );
        self::ensureColumn(
            'system_session_activity',
            'last_route',
            'ALTER TABLE system_session_activity ADD COLUMN last_route VARCHAR(255) NULL AFTER user_agent'
        );
        self::ensureColumn(
            'system_session_activity',
            'first_seen_at',
            'ALTER TABLE system_session_activity ADD COLUMN first_seen_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP AFTER last_route'
        );
        self::ensureColumn(
            'system_session_activity',
            'last_seen_at',
            'ALTER TABLE system_session_activity ADD COLUMN last_seen_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP AFTER first_seen_at'
        );
        self::ensureColumn(
            'system_session_activity',
            'created_at',
            'ALTER TABLE system_session_activity ADD COLUMN created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP AFTER last_seen_at'
        );
        self::ensureColumn(
            'system_session_activity',
            'updated_at',
            'ALTER TABLE system_session_activity ADD COLUMN updated_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP AFTER created_at'
        );

        self::$initialized = true;
    }

    public static function tableHasColumn(string $table, string $column): bool
    {
        global $db;

        $table = $db->escape_string($table);
        $column = $db->escape_string($column);
        $database = $db->escape_string($db->getDatabase());

        $sql = "SELECT COUNT(*) AS c
                FROM information_schema.COLUMNS
                WHERE TABLE_SCHEMA = '$database'
                  AND TABLE_NAME = '$table'
                  AND COLUMN_NAME = '$column'";
        $result = $db->query($sql);
        if (!$result) {
            return false;
        }

        $row = $result->fetch_assoc();
        return ((int)($row['c'] ?? 0)) > 0;
    }

    public static function ensureColumn(string $table, string $column, string $alterSql): void
    {
        global $db;

        if (self::tableHasColumn($table, $column)) {
            return;
        }

        $db->query($alterSql);
    }
}
