<?php

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

/**
 * 일간 통계 테이블 RANGE 파티셔닝 준비
 *
 * 실행 방법: php artisan migrate --path=database/migrations/stats/2026_01_29_300001_prepare_partitioning_daily_tables.php
 *
 * 주의: MySQL에서 파티셔닝 적용 시 UNIQUE KEY에 파티션 컬럼(stat_date)이 포함되어야 합니다.
 *       이 마이그레이션은 기존 데이터를 보존하며 파티셔닝을 적용합니다.
 */
return new class extends Migration
{
    protected $connection = 'sam_stat';

    /**
     * 파티셔닝 대상 테이블과 고유 키 정의
     */
    private function getTargetTables(): array
    {
        return [
            'stat_sales_daily' => [
                'unique_columns' => 'tenant_id, stat_date',
                'unique_name' => 'uk_tenant_date',
            ],
            'stat_finance_daily' => [
                'unique_columns' => 'tenant_id, stat_date',
                'unique_name' => 'uk_tenant_date',
            ],
            'stat_production_daily' => [
                'unique_columns' => 'tenant_id, stat_date',
                'unique_name' => 'uk_tenant_date',
            ],
            'stat_inventory_daily' => [
                'unique_columns' => 'tenant_id, stat_date',
                'unique_name' => 'uk_tenant_date',
            ],
            'stat_quote_pipeline_daily' => [
                'unique_columns' => 'tenant_id, stat_date',
                'unique_name' => 'uk_tenant_date',
            ],
            'stat_hr_attendance_daily' => [
                'unique_columns' => 'tenant_id, stat_date',
                'unique_name' => 'uk_tenant_date',
            ],
            'stat_system_daily' => [
                'unique_columns' => 'tenant_id, stat_date',
                'unique_name' => 'uk_tenant_date',
            ],
        ];
    }

    /**
     * 연도별 파티션 정의 생성 (2024~2028 + MAXVALUE)
     */
    private function getPartitionDefinitions(): string
    {
        $partitions = [];
        for ($year = 2024; $year <= 2028; $year++) {
            $partitions[] = "PARTITION p{$year} VALUES LESS THAN ('{$year}-01-01')";
        }
        $partitions[] = 'PARTITION p_future VALUES LESS THAN MAXVALUE';

        return implode(",\n    ", $partitions);
    }

    public function up(): void
    {
        $tables = $this->getTargetTables();
        $partitionDefs = $this->getPartitionDefinitions();

        foreach ($tables as $table => $config) {
            // 테이블 존재 여부 확인
            $exists = DB::connection('sam_stat')
                ->select("SHOW TABLES LIKE '{$table}'");

            if (empty($exists)) {
                continue;
            }

            // 이미 파티셔닝되어 있는지 확인
            $partitionInfo = DB::connection('sam_stat')
                ->select('SELECT PARTITION_NAME FROM INFORMATION_SCHEMA.PARTITIONS
                          WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ? AND PARTITION_NAME IS NOT NULL',
                    [$table]);

            if (! empty($partitionInfo)) {
                continue; // 이미 파티셔닝됨
            }

            // AUTO_INCREMENT PK를 일반 PK로 변경 (파티션 키 포함)
            // MySQL 파티셔닝 제약: UNIQUE KEY에 파티션 컬럼 포함 필수
            DB::connection('sam_stat')->statement("
                ALTER TABLE `{$table}`
                DROP PRIMARY KEY,
                ADD PRIMARY KEY (`id`, `stat_date`),
                DROP INDEX `{$config['unique_name']}`,
                ADD UNIQUE KEY `{$config['unique_name']}` ({$config['unique_columns']})
            ");

            // RANGE 파티셔닝 적용
            DB::connection('sam_stat')->statement("
                ALTER TABLE `{$table}`
                PARTITION BY RANGE COLUMNS(`stat_date`) (
                    {$partitionDefs}
                )
            ");
        }
    }

    public function down(): void
    {
        $tables = $this->getTargetTables();

        foreach ($tables as $table => $config) {
            $exists = DB::connection('sam_stat')
                ->select("SHOW TABLES LIKE '{$table}'");

            if (empty($exists)) {
                continue;
            }

            // 파티션 제거
            DB::connection('sam_stat')->statement("
                ALTER TABLE `{$table}` REMOVE PARTITIONING
            ");

            // PK 원복
            DB::connection('sam_stat')->statement("
                ALTER TABLE `{$table}`
                DROP PRIMARY KEY,
                ADD PRIMARY KEY (`id`)
            ");
        }
    }
};
