<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\SoftDeletes;

/**
 * @property int $id
 * @property int $provider_id
 * @property int|null $bank_id
 * @property string $bank_code
 * @property string|null $bank_name
 * @property string $holder_name
 * @property string $holder_document
 * @property string $holder_type
 * @property string $type
 * @property string $branch_number
 * @property string|null $branch_check_digit
 * @property string $account_number
 * @property string $account_check_digit
 * @property bool $is_primary
 * @property bool $is_active
 * @property \Illuminate\Support\Carbon|null $gateway_synced_at
 * @property string|null $gateway_sync_hash
 * @property array|null $gateway_payload
 * @property \Illuminate\Support\Carbon|null $created_at
 * @property \Illuminate\Support\Carbon|null $updated_at
 * @property \Illuminate\Support\Carbon|null $deleted_at
 * @property-read Bank|null $bank
 * @property-read Provider $provider
 * @method static \Illuminate\Database\Eloquent\Builder<static>|ProviderBankAccount newModelQuery()
 * @method static \Illuminate\Database\Eloquent\Builder<static>|ProviderBankAccount newQuery()
 * @method static \Illuminate\Database\Eloquent\Builder<static>|ProviderBankAccount onlyTrashed()
 * @method static \Illuminate\Database\Eloquent\Builder<static>|ProviderBankAccount query()
 * @method static \Illuminate\Database\Eloquent\Builder<static>|ProviderBankAccount active()
 * @method static \Illuminate\Database\Eloquent\Builder<static>|ProviderBankAccount primary()
 * @method static \Illuminate\Database\Eloquent\Builder<static>|ProviderBankAccount withTrashed(bool $withTrashed = true)
 * @method static \Illuminate\Database\Eloquent\Builder<static>|ProviderBankAccount withoutTrashed()
 * @mixin \Eloquent
 */
class ProviderBankAccount extends Model
{
    use HasFactory, SoftDeletes;

    protected $table = 'provider_bank_accounts';

    protected $fillable = [
        'provider_id',
        'bank_id',
        'bank_code',
        'bank_name',
        'holder_name',
        'holder_document',
        'holder_type',
        'type',
        'branch_number',
        'branch_check_digit',
        'account_number',
        'account_check_digit',
        'is_primary',
        'is_active',
        'gateway_synced_at',
        'gateway_sync_hash',
        'gateway_sync_count',
        'gateway_payload',
    ];

    protected function casts(): array
    {
        return [
            'is_primary'         => 'boolean',
            'is_active'          => 'boolean',
            'gateway_synced_at'  => 'datetime',
            'gateway_sync_count' => 'integer',
            'gateway_payload'    => 'array',
        ];
    }

    public function provider(): BelongsTo
    {
        return $this->belongsTo(Provider::class);
    }

    public function bank(): BelongsTo
    {
        return $this->belongsTo(Bank::class);
    }

    //

    public function scopePrimary(Builder $query): Builder
    {
        return $query->where('is_primary', true);
    }

    public function scopeActive(Builder $query): Builder
    {
        return $query->where('is_active', true);
    }

    //

    /**
     * Formato esperado pelo Pagar.me em default_bank_account / bank_account.
     * E tambem o formato espelhado em providers.recipient_default_bank_account.
     */
    public function toGatewayBankAccount(): array
    {
        return [
            'holder_name'         => $this->holder_name,
            'holder_type'         => $this->holder_type,
            'holder_document'     => $this->holder_document,
            'bank'                => $this->bank_code,
            'branch_number'       => $this->branch_number,
            'branch_check_digit'  => $this->branch_check_digit,
            'account_number'      => $this->account_number,
            'account_check_digit' => $this->account_check_digit,
            'type'                => $this->type,
        ];
    }

    /**
     * Identifica o conteudo da conta enviado ao gateway, para detectar divergencia
     * entre o que esta salvo aqui e o que o Pagar.me tem como conta padrao.
     */
    public function gatewayHash(): string
    {
        return sha1(json_encode($this->toGatewayBankAccount()));
    }

    /**
     * Avanca o contador usado na chave de idempotencia, para que cada envio ao Pagar.me
     * seja uma operacao nova - inclusive ao voltar para uma conta ja usada antes.
     */
    public function markGatewaySyncAttempt(): int
    {
        $this->forceFill(['gateway_sync_count' => $this->gateway_sync_count + 1])->save();

        return $this->gateway_sync_count;
    }

    public function isSyncedWithGateway(): bool
    {
        return $this->gateway_synced_at !== null
            && $this->gateway_sync_hash === $this->gatewayHash();
    }
}
