<?php

namespace App\Commands;

use App\Models\Address;
use App\Models\Client;
use App\Models\Provider;
use App\Services\Pagarme\PagarmeCustomerService;
use App\Services\Pagarme\PagarmeRecipientService;
use Illuminate\Console\Command;

class RefreshPagarmeEntities extends Command
{
    protected $signature = 'pagarme:refresh-entities';

    protected $description = 'Limpa os recipients e clients locais e os recria no Pagar.me com os dados do banco local';

    public function __construct(
        protected PagarmeRecipientService $recipientService,
        protected PagarmeCustomerService $customerService,
    ) {
        parent::__construct();
    }

    public function handle(): int
    {
        $this->warn('ATENCAO: Este comando vai limpar os IDs de gateway dos recipients (providers) e customers (clients)');
        $this->warn('e recria-los no Pagar.me com os dados do banco local. Os registros antigos no Pagar.me');
        $this->warn('ficarao orfaos (nao serao deletados).');
        $this->newLine();

        $providers = Provider::query()
            ->whereNotNull('recipient_id')
            ->count();

        $clients = Client::query()
            ->whereNotNull('gateway_customer_id')
            ->count();

        $this->info("Providers com recipient_id: {$providers}");
        $this->info("Clients com gateway_customer_id: {$clients}");
        $this->newLine();

        if ($providers + $clients === 0) {
            $this->info('Nenhum registro para processar.');

            return Command::SUCCESS;
        }

        if (! $this->confirm('Deseja continuar com a limpeza e recriacao?')) {
            $this->info('Operacao cancelada.');

            return Command::SUCCESS;
        }

        $this->newLine();

        if ($providers > 0) {
            $this->processProviders();
        }

        if ($clients > 0) {
            $this->processClients();
        }

        $this->newLine();
        $this->info('Operacao concluida.');

        return Command::SUCCESS;
    }

    private function processProviders(): void
    {
        $this->info('--- Processando providers ---');
        $this->newLine();

        $providers = Provider::query()
            ->whereNotNull('recipient_id')
            ->with(['user', 'addresses.city.state', 'addresses.state', 'primaryBankAccount'])
            ->get();

        $bar = $this->output->createProgressBar($providers->count());
        $bar->start();

        foreach ($providers as $provider) {
            $address = $provider->addresses->where('is_primary', true)->first()
                ?? $provider->addresses->first();

            $data = [
                'recipient_name'                 => $provider->recipient_name,
                'recipient_email'                => $provider->recipient_email,
                'recipient_document'             => $provider->recipient_document,
                'recipient_type'                 => $provider->recipient_type,
                'recipient_payment_mode'         => $provider->recipient_payment_mode,
                'recipient_description'          => $provider->recipient_description,
                'recipient_metadata'             => $provider->recipient_metadata ?? [],
                'recipient_default_bank_account' => $provider->primaryBankAccount?->toGatewayBankAccount()
                    ?? $provider->recipient_default_bank_account
                    ?? [],
                'birth_date'                     => $provider->birth_date?->format('Y-m-d'),
                'professional_occupation'        => 'autonomo',
                'phone'                          => $provider->user?->phone,
                'address'                        => $address?->address ?? '',
                'number'                         => $address?->number ?? '',
                'district'                       => $address?->district ?? '',
                'city'                           => $address?->city?->name ?? '',
                'state'                          => $address?->state?->code ?? '',
                'zip_code'                       => $address?->zip_code ?? '',
                'complement'                     => $address?->complement ?? '',
            ];

            $provider->forceFill([
                'recipient_id'    => null,
                'idempotency_key' => null,
                'recipient_code'  => null,
            ])->save();

            try {
                $this->recipientService->createRecipientForProvider($provider, $data);
            } catch (\Throwable $e) {
                $this->newLine();
                $this->error("Erro ao recriar recipient do provider {$provider->id}: {$e->getMessage()}");

                $provider->forceFill([
                    'recipient_id'    => null,
                    'idempotency_key' => null,
                    'recipient_code'  => null,
                ])->save();
            }

            $bar->advance();
        }

        $bar->finish();
        $this->newLine();
        $this->newLine();
    }

    private function processClients(): void
    {
        $this->info('--- Processando clients ---');
        $this->newLine();

        $clients = Client::query()
            ->whereNotNull('gateway_customer_id')
            ->with('user')
            ->get();

        $bar = $this->output->createProgressBar($clients->count());
        $bar->start();

        foreach ($clients as $client) {
            $address = Address::query()
                ->with(['city', 'state'])
                ->where('source', 'client')
                ->where('source_id', $client->id)
                ->where('is_primary', true)
                ->first()
                ?? Address::query()
                    ->with(['city', 'state'])
                    ->where('source', 'client')
                    ->where('source_id', $client->id)
                    ->first();

            $data = [
                'name'       => $client->user?->name,
                'email'      => $client->user?->email,
                'phone'      => $client->user?->phone,
                'document'   => $client->document,
                'address'    => $address?->address ?? '',
                'number'     => $address?->number ?? '',
                'district'   => $address?->district ?? '',
                'city'       => $address?->city?->name ?? '',
                'state'      => $address?->state?->code ?? '',
                'zip_code'   => $address?->zip_code ?? '',
                'complement' => $address?->complement ?? '',
            ];

            $client->forceFill([
                'gateway_customer_id'   => null,
                'gateway_customer_code' => null,
                'idempotency_key'       => null,
            ])->save();

            try {
                $this->customerService->createCustomerForClient($client, $data);
            } catch (\Throwable $e) {
                $this->newLine();
                $this->error("Erro ao recriar customer do client {$client->id}: {$e->getMessage()}");

                $client->forceFill([
                    'gateway_customer_id'   => null,
                    'gateway_customer_code' => null,
                    'idempotency_key'       => null,
                ])->save();
            }

            $bar->advance();
        }

        $bar->finish();

        $this->newLine();
        $this->newLine();
    }
}
