<?php

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

return new class extends Migration {
    public function up(): void
    {
        if (!Schema::hasTable('egame_items')) {
            return;
        }

        if (!Schema::hasColumn('egame_items', 'lobby_enabled')) {
            Schema::table('egame_items', function (Blueprint $table) {
                $table->unsignedTinyInteger('lobby_enabled')
                    ->default(0)
                    ->after('logo_langs')
                    ->comment('1允许无gameCode进入平台大厅 0不允许');
            });
        }

        $now = date('Y-m-d H:i:s');
        $gameTypes = $this->gameTypes();
        $platforms = $this->platforms();
        $lobbyTypes = $this->platformGameTypes();
        $visibleTypes = $this->platformVisibleTypes();
        $categoryLogos = $this->categoryLogos();

        $categorySort = count($gameTypes);
        foreach ($gameTypes as $gameType => $name) {
            $this->ensureCatalogRow(
                'category',
                '',
                $gameType,
                $name,
                $categoryLogos[$gameType] ?? '',
                1,
                0,
                $categorySort--,
                $now
            );
        }

        $existingNames = $this->existingPlatformNames();
        $allPlatformNames = $platforms;
        $configuredPlatformTypes = array_fill_keys(array_keys($platforms), true);
        foreach (array_keys($lobbyTypes) as $platType) {
            $this->addPlatformName($allPlatformNames, $platType, $existingNames);
        }
        foreach ($visibleTypes as $platTypes) {
            foreach ($platTypes as $platType) {
                $this->addPlatformName($allPlatformNames, $platType, $existingNames);
            }
        }
        foreach ($existingNames as $platType => $name) {
            $this->addPlatformName($allPlatformNames, $platType, $existingNames);
        }

        $platformSort = count($platforms);
        foreach ($allPlatformNames as $platType => $name) {
            $this->ensureCatalogRow(
                'platform',
                $platType,
                0,
                $name,
                '',
                isset($configuredPlatformTypes[$platType]) ? 1 : 0,
                0,
                isset($platforms[$platType]) ? $platformSort-- : 0,
                $now
            );
        }

        $visibleRelations = $this->relationSet($visibleTypes);
        $lobbyRelations = $this->relationSet($lobbyTypes);

        // Existing relation switches are only tightened here. A visible relation
        // that an administrator already closed must never be reopened.
        $existingRelations = DB::table('egame_items')
            ->where('item_type', 'platform')
            ->where('game_type', '>', 0)
            ->get(['id', 'plat_type', 'game_type', 'status', 'lobby_enabled']);
        foreach ($existingRelations as $relation) {
            $key = $this->relationKey((string)$relation->plat_type, (int)$relation->game_type);
            $updates = [];
            if (!isset($visibleRelations[$key]) && (int)$relation->status !== 0) {
                $updates['status'] = 0;
            }
            if (isset($lobbyRelations[$key]) && (int)$relation->lobby_enabled !== 1) {
                $updates['lobby_enabled'] = 1;
            }
            if ($updates !== []) {
                $updates['updated_at'] = $now;
                DB::table('egame_items')->where('id', $relation->id)->update($updates);
            }
        }

        $relationPairs = $visibleRelations + $lobbyRelations;
        $existingGamePairs = DB::table('egame_items')
            ->where('item_type', 'game')
            ->where('plat_type', '<>', '')
            ->where('game_type', '>', 0)
            ->distinct()
            ->get(['plat_type', 'game_type']);
        foreach ($existingGamePairs as $pair) {
            $key = $this->relationKey((string)$pair->plat_type, (int)$pair->game_type);
            $relationPairs[$key] = [
                'plat_type' => strtolower(trim((string)$pair->plat_type)),
                'game_type' => (int)$pair->game_type,
            ];
        }

        foreach ($relationPairs as $key => $relation) {
            $platType = $relation['plat_type'];
            $gameType = $relation['game_type'];
            $isVisible = isset($visibleRelations[$key]);
            $isLobby = isset($lobbyRelations[$key]);
            $name = $allPlatformNames[$platType]
                ?? $existingNames[$platType]
                ?? strtoupper($platType);

            $this->ensureCatalogRow(
                'platform',
                $platType,
                $gameType,
                $name,
                '',
                $isVisible ? 1 : 0,
                $isLobby ? 1 : 0,
                0,
                $now
            );

            $query = $this->catalogRowQuery('platform', $platType, $gameType);
            $current = $query->first(['status', 'lobby_enabled']);
            $updates = [];
            if (!$isVisible && $current && (int)$current->status !== 0) {
                $updates['status'] = 0;
            }
            if ($isLobby && $current && (int)$current->lobby_enabled !== 1) {
                $updates['lobby_enabled'] = 1;
            }
            if ($updates !== []) {
                $updates['updated_at'] = $now;
                $query->update($updates);
            }
        }
    }

    public function down(): void
    {
        // This is an irreversible data migration. Keep both the seeded catalog
        // rows and lobby_enabled state; dropping only the column would leave the
        // catalog marker rows behind and create an unsafe half-rollback state.
    }

    private function ensureCatalogRow(
        string $itemType,
        string $platType,
        int $gameType,
        string $name,
        string $logo,
        int $status,
        int $lobbyEnabled,
        int $sort,
        string $now
    ): bool {
        $query = $this->catalogRowQuery($itemType, $platType, $gameType);
        $row = $query->first(['id', 'name', 'logo']);
        if ($row) {
            $updates = [];
            if (trim((string)$row->name) === '' && $name !== '') {
                $updates['name'] = $name;
            }
            if (trim((string)$row->logo) === '' && $logo !== '') {
                $updates['logo'] = $logo;
            }
            if ($updates !== []) {
                $updates['updated_at'] = $now;
                DB::table('egame_items')->where('id', $row->id)->update($updates);
            }
            return false;
        }

        DB::table('egame_items')->insertOrIgnore([
            'item_type' => $itemType,
            'plat_type' => $platType,
            'game_type' => $gameType,
            'game_code' => '',
            'name' => $name,
            'ingress' => '3',
            'logo' => $logo,
            'logo_langs' => null,
            'lobby_enabled' => $lobbyEnabled,
            'status' => $status,
            'sort' => $sort,
            'created_at' => $now,
            'updated_at' => $now,
        ]);

        return true;
    }

    private function catalogRowQuery(string $itemType, string $platType, int $gameType)
    {
        return DB::table('egame_items')
            ->where('item_type', $itemType)
            ->where('plat_type', strtolower(trim($platType)))
            ->where('game_type', $gameType)
            ->where('game_code', '');
    }

    private function existingPlatformNames(): array
    {
        $names = [];
        $rows = DB::table('egame_items')
            ->where('plat_type', '<>', '')
            ->orderBy('id')
            ->get(['plat_type', 'name']);
        foreach ($rows as $row) {
            $platType = strtolower(trim((string)$row->plat_type));
            if ($platType === '') {
                continue;
            }
            $name = trim((string)$row->name);
            if (!isset($names[$platType]) || ($names[$platType] === '' && $name !== '')) {
                $names[$platType] = $name !== '' ? $name : strtoupper($platType);
            }
        }

        return $names;
    }

    private function addPlatformName(array &$platforms, string $platType, array $existingNames): void
    {
        $platType = strtolower(trim($platType));
        if ($platType === '' || isset($platforms[$platType])) {
            return;
        }
        $platforms[$platType] = $existingNames[$platType] ?? strtoupper($platType);
    }

    private function relationSet(array $typesByPlatformOrType): array
    {
        $relations = [];
        $isPlatformMap = $typesByPlatformOrType !== []
            && is_string(array_key_first($typesByPlatformOrType));

        if ($isPlatformMap) {
            foreach ($typesByPlatformOrType as $platType => $gameTypes) {
                foreach ($gameTypes as $gameType) {
                    $this->addRelation($relations, (string)$platType, (int)$gameType);
                }
            }
            return $relations;
        }

        foreach ($typesByPlatformOrType as $gameType => $platTypes) {
            foreach ($platTypes as $platType) {
                $this->addRelation($relations, (string)$platType, (int)$gameType);
            }
        }

        return $relations;
    }

    private function addRelation(array &$relations, string $platType, int $gameType): void
    {
        $platType = strtolower(trim($platType));
        if ($platType === '' || $gameType <= 0) {
            return;
        }
        $relations[$this->relationKey($platType, $gameType)] = [
            'plat_type' => $platType,
            'game_type' => $gameType,
        ];
    }

    private function relationKey(string $platType, int $gameType): string
    {
        return strtolower(trim($platType)) . '|' . $gameType;
    }

    private function gameTypes(): array
    {
        return [
            1 => '视讯',
            2 => '电子',
            3 => '彩票',
            4 => '体育',
            5 => '电竞',
            6 => '捕鱼',
            7 => '棋牌',
        ];
    }

    private function categoryLogos(): array
    {
        return [
            1 => '/static/img/game-type/sx.png',
            2 => '/static/img/game-type/dz.png',
            3 => '/static/img/game-type/cp1.png',
            4 => '/static/img/game-type/ty.png',
            5 => '/static/img/game-type/dj.png',
            6 => '/static/img/game-type/by.png',
            7 => '/static/img/game-type/qp.png',
        ];
    }

    private function platforms(): array
    {
        return [
            'ag' => 'Choice',
            'allbet' => '欧博',
            'ap' => '平博',
            'bbin' => '宝盈',
            'bg' => 'BG',
            'boya' => '博雅',
            'cmd' => 'CMD',
            'cq9' => 'CQ9',
            'crown' => '皇冠',
            'db1' => 'DB视讯',
            'db2' => 'DB2',
            'db3' => 'DB彩票',
            'db5' => 'DB电竞',
            'db6' => 'DB6',
            'db7' => 'DB7',
            'dg' => 'DG',
            'esb' => '电竞牛',
            'evo' => 'EVO',
            'fb' => 'FB',
            'fc' => 'FC',
            'fg' => 'FG',
            'im' => 'IM体育',
            'jdb' => '夺宝',
            'joker' => 'Joker',
            'km' => 'KM',
            'ky' => '开元棋牌',
            'leg' => 'LEG',
            'lgd' => 'LGD',
            'mg' => 'MG',
            'mt' => 'MT',
            'mw' => 'MW',
            'newbb' => 'NewBB',
            'nw' => 'NW',
            'og' => 'OG',
            'panda' => '熊猫体育',
            'pg' => 'PG',
            'pgs' => 'PGS',
            'png' => 'PNG',
            'pp' => '王者',
            'pt' => 'PT',
            'rsg' => 'RSG',
            'sa' => '沙龙',
            'saba' => '沙巴体育',
            'sexy' => 'Sexy',
            'sg' => 'SG',
            'sgwin' => '双赢彩票',
            'ss' => '三昇',
            't1' => 'T1',
            'tcg' => '天成彩票',
            'tf' => '雷火电竞',
            'v8' => 'V8棋牌',
            'vg' => 'VG',
            'vr' => 'VR彩票',
            'we' => 'WE',
            'wl' => 'WL',
            'wm' => '完美',
            'ww' => 'WW',
            'xgd' => 'XGD',
            'xj' => '小金体育',
            'yoo' => 'YOO',
        ];
    }

    private function platformGameTypes(): array
    {
        return [
            'allbet' => [1],
            'ap' => [4],
            'bg' => [1, 6, 7],
            'cmd' => [4],
            'crown' => [4],
            'db1' => [1],
            'db3' => [3],
            'db5' => [5],
            'dg' => [1],
            'esb' => [5],
            'evo' => [1],
            'fb' => [4],
            'im' => [4],
            'newbb' => [4],
            'og' => [1],
            'ag' => [1, 2, 6],
            'panda' => [4],
            'png' => [2],
            'sa' => [1],
            'saba' => [4],
            'sexy' => [1],
            'sg' => [2],
            'sgwin' => [3],
            'ss' => [4],
            'tcg' => [3],
            'tf' => [5],
            'v8' => [7],
            'vr' => [3],
            'we' => [1],
            'wm' => [1],
            'xj' => [4],
        ];
    }

    private function platformVisibleTypes(): array
    {
        return [
            1 => ['db1', 'og', 'bbin', 'bg', 'ag'],
            2 => ['ag', 'as', 'bbin', 'db2', 'fg', 'jdb', 'pg'],
            4 => ['crown', 'im', 'panda', 'saba'],
            6 => ['db6', 'fg', 'jdb', 'cq9', 'ag'],
            7 => ['db7', 'jdb', 'ky', 'bbin'],
        ];
    }
};
