<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;

/**
 * Migration: Índices compostos de performance — LABRE-DX Contest
 *
 * Resolve definitivamente o problema de full-scan em multi-anos.
 * Todas as queries de processamento (Etapas 1–10) e relatórios
 * filtram por contest_id — sem estes índices o MySQL lê todas as
 * linhas independente do ano.
 *
 * Aplicar com: php artisan migrate
 */
return new class extends Migration
{
    public function up(): void
    {
        // ── qsos_result ─────────────────────────────────────────────────────
        // Usada em todas as etapas de validação, cruzamento e pontuação.
        Schema::table('qsos_result', function (Blueprint $table) {

            // Etapas 2, 3, 4, 5, 6, 7 — filtra QSOs válidos de um contest
            if (!$this->indexExists('qsos_result', 'idx_qr_contest_valid')) {
                $table->index(['contest_id', 'valid_qso'], 'idx_qr_contest_valid');
            }

            // Etapas 7, 9, relatórios — filtra confirmados de um contest
            if (!$this->indexExists('qsos_result', 'idx_qr_contest_confirmado')) {
                $table->index(['contest_id', 'confirmado'], 'idx_qr_contest_confirmado');
            }

            // Etapa 5 (cruzamento bilateral) — busca call_sent dentro do contest
            if (!$this->indexExists('qsos_result', 'idx_qr_contest_callsent')) {
                $table->index(['contest_id', 'call_sent'], 'idx_qr_contest_callsent');
            }

            // Relatórios por banda dentro de um contest
            if (!$this->indexExists('qsos_result', 'idx_qr_contest_band')) {
                $table->index(['contest_id', 'band'], 'idx_qr_contest_band');
            }
        });

        // ── logs_cabecalhos ──────────────────────────────────────────────────
        // Ponto de entrada de todas as etapas — lista os LOGs do contest.
        Schema::table('logs_cabecalhos', function (Blueprint $table) {
            if (!$this->indexExists('logs_cabecalhos', 'idx_lc_contest_id')) {
                $table->index('contest_id', 'idx_lc_contest_id');
            }
        });

        // ── resultados_final ─────────────────────────────────────────────────
        // Etapa 10 e relatório de resultados.
        Schema::table('resultados_final', function (Blueprint $table) {

            // Ranking geral do contest (ORDER BY rk)
            if (!$this->indexExists('resultados_final', 'idx_rf_contest_rk')) {
                $table->index(['contest_id', 'rk'], 'idx_rf_contest_rk');
            }

            // Ranking por categoria dentro do contest
            if (!$this->indexExists('resultados_final', 'idx_rf_contest_categoria')) {
                $table->index(['contest_id', 'categoria'], 'idx_rf_contest_categoria');
            }
        });

        // ── logs_qsos ────────────────────────────────────────────────────────
        // log_id é FK para logs_cabecalhos.id — garante índice se não houver PK.
        // (Normalmente já é PK; esta linha é segura pois verifica antes.)
        Schema::table('logs_qsos', function (Blueprint $table) {
            if (!$this->indexExists('logs_qsos', 'idx_lq_log_id') &&
                !$this->indexExists('logs_qsos', 'PRIMARY')) {
                $table->index('log_id', 'idx_lq_log_id');
            }
        });
    }

    public function down(): void
    {
        Schema::table('qsos_result', function (Blueprint $table) {
            foreach ([
                'idx_qr_contest_valid',
                'idx_qr_contest_confirmado',
                'idx_qr_contest_callsent',
                'idx_qr_contest_band',
            ] as $idx) {
                if ($this->indexExists('qsos_result', $idx)) {
                    $table->dropIndex($idx);
                }
            }
        });

        Schema::table('logs_cabecalhos', function (Blueprint $table) {
            if ($this->indexExists('logs_cabecalhos', 'idx_lc_contest_id')) {
                $table->dropIndex('idx_lc_contest_id');
            }
        });

        Schema::table('resultados_final', function (Blueprint $table) {
            foreach (['idx_rf_contest_rk', 'idx_rf_contest_categoria'] as $idx) {
                if ($this->indexExists('resultados_final', $idx)) {
                    $table->dropIndex($idx);
                }
            }
        });

        Schema::table('logs_qsos', function (Blueprint $table) {
            if ($this->indexExists('logs_qsos', 'idx_lq_log_id')) {
                $table->dropIndex('idx_lq_log_id');
            }
        });
    }

    // ── Helper: verifica existência de índice sem exceção ────────────────────
    private function indexExists(string $table, string $indexName): bool
    {
        $result = DB::select(
            "SELECT COUNT(1) as found
               FROM information_schema.STATISTICS
              WHERE table_schema = DATABASE()
                AND table_name   = ?
                AND index_name   = ?",
            [$table, $indexName]
        );

        return (int) ($result[0]->found ?? 0) > 0;
    }
};
