<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;

class ImportLegacyFavourites extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'import:legacy-favourites
                            {--connection=legacy : Legacy DB connection name}
                            {--table=favourites : Legacy favourites table name}
                            {--id-column=id : ID column to use for chunking}
                            {--map-user=user_id : Column name for user id}
                            {--map-artwork=artwork_id : Column name for artwork id}
                            {--map-created=datum : Column name for created timestamp}
                            {--chunk=500 : Chunk size}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Copy legacy favourites (from another DB connection) into user_favorites';

    public function handle(): int
    {
        $connection = $this->option('connection');
        $table = $this->option('table');
        $idColumn = $this->option('id-column');
        $mapUser = $this->option('map-user');
        $mapArtwork = $this->option('map-artwork');
        $mapCreated = $this->option('map-created');
        $chunk = (int) $this->option('chunk');

        $this->info("Using connection='{$connection}', table='{$table}', idColumn='{$idColumn}'");

        try {
            $legacy = DB::connection($connection);
        } catch (\Throwable $e) {
            $this->error('Cannot connect to legacy connection: '.$e->getMessage());
            return 1;
        }

        try {
            $schema = $legacy->getSchemaBuilder();
        } catch (\Throwable $e) {
            $this->error('Failed to get schema builder for legacy connection: '.$e->getMessage());
            return 1;
        }

        if (! $schema->hasTable($table)) {
            $this->error("Table '{$table}' does not exist on connection '{$connection}'");
            return 1;
        }

        $this->info('Starting import...');

        $attempted = 0;
        $inserted = 0;

        // Try chunkById for efficient processing; fallback to cursor if id column missing
        try {
            $legacy->table($table)
                ->select([$idColumn, $mapUser, $mapArtwork, $mapCreated])
                ->orderBy($idColumn)
                ->chunkById($chunk, function ($rows) use (&$attempted, &$inserted, $mapUser, $mapArtwork, $mapCreated) {
                    $batch = [];
                    foreach ($rows as $r) {
                        $attempted++;
                        $batch[] = [
                            'user_id' => $r->{$mapUser},
                            'artwork_id' => $r->{$mapArtwork},
                            'created_at' => $r->{$mapCreated} ?? now(),
                        ];
                    }

                    if (count($batch) > 0) {
                        $res = DB::table('user_favorites')->insertOrIgnore($batch);
                        // insertOrIgnore may return number inserted on some drivers; approximate otherwise
                        if (is_int($res)) {
                            $inserted += $res;
                        } else {
                            $inserted += count($batch);
                        }
                    }

                    $this->info("Processed {$attempted} rows, approx inserted {$inserted}");
                });
        } catch (\Throwable $e) {
            $this->warn('chunkById failed, falling back to cursor: '.$e->getMessage());

            $cursor = $legacy->table($table)
                ->select([$mapUser, $mapArtwork, $mapCreated])
                ->orderBy($mapCreated)
                ->cursor();

            $batch = [];
            foreach ($cursor as $r) {
                $attempted++;
                $batch[] = [
                    'user_id' => $r->{$mapUser},
                    'artwork_id' => $r->{$mapArtwork},
                    'created_at' => $r->{$mapCreated} ?? now(),
                ];

                if (count($batch) >= $chunk) {
                    $res = DB::table('user_favorites')->insertOrIgnore($batch);
                    if (is_int($res)) {
                        $inserted += $res;
                    } else {
                        $inserted += count($batch);
                    }
                    $this->info("Processed {$attempted} rows, approx inserted {$inserted}");
                    $batch = [];
                }
            }

            if (count($batch) > 0) {
                $res = DB::table('user_favorites')->insertOrIgnore($batch);
                if (is_int($res)) {
                    $inserted += $res;
                } else {
                    $inserted += count($batch);
                }
            }
        }

        $this->info("Import complete. Attempted {$attempted}, approx inserted {$inserted}.");
        return 0;
    }
}
