<?php

namespace App\Console\Commands\Migrations;

use App\Models\WaterSource;
use Illuminate\Support\Facades\DB;

class WaterSourceMigration extends BaseMigration
{
    protected string $oldTableName = 'sek_water_sources';

    protected string $modelName = 'Water Sources';

    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 'Water Sources';
    }

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

    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} water sources to migrate");

        if ($totalCount === 0) {
            $this->warn('⚠️  No water sources 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) {
                    try {
                        $mappedData = $this->mapData($oldRecord);

                        if ($this->validateData($mappedData)) {
                            if (! $dryRun) {
                                $this->createModel($mappedData);
                                $this->stats['migrated']++;
                            } else {
                                $this->info("🔍 [DRY RUN] Would migrate water source ID {$oldRecord->id}: {$mappedData['name']}");
                            }
                        } else {
                            $this->stats['skipped']++;
                        }
                    } catch (\Exception $e) {
                        $this->stats['errors']++;
                        $this->error("❌ Error migrating water source ID {$oldRecord->id}: ".$e->getMessage());
                    }

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

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

    protected function mapData(object $oldRecord): array
    {
        // Handle null, empty, or 'nan' values
        $name = $oldRecord->water_source;
        if (empty($name) || $name === 'nan' || $name === 'null') {
            $name = 'Unknown Water Source';
        }

        return [
            'id' => (int) $oldRecord->id,
            'name' => $name,
            'lat' => $this->parseCoordinate($oldRecord->y_coordinate),
            'lng' => $this->parseCoordinate($oldRecord->x_coordinate),
            'created_at' => now(),
            'updated_at' => now(),
        ];
    }

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

            return false;
        }

        // Coordinates are optional, but if provided should be valid
        if (! empty($data['lat']) && ! $this->isValidLatitude($data['lat'])) {
            $this->warn("⚠️  Skipping water source ID {$data['id']}: invalid latitude {$data['lat']}");

            return false;
        }

        if (! empty($data['lng']) && ! $this->isValidLongitude($data['lng'])) {
            $this->warn("⚠️  Skipping water source ID {$data['id']}: invalid longitude {$data['lng']}");

            return false;
        }

        return true;
    }

    protected function createModel(array $data): void
    {
        // Create the water source with unguarded mass assignment to preserve IDs
        WaterSource::unguarded(function () use ($data) {
            $waterSource = WaterSource::create($data);
            $this->info("💧 Migrated water source ID {$waterSource->getKey()}: {$data['name']}");
        });
    }

    /**
     * Parse coordinate value and return as float or null
     */
    private function parseCoordinate($coordinate): ?float
    {
        if (empty($coordinate)) {
            return null;
        }

        $parsed = (float) $coordinate;

        return $parsed != 0 ? $parsed : null;
    }

    /**
     * Validate latitude is within valid range
     */
    private function isValidLatitude(?float $lat): bool
    {
        if ($lat === null) {
            return true; // null is valid (optional)
        }

        return $lat >= -90 && $lat <= 90;
    }

    /**
     * Validate longitude is within valid range
     */
    private function isValidLongitude(?float $lng): bool
    {
        if ($lng === null) {
            return true; // null is valid (optional)
        }

        return $lng >= -180 && $lng <= 180;
    }
}
