<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Facades\Storage;

class Company extends Model
{
    use HasFactory, SoftDeletes;

    protected $guarded = ['id'];

    /**
     * Espelha os defaults do banco, para que uma empresa recém-criada já
     * responda corretamente às checagens de assinatura e de monitor.
     *
     * @var array<string, mixed>
     */
    protected $attributes = [
        'plano' => 'trial',
        'is_active' => true,
        'limite_notas_mes' => 1000,
        'monitor_enabled' => true,
        'monitor_intervalo_min' => 60,
        'ult_nsu' => 0,
        'max_nsu' => 0,
        'manifestacao_automatica' => false,
        'ambiente' => 1,
    ];

    protected function casts(): array
    {
        return [
            'cert_password' => 'encrypted',
            'cert_valid_from' => 'datetime',
            'cert_valid_to' => 'datetime',
            'last_sync_at' => 'datetime',
            'assinatura_expira_em' => 'date',
            'is_active' => 'boolean',
            'monitor_enabled' => 'boolean',
            'manifestacao_automatica' => 'boolean',
            'ult_nsu' => 'integer',
            'max_nsu' => 'integer',
        ];
    }

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

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

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

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

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

    public function getCnpjFormatadoAttribute(): string
    {
        return self::formatCnpj($this->cnpj);
    }

    public static function formatCnpj(?string $cnpj): string
    {
        $cnpj = preg_replace('/\D/', '', (string) $cnpj);

        if (strlen($cnpj) !== 14) {
            return (string) $cnpj;
        }

        return vsprintf('%s%s.%s%s%s.%s%s%s/%s%s%s%s-%s%s', str_split($cnpj));
    }

    public function hasCertificate(): bool
    {
        return $this->cert_path && Storage::disk('certificados')->exists($this->cert_path);
    }

    public function certificateExpired(): bool
    {
        return $this->cert_valid_to !== null && $this->cert_valid_to->isPast();
    }

    /**
     * Dias restantes de validade. Positivo no futuro, negativo se já venceu.
     *
     * O sinal importa: `$data->diffInDays(now())` devolve valor negativo para
     * datas futuras, o que fazia todo certificado válido cair na faixa de
     * "vence em breve".
     */
    public function certificateDaysLeft(): ?int
    {
        return $this->cert_valid_to === null
            ? null
            : (int) now()->diffInDays($this->cert_valid_to, false);
    }

    public function certificateExpiringSoon(int $days = 30): bool
    {
        $restantes = $this->certificateDaysLeft();

        return $restantes !== null && $restantes >= 0 && $restantes <= $days;
    }

    public function assinaturaAtiva(): bool
    {
        return $this->is_active
            && ($this->assinatura_expira_em === null || $this->assinatura_expira_em->isFuture());
    }

    /**
     * Monitor pode rodar agora? Respeita o intervalo mínimo entre consultas,
     * exigido pela SEFAZ para o serviço NFeDistribuicaoDFe.
     */
    public function podeSincronizar(): bool
    {
        if (! $this->monitor_enabled || ! $this->assinaturaAtiva() || ! $this->hasCertificate()) {
            return false;
        }

        if ($this->certificateExpired()) {
            return false;
        }

        if ($this->last_sync_at === null) {
            return true;
        }

        return $this->last_sync_at->addMinutes($this->monitor_intervalo_min)->isPast();
    }

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

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

    public function scopeComMonitor($query)
    {
        return $query->where('is_active', true)->where('monitor_enabled', true);
    }
}
