<?php

namespace App\Console\Commands;

use App\Models\BankInfo;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Str;

class SyncBankCodes extends Command
{
    protected $signature = 'bank:sync-codes';
    protected $description = 'Fix bank codes using Remita (prioritize Nigeria matches with hardcoded aliases)';

    /**
     * Blocked countries
     */
    protected array $blockedCountries = [
        'ghana',
        'gambia',
        'kenya',
        'uganda',
        'liberia',
        'tanzania',
        'south africa',
        'zambia',
        'uk',
        'united kingdom',
        'usa',
        'united states',
        'canada'
    ];

    /**
     * Hardcoded aliases (force specific name + code)
     */
    protected array $aliasBanks = [
        'gtb' => ['name' => 'Guaranty Trust Bank Plc', 'code' => '058'],
        'guarantee trust bank' => ['name' => 'Guaranty Trust Bank Plc', 'code' => '058'],
        // Add more aliases here if needed
    ];

    public function handle()
    {
        $this->info('Logging into Remita...');

        try {
            $loginRemita = app()->call(
                [app(\App\Http\Controllers\MiscController::class), 'remitaLogin']
            );

            if (!isset($loginRemita['accessToken'])) {
                $this->error('Remita authentication failed');
                return Command::FAILURE;
            }

            $this->info('Fetching banks from Remita...');

            $response = Http::withHeaders([
                'Authorization' => "Bearer {$loginRemita['accessToken']}",
                'Content-Type' => 'application/json',
            ])->get('https://api-gateway.remita.net/api/v1/integration/banks');

            $remitaBanks = collect($response->json('data.banks', []))
                ->map(fn($bank) => [
                    'name' => Str::lower(trim($bank['bankName'])),
                    'code' => trim($bank['bankCode']),
                ])
                ->filter(function ($bank) {
                    foreach ($this->blockedCountries as $country) {
                        if (str_contains($bank['name'], $country))
                            return false;
                    }
                    return true;
                })
                ->values();

            if ($remitaBanks->isEmpty()) {
                $this->error('No valid Remita banks found');
                return Command::FAILURE;
            }

            $accounts = BankInfo::whereNotNull('bank_name')->get();

            $this->info("Processing {$accounts->count()} bank records...");
            $updated = 0;

            foreach ($accounts as $account) {
                $originalName = Str::lower(trim($account->bank_name));
                if (!$originalName)
                    continue;

                // STEP 0: Check hardcoded aliases first
                $aliasMatched = null;
                foreach ($this->aliasBanks as $key => $alias) {
                    if (str_contains($originalName, $key)) {
                        $aliasMatched = $alias;
                        break;
                    }
                }

                if ($aliasMatched) {
                    BankInfo::where('id', $account->id)->update([
                        'bank_code' => $aliasMatched['code'],
                        'bank_name' => $aliasMatched['name'],
                        'updated_at' => now(),
                    ]);
                    $updated++;
                    $this->line("✔ {$account->bank_name} → {$aliasMatched['name']} ({$aliasMatched['code']}) [ALIAS]");
                    continue;
                }

                // STEP 1: Remove blocked countries
                $cleanName = $originalName;
                foreach ($this->blockedCountries as $country) {
                    $cleanName = str_replace($country, '', $cleanName);
                }
                $cleanName = trim(preg_replace('/\s+/', ' ', $cleanName));

                // STEP 2: Use first or first+second word
                $words = explode(' ', $cleanName);
                $searchNames = [];
                if (count($words) >= 2) {
                    $searchNames[] = $words[0] . ' ' . $words[1];
                }
                if (count($words) >= 1) {
                    $searchNames[] = $words[0];
                }

                $matchedBank = null;

                // STEP 3: Prioritize Nigerian banks
                foreach ($searchNames as $namePart) {
                    $matchedBank = $remitaBanks->first(function ($bank) use ($namePart) {
                        $namePart = Str::lower($namePart);
                        return (str_contains($bank['name'], $namePart) && str_contains($bank['name'], 'nigeria'));
                    });
                    if ($matchedBank)
                        break;
                }

                // STEP 4: If no Nigerian match, match without country
                if (!$matchedBank) {
                    foreach ($searchNames as $namePart) {
                        $matchedBank = $remitaBanks->first(function ($bank) use ($namePart) {
                            $namePart = Str::lower($namePart);
                            return str_contains($bank['name'], $namePart) && !str_contains($bank['name'], 'nigeria');
                        });
                        if ($matchedBank)
                            break;
                    }
                }

                if (!$matchedBank) {
                    $this->warn("No valid Remita match for: {$account->bank_name}");
                    continue;
                }

                // STEP 5: Update bank_name and bank_code
                BankInfo::where('id', $account->id)->update([
                    'bank_code' => $matchedBank['code'],
                    'bank_name' => ucwords($matchedBank['name']),
                    'updated_at' => now(),
                ]);

                $updated++;
                $this->line("✔ {$account->bank_name} → {$matchedBank['name']} ({$matchedBank['code']})");
            }

            $this->info("Done. Updated {$updated} records.");
            return Command::SUCCESS;

        } catch (\Throwable $e) {
            $this->error('Error: ' . $e->getMessage());
            return Command::FAILURE;
        }
    }
}
