<?php

namespace App\Console\Commands;

use App\Models\Platform;
use Illuminate\Console\Attributes\Description;
use Illuminate\Console\Attributes\Signature;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;

#[Signature('migrate:games:execute')]
#[Description("Migrate all games from WP posts.")]
class MigrateGamesExecute extends Command
{
    private const array WP_CPTS = [ 'translations', 'romhacks', 'homebrew', 'utilities', 'documents', 'lua-scripts' ];
    private const array RELATED_TAXS = ['game', 'platform', 'genre'];
    private const int DEFAULT_GENRE_ID = 1;
    private const int NO_GENRE_SENTINEL = 0;

    public function handle()
    {
        $rows = DB::connection('old_wp')
            ->table('term_relationships as tr')
            ->join('term_taxonomy as tt', 'tr.term_taxonomy_id', '=', 'tt.term_taxonomy_id')
            ->join('posts as p', 'tr.object_id', '=', 'p.ID')
            ->whereIn('tt.taxonomy', self::RELATED_TAXS )
            ->whereIn('p.post_type', self::WP_CPTS )
            ->where('p.post_status', '!=', 'trash')
            ->select('p.ID as post_id', 'tt.taxonomy', 'tt.term_taxonomy_id' )
            ->get();

        $byPost = [];
        $ignored = 0;
        foreach( $rows as $row ){
            if( isset( $byPost[ $row->post_id ][$row->taxonomy] ) ){
                $ignored++;
                continue;
            }
            $byPost[ $row->post_id ][$row->taxonomy] = $row->term_taxonomy_id;
        }
        if( $ignored ){
            $this->warn("$ignored posts with multiple taxs will be ignored.");
        }

        $structure = [];
        $ignoredNoPlatform = 0;

        foreach ( $byPost as $data )
        {
            if( empty( $data['game'] ) )
                continue;

            if( empty( $data['platform'] ) ){
                $ignoredNoPlatform++;
                continue;
            }

            $gameId = $data['game'];
            $platformId = $data['platform'];
            $genreId = $data['genre'] ?? self::NO_GENRE_SENTINEL;

            $structure[$gameId][$platformId]['count'] = ( $structure[$gameId][$platformId]['count'] ?? 0 ) + 1;
            $structure[$gameId][$platformId]['genres'][$genreId] = ( $structure[$gameId][$platformId]['genres'][$genreId] ?? 0 ) + 1;
        }
        if( $ignoredNoPlatform ){
            $this->warn("$ignoredNoPlatform posts with no platforms will be ignored.");
        }

        $games = DB::connection('old_wp')
            ->table('term_taxonomy')
            ->join('terms', 'term_taxonomy.term_id', '=', 'terms.term_id')
            ->where('term_taxonomy.taxonomy', 'game' )
            ->select('term_taxonomy.term_taxonomy_id', 'terms.name', 'terms.slug' )
            ->get()
            ->keyBy('term_taxonomy_id');

        $platformMap = DB::table('migrations_logs')
            ->where('source_system', 'wp' )
            ->where('target_table', 'platforms')
            ->pluck('target_id', 'source_id');

        $genreMap = DB::table('migrations_logs')
            ->where('source_system', 'wp' )
            ->where('target_table', 'genres')
            ->pluck('target_id', 'source_id');

        if( $this->ask("Are you sure you want launch that migration? Write ok if you want to launch it.", "") !== 'ok' ){
            return self::SUCCESS;
        }

        $created = 0;
        $genreConflicts = 0;

        foreach( $structure as $gameId => $platforms )
        {
            $game = $games->get( $gameId );
            if( !$game )
                continue;

            foreach( $platforms as $platformId => $info )
            {
                $alreadyExists = DB::table('migration_game_plan')
                    ->where('wp_game_id', $gameId )
                    ->where('wp_platform_id', $platformId )
                    ->exists();
                if( $alreadyExists )
                    continue;

                $newPlatformId = $platformMap[$platformId] ?? null;
                if( !$newPlatformId ){
                    $this->warn("$gameId ignored because platform $platformId does not exist in Laravel.");
                    continue;
                }

                $genres = $info['genres'];
                $newGenreId = null;
                $topId = null;
                $genreConflict = false;

                arsort( $genres );
                $topId = array_key_first( $genres );
                $topCount = $genres[$topId];
                $tied = count(array_filter(
                   $genres, fn( $c ) => $c === $topCount
                ));
                if( $tied > 1 ){
                    $genreConflict = true;
                    $genreConflicts++;
                }
                $newGenreId = $topId === self::NO_GENRE_SENTINEL
                    ? self::DEFAULT_GENRE_ID
                    : ($genreMap[$topId] ?? self::DEFAULT_GENRE_ID);

                $gameSlug = $game->slug;
                if (count($platforms) > 1) {
                    $platformSlug = DB::table('platforms')->where('id', $newPlatformId)->value('slug');
                    $gameSlug = $game->slug . '-' . $platformSlug;
                }

                $newGameId = DB::table('games')
                    ->insertGetId([
                        'name' => $game->name,
                        'slug' => $gameSlug,
                        'platform_id' => $newPlatformId,
                        'genre_id' => $newGenreId,
                        'created_at' => now(),
                        'updated_at' => now(),
                    ]);

                DB::table('migration_game_plan')->insert([
                    'wp_game_id' => $gameId,
                    'wp_platform_id' => $platformId,
                    'game_id' => $newGameId,
                    'wp_genre_id' => $topId === self::NO_GENRE_SENTINEL ? null : $topId,
                    'post_count' => $info['count'],
                    'genre_conflict' => $genreConflict,
                    'created_at' => now(),
                    'updated_at' => now(),
                ]);

                $created++;

            }
        }

        $this->newLine();
        $this->info("$created games created. $genreConflicts genre conflicts.");
    }
}
