<?php

use App\Domain\Shared\Helpers\CredentialNormalizer;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

/**
 * Bring existing user credentials into the canonical shape that login now
 * matches on: lowercase emails, digits-only local phone numbers.
 *
 * Runs against every client database on deploy, so it is deliberately
 * non-destructive. A row that cannot be normalised without colliding with
 * another account is left exactly as it is and logged — those pairs are
 * duplicate registrations that need a human merge decision, and guessing
 * which one to keep would be worse than leaving both.
 *
 * Uses the query builder rather than the User model on purpose: the
 * BelongsToAcademy global scope resolves 'current_academy', which is not
 * bound during migrations.
 */
return new class extends Migration
{
    public function up(): void
    {
        $this->normalizeColumn('email', fn ($v) => CredentialNormalizer::email($v));
        $this->normalizeColumn('phone', fn ($v) => CredentialNormalizer::phone($v));
    }

    public function down(): void
    {
        // Irreversible by design: the original casing and formatting are not
        // recorded anywhere, and restoring them would re-break login.
    }

    private function normalizeColumn(string $column, callable $normalize): void
    {
        $skipped = [];

        DB::table('users')
            ->select('id', $column)
            ->whereNotNull($column)
            ->orderBy('id')
            ->chunk(200, function ($rows) use ($column, $normalize, &$skipped) {
                foreach ($rows as $row) {
                    $current = $row->{$column};
                    $normalized = $normalize($current);

                    if ($normalized === null || $normalized === $current) {
                        continue;
                    }

                    $taken = DB::table('users')
                        ->where($column, $normalized)
                        ->where('id', '!=', $row->id)
                        ->exists();

                    if ($taken) {
                        $skipped[] = $row->id;

                        continue;
                    }

                    DB::table('users')
                        ->where('id', $row->id)
                        ->update([$column => $normalized]);
                }
            });

        if ($skipped !== []) {
            Log::warning('normalize_user_credentials: left {column} untouched on user ids {ids} — another account already holds the normalised value. These are duplicate registrations and need a manual merge.', [
                'column' => $column,
                'ids' => implode(', ', $skipped),
            ]);
        }
    }
};
