<?php

namespace classes;

class cron_schema_bootstrap
{
    private static bool $initialized = false;

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

        global $db;

        if (!isset($db) || !is_object($db) || !method_exists($db, 'query')) {
            return;
        }

        $db->query(
            "CREATE TABLE IF NOT EXISTS cron_task_state (
                task_id VARCHAR(191) NOT NULL PRIMARY KEY,
                module VARCHAR(64) NOT NULL,
                enabled TINYINT(1) NOT NULL DEFAULT 1,
                schedule_json LONGTEXT NULL,
                last_run_at DATETIME NULL,
                next_run_at DATETIME NULL,
                locked_until DATETIME NULL,
                lock_owner VARCHAR(191) NULL,
                current_run_id BIGINT UNSIGNED NULL,
                last_status VARCHAR(32) NULL,
                last_error TEXT NULL,
                created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
                updated_at TIMESTAMP NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
                KEY idx_cron_task_state_next_run (enabled, next_run_at),
                KEY idx_cron_task_state_lock (locked_until)
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci"
        );

        $db->query(
            "CREATE TABLE IF NOT EXISTS cron_task_runs (
                id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
                task_id VARCHAR(191) NOT NULL,
                module VARCHAR(64) NOT NULL,
                source VARCHAR(32) NOT NULL,
                status VARCHAR(32) NOT NULL DEFAULT 'running',
                actor_user_id INT NULL,
                scheduled_for DATETIME NULL,
                started_at DATETIME NULL,
                completed_at DATETIME NULL,
                duration_ms INT UNSIGNED NULL,
                summary_json LONGTEXT NULL,
                error_message TEXT NULL,
                lock_owner VARCHAR(191) NULL,
                force_run TINYINT(1) NOT NULL DEFAULT 0,
                created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
                updated_at TIMESTAMP NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
                KEY idx_cron_task_runs_task_created (task_id, created_at),
                KEY idx_cron_task_runs_status_created (status, created_at),
                KEY idx_cron_task_runs_module_created (module, created_at)
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci"
        );
        self::ensureColumn('cron_task_runs', 'force_run', 'TINYINT(1) NOT NULL DEFAULT 0 AFTER lock_owner');

        $db->query(
            "CREATE TABLE IF NOT EXISTS cron_worker_state (
                worker_id VARCHAR(191) NOT NULL PRIMARY KEY,
                name VARCHAR(191) NOT NULL,
                hostname VARCHAR(191) NULL,
                pid INT UNSIGNED NULL,
                source VARCHAR(64) NOT NULL DEFAULT 'coolify_worker',
                status VARCHAR(32) NOT NULL DEFAULT 'starting',
                release_channel_id BIGINT UNSIGNED NULL,
                release_target_id BIGINT UNSIGNED NULL,
                coolify_resource_uuid VARCHAR(128) NULL,
                coolify_resource_type VARCHAR(32) NULL,
                commit_sha VARCHAR(64) NULL,
                poll_seconds INT UNSIGNED NOT NULL DEFAULT 15,
                last_run_count INT UNSIGNED NOT NULL DEFAULT 0,
                last_stale_run_count INT UNSIGNED NOT NULL DEFAULT 0,
                last_error TEXT NULL,
                started_at DATETIME NULL,
                last_heartbeat_at DATETIME NULL,
                last_loop_started_at DATETIME NULL,
                last_loop_finished_at DATETIME NULL,
                stopped_at DATETIME NULL,
                created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
                updated_at TIMESTAMP NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
                KEY idx_cron_worker_state_heartbeat (last_heartbeat_at),
                KEY idx_cron_worker_state_status (status),
                KEY idx_cron_worker_state_release_target (release_target_id),
                KEY idx_cron_worker_state_coolify_resource (coolify_resource_uuid)
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci"
        );

        self::$initialized = true;
    }

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

        $table = preg_replace('/[^a-zA-Z0-9_]/', '', $table);
        $column = preg_replace('/[^a-zA-Z0-9_]/', '', $column);
        if ($table === '' || $column === '') {
            return;
        }

        $result = $db->query("SHOW COLUMNS FROM `{$table}` LIKE '{$column}'");
        if ($result && $result->num_rows > 0) {
            return;
        }

        $db->query("ALTER TABLE `{$table}` ADD COLUMN `{$column}` {$definition}");
    }
}
