<?php

namespace App\Console\Commands\Migrations;

use Carbon\Carbon;
use Illuminate\Support\Facades\DB;

class SekayaValueMigration extends BaseMigration
{
    protected string $oldTableName = 'sek_values';

    protected string $modelName = 'Sekaya Values';

    public function migrate(bool $dryRun = false, int $batchSize = 1000, int $startFrom = 0): void
    {
        $oldDb = DB::connection($this->connection);
        $this->processData($oldDb, $dryRun, $startFrom, $batchSize);
    }

    protected function getModelName(): string
    {
        return 'Sekaya Value';
    }

    protected function getModelClass(): string
    {
        return 'App\\Models\\SekayaValue';
    }

    protected function processData($oldDb, bool $dryRun = false, int $startFrom = 0, int $batchSize = 1000): void
    {
        $query = $oldDb->table($this->oldTableName)
            ->whereNotNull('id')
            ->orderBy('id');

        $totalCount = $query->count();
        $this->stats['total'] = $totalCount;

        $this->info("📊 Found {$totalCount} sekaya values to migrate");

        if ($totalCount === 0) {
            $this->warn('⚠️  No sekaya values found to migrate');

            return;
        }

        $processed = 0;
        $bar = $this->command->getOutput()->createProgressBar($totalCount);

        $query->skip($startFrom)
            ->chunk($batchSize, function ($oldRecords) use ($dryRun, &$processed, $bar) {
                foreach ($oldRecords as $oldRecord) {
                    // Use a transaction for each record to prevent transaction aborted errors
                    DB::beginTransaction();
                    try {
                        $data = $this->mapData($oldRecord);

                        if ($this->validateData($data)) {
                            if (! $dryRun) {
                                $this->createModel($data);
                            }
                            $this->stats['migrated']++;
                        } else {
                            $this->stats['skipped']++;
                        }

                        DB::commit();
                    } catch (\Exception $e) {
                        DB::rollback();
                        $this->stats['errors']++;
                        $this->error("❌ Error processing sekaya value ID {$oldRecord->id}: ".$e->getMessage());
                    }

                    $processed++;
                    $bar->advance();
                }
            });

        $bar->finish();
        $this->command->info('');
    }

    protected function mapData(object $oldRecord): array
    {
        return [
            'id' => $oldRecord->id, // Preserve original ID
            'name' => $oldRecord->name ?? 'Unnamed Value',
            'type' => $oldRecord->type ?? 'UNKNOWN',
            'created_at' => $this->parseDateTime($oldRecord->created_at ?? null),
            'updated_at' => $this->parseDateTime($oldRecord->modified_at ?? $oldRecord->updated_at ?? null),
            'old_record' => $oldRecord, // Keep for reference
        ];
    }

    protected function validateData(array $data): bool
    {
        // Must have a name
        if (empty($data['name']) || trim($data['name']) === '') {
            $this->warn("⚠️  Skipping sekaya value {$data['id']}: Missing name");

            return false;
        }

        // Must have a type
        if (empty($data['type']) || trim($data['type']) === '') {
            $this->warn("⚠️  Skipping sekaya value {$data['id']}: Missing type");

            return false;
        }

        // Check if sekaya value already exists
        $existingSekayaValue = DB::table('sekaya_values')->where('id', $data['id'])->exists();
        if ($existingSekayaValue) {
            $this->warn("⚠️  Skipping sekaya value {$data['id']}: Already exists");

            return false;
        }

        return true;
    }

    protected function createModel(array $data): void
    {
        $oldRecord = $data['old_record'];
        unset($data['old_record']);

        // Use raw DB insertion to preserve the original ID
        DB::table('sekaya_values')->insert($data);

        $sekayaValueId = $data['id'];
        $sekayaValueName = $data['name'];
        $sekayaValueType = $data['type'];

        $this->info("✅ Created sekaya value: {$sekayaValueName} (ID: {$sekayaValueId}, Type: {$sekayaValueType})");
    }

    /**
     * Parse datetime string to Carbon instance
     */
    protected function parseDateTime($dateTime): ?Carbon
    {
        if (empty($dateTime) || $dateTime === '0000-00-00 00:00:00') {
            return null;
        }

        try {
            return Carbon::parse($dateTime);
        } catch (\Exception $e) {
            return null;
        }
    }
}
