<?php

namespace App\Console\Commands;

use App\Models\Client;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;

class UpdateCustomerUseridByPopCommand extends Command
{
    /**
     * The name and signature of the console command.
     *
     * Examples:
     *  php artisan update:customer-userid-by-pop 5
     *  php artisan update:customer-userid-by-pop 5 --with-trashed
     */
    protected $signature = 'update:customer-userid-by-pop
                            {pop_id : The pop_id to process}
                            {--with-trashed : Include soft-deleted customers}';

    protected $description = 'Append client ID to userid for a specific pop_id and sync Radius usernames';

    public function handle(): int
    {
        $popId = (int) $this->argument('pop_id');
        $withTrashed = (bool) $this->option('with-trashed');

        $this->info("Starting userid update for pop_id={$popId}" . ($withTrashed ? ' (including trashed)' : '') . '...');

        $query = $withTrashed ? Client::withTrashed() : Client::query();
        $query->where('pop_id', $popId)->orderBy('id');

        $total = (clone $query)->count();
        $this->info("Found {$total} clients in this POP.");

        $updated = 0;
        $skipped = 0;
        $errors = 0;

        $query->chunkById(500, function ($clients) use (&$updated, &$skipped, &$errors) {
            foreach ($clients as $client) {
                $oldUserid = (string) $client->userid;
                $suffix = '_' . $client->id;

                // Already updated
                if (substr($oldUserid, -strlen($suffix)) === $suffix) {
                    $skipped++;
                    continue;
                }

                $newUserid = $oldUserid . $suffix;

                try {
                    DB::transaction(function () use ($client, $oldUserid, $newUserid) {
                        // Avoid unique collisions on clients.userid
                        $exists = Client::withTrashed()
                            ->where('userid', $newUserid)
                            ->where('id', '!=', $client->id)
                            ->exists();

                        if ($exists) {
                            throw new \RuntimeException("userid '{$newUserid}' already exists");
                        }

                        // Update clients table
                        DB::table('clients')->where('id', $client->id)->update(['userid' => $newUserid]);

                        // Keep Radius tables consistent (rename username)
                        DB::table('radcheck')->where('username', $oldUserid)->update(['username' => $newUserid]);
                        DB::table('radreply')->where('username', $oldUserid)->update(['username' => $newUserid]);
                        DB::table('radusergroup')->where('username', $oldUserid)->update(['username' => $newUserid]);
                    });

                    $updated++;
                    $this->line("Updated client_id={$client->id}: {$oldUserid} -> {$newUserid}");
                } catch (\Throwable $e) {
                    $errors++;
                    $this->error("Error client_id={$client->id} ({$oldUserid}): {$e->getMessage()}");
                }
            }
        });

        $this->info("\n=== Summary ===");
        $this->info("Total matched: {$total}");
        $this->info("Updated: {$updated}");
        $this->info("Skipped (already had _id): {$skipped}");
        $this->info("Errors: {$errors}");

        return Command::SUCCESS;
    }
}

