<?php

namespace App\Models;

use App\Models\Scopes\CompanyScope;
use Illuminate\Database\Eloquent\Attributes\ScopedBy;
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\Relations\HasMany;
use Illuminate\Support\Facades\Storage;

#[ScopedBy([CompanyScope::class])]
class NotaFiscal extends Model
{
    use HasFactory;

    protected $table = 'notas_fiscais';

    protected $guarded = ['id'];

    protected function casts(): array
    {
        return [
            'data_emissao' => 'datetime',
            'data_autorizacao' => 'datetime',
            'manifestacao_at' => 'datetime',
            'valor_total' => 'decimal:2',
            'tem_xml_completo' => 'boolean',
            'nsu' => 'integer',
        ];
    }

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

    public function eventos(): HasMany
    {
        return $this->hasMany(NotaEvento::class);
    }

    /* ---------------------------------------------------------- Attributes */

    public function getEmitCnpjFormatadoAttribute(): string
    {
        return Company::formatCnpj($this->emit_cnpj);
    }

    public function getChaveFormatadaAttribute(): string
    {
        return trim(chunk_split((string) $this->chave, 4, ' '));
    }

    public function situacaoLabel(): string
    {
        return match ($this->situacao) {
            'cancelada' => 'Cancelada',
            'denegada' => 'Denegada',
            default => 'Autorizada',
        };
    }

    public function manifestacaoLabel(): string
    {
        return match ($this->manifestacao) {
            'ciencia' => 'Ciência da operação',
            'confirmada' => 'Operação confirmada',
            'desconhecida' => 'Desconhecimento',
            'nao_realizada' => 'Operação não realizada',
            default => 'Sem manifestação',
        };
    }

    public function xmlContent(): ?string
    {
        if (! $this->xml_path || ! Storage::disk('xmls')->exists($this->xml_path)) {
            return null;
        }

        return Storage::disk('xmls')->get($this->xml_path);
    }

    public function downloadFilename(): string
    {
        return $this->chave.'.xml';
    }

    /* ------------------------------------------------------------- Scopes */

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

    public function scopePendentesManifestacao(Builder $query): Builder
    {
        return $query->where('tem_xml_completo', false)
            ->whereNull('manifestacao')
            ->where('situacao', 'autorizada');
    }

    public function scopePeriodo(Builder $query, ?string $de, ?string $ate): Builder
    {
        return $query
            ->when($de, fn ($q) => $q->whereDate('data_emissao', '>=', $de))
            ->when($ate, fn ($q) => $q->whereDate('data_emissao', '<=', $ate));
    }

    public function scopeBusca(Builder $query, ?string $termo): Builder
    {
        if (blank($termo)) {
            return $query;
        }

        $termo = trim($termo);
        $digits = preg_replace('/\D/', '', $termo);

        return $query->where(function (Builder $q) use ($termo, $digits) {
            $q->where('emit_nome', 'like', "%{$termo}%");

            if ($digits !== '') {
                $q->orWhere('chave', 'like', "%{$digits}%")
                    ->orWhere('emit_cnpj', 'like', "%{$digits}%")
                    ->orWhere('numero', $digits);
            }
        });
    }
}
