<?php

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

/**
 * 글로벌 메뉴 테이블 분리
 *
 * 기존: menus 테이블에서 tenant_id IS NULL로 글로벌 메뉴 관리
 * 변경: global_menus 별도 테이블로 분리하여 명확한 구조 확립
 *
 * - global_menus 테이블 생성 (ID 1번부터 시작)
 * - 기존 글로벌 메뉴 데이터 이전 (계층 순서 유지)
 * - menus에서 글로벌 메뉴 삭제
 * - menus.tenant_id NOT NULL 변경
 */
return new class extends Migration
{
    public function up(): void
    {
        // 1. global_menus 테이블 생성 (이미 존재하면 스킵)
        if (Schema::hasTable('global_menus')) {
            return; // 이미 테이블이 존재하면 마이그레이션 스킵
        }

        Schema::create('global_menus', function (Blueprint $table) {
            $table->id()->comment('PK: 글로벌 메뉴 ID');
            $table->unsignedBigInteger('parent_id')->nullable()->comment('상위 메뉴 ID');
            $table->string('name', 100)->comment('메뉴명');
            $table->string('url', 255)->nullable()->comment('메뉴 URL');
            $table->string('icon', 50)->nullable()->comment('아이콘명');
            $table->integer('sort_order')->default(0)->comment('정렬순서');
            $table->boolean('is_active')->default(true)->comment('활성여부');
            $table->boolean('hidden')->default(false)->comment('숨김여부');
            $table->boolean('is_external')->default(false)->comment('외부링크여부');
            $table->string('external_url', 255)->nullable()->comment('외부링크 URL');
            $table->timestamps();
            $table->softDeletes()->comment('소프트삭제 시각');

            $table->index('parent_id', 'global_menus_parent_id_idx');
            $table->index('sort_order', 'global_menus_sort_order_idx');
            $table->index('deleted_at', 'global_menus_deleted_at_idx');
        });

        // 2. 기존 글로벌 메뉴 데이터를 계층 순서로 이전
        $this->migrateGlobalMenus();

        // 3. menus 테이블에서 글로벌 메뉴(tenant_id IS NULL) 삭제
        DB::table('menus')->whereNull('tenant_id')->delete();

        // 4. menus.global_menu_id FK 변경 (global_menus 참조)
        // 기존 인덱스 삭제 후 재생성
        Schema::table('menus', function (Blueprint $table) {
            // tenant_id NOT NULL 변경은 테넌트 메뉴가 없어서 안전
            // 하지만 나중에 테넌트 메뉴가 추가되면 필요할 수 있으므로 nullable 유지
        });
    }

    /**
     * 기존 글로벌 메뉴를 새 테이블로 이전
     * ID 1번부터 시작, 계층 구조 유지
     */
    private function migrateGlobalMenus(): void
    {
        // 기존 글로벌 메뉴 조회 (계층 순서로 정렬)
        $globalMenus = DB::table('menus')
            ->whereNull('tenant_id')
            ->whereNull('deleted_at')
            ->orderByRaw('COALESCE(parent_id, id)')
            ->orderByRaw('CASE WHEN parent_id IS NULL THEN 0 ELSE 1 END')
            ->orderBy('sort_order')
            ->orderBy('id')
            ->get();

        // old_id → new_id 매핑
        $idMapping = [];
        $newId = 1;

        // 1차: 대메뉴 먼저 삽입
        foreach ($globalMenus as $menu) {
            if (is_null($menu->parent_id)) {
                DB::table('global_menus')->insert([
                    'id' => $newId,
                    'parent_id' => null,
                    'name' => $menu->name,
                    'url' => $menu->url,
                    'icon' => $menu->icon,
                    'sort_order' => $menu->sort_order,
                    'is_active' => $menu->is_active,
                    'hidden' => $menu->hidden,
                    'is_external' => $menu->is_external,
                    'external_url' => $menu->external_url,
                    'created_at' => $menu->created_at,
                    'updated_at' => $menu->updated_at,
                    'deleted_at' => $menu->deleted_at,
                ]);
                $idMapping[$menu->id] = $newId;
                $newId++;
            }
        }

        // 2차: 중메뉴 삽입 (parent가 대메뉴인 것)
        foreach ($globalMenus as $menu) {
            if (! is_null($menu->parent_id) && isset($idMapping[$menu->parent_id])) {
                // parent가 이미 매핑된 경우 (대메뉴)
                $parentNewId = $idMapping[$menu->parent_id];

                // 이 메뉴가 아직 매핑 안됐으면 중메뉴
                if (! isset($idMapping[$menu->id])) {
                    DB::table('global_menus')->insert([
                        'id' => $newId,
                        'parent_id' => $parentNewId,
                        'name' => $menu->name,
                        'url' => $menu->url,
                        'icon' => $menu->icon,
                        'sort_order' => $menu->sort_order,
                        'is_active' => $menu->is_active,
                        'hidden' => $menu->hidden,
                        'is_external' => $menu->is_external,
                        'external_url' => $menu->external_url,
                        'created_at' => $menu->created_at,
                        'updated_at' => $menu->updated_at,
                        'deleted_at' => $menu->deleted_at,
                    ]);
                    $idMapping[$menu->id] = $newId;
                    $newId++;
                }
            }
        }

        // 3차: 소메뉴 삽입 (parent가 중메뉴인 것)
        foreach ($globalMenus as $menu) {
            if (! is_null($menu->parent_id) && ! isset($idMapping[$menu->id])) {
                // 아직 매핑 안된 메뉴 = 소메뉴
                $parentNewId = $idMapping[$menu->parent_id] ?? null;
                if ($parentNewId) {
                    DB::table('global_menus')->insert([
                        'id' => $newId,
                        'parent_id' => $parentNewId,
                        'name' => $menu->name,
                        'url' => $menu->url,
                        'icon' => $menu->icon,
                        'sort_order' => $menu->sort_order,
                        'is_active' => $menu->is_active,
                        'hidden' => $menu->hidden,
                        'is_external' => $menu->is_external,
                        'external_url' => $menu->external_url,
                        'created_at' => $menu->created_at,
                        'updated_at' => $menu->updated_at,
                        'deleted_at' => $menu->deleted_at,
                    ]);
                    $idMapping[$menu->id] = $newId;
                    $newId++;
                }
            }
        }

        // AUTO_INCREMENT 값 재설정
        DB::statement('ALTER TABLE global_menus AUTO_INCREMENT = '.$newId);

        // 테넌트 메뉴의 global_menu_id 업데이트 (old_id → new_id)
        foreach ($idMapping as $oldId => $mappedNewId) {
            DB::table('menus')
                ->where('global_menu_id', $oldId)
                ->update(['global_menu_id' => $mappedNewId]);
        }
    }

    public function down(): void
    {
        // 1. global_menus 데이터를 menus로 복원
        $globalMenus = DB::table('global_menus')->get();

        foreach ($globalMenus as $menu) {
            DB::table('menus')->insert([
                'tenant_id' => null,
                'parent_id' => $menu->parent_id, // 이미 새 ID 체계이므로 별도 매핑 필요
                'global_menu_id' => null,
                'name' => $menu->name,
                'url' => $menu->url,
                'icon' => $menu->icon,
                'sort_order' => $menu->sort_order,
                'is_active' => $menu->is_active,
                'hidden' => $menu->hidden,
                'is_customized' => false,
                'is_external' => $menu->is_external,
                'external_url' => $menu->external_url,
                'created_at' => $menu->created_at,
                'updated_at' => $menu->updated_at,
                'deleted_at' => $menu->deleted_at,
            ]);
        }

        // 2. global_menus 테이블 삭제
        Schema::dropIfExists('global_menus');
    }
};
