<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;

/**
 * Punto de emisión del SRI.
 *
 * Combina el código de establecimiento y el punto de emisión y mantiene
 * los secuenciales de cada tipo de comprobante (factura, nota de crédito,
 * nota de débito y comprobante de retención).
 */
class PuntoEmision extends Model
{
    use HasFactory;

    protected $table = 'puntos_emision';

    protected $fillable = [
        'estab', 'pto_emi', 'descripcion', 'direccion',
        'sec_factura', 'sec_nota_credito', 'sec_nota_debito', 'sec_retencion',
        'activo',
    ];

    protected $casts = [
        'sec_factura' => 'integer',
        'sec_nota_credito' => 'integer',
        'sec_nota_debito' => 'integer',
        'sec_retencion' => 'integer',
        'activo' => 'boolean',
    ];

    /** Columna de secuencial según el tipo de comprobante */
    public const COLUMNA_SECUENCIAL = [
        '01' => 'sec_factura',
        '04' => 'sec_nota_credito',
        '05' => 'sec_nota_debito',
        '07' => 'sec_retencion',
    ];

    /**
     * Obtiene el siguiente secuencial (9 dígitos) para un tipo de comprobante
     * y lo incrementa de forma atómica.
     */
    public static function siguienteSecuencial(string $tipoDocumento, ?int $puntoEmisionId = null): array
    {
        $columna = self::COLUMNA_SECUENCIAL[$tipoDocumento]
            ?? throw new \InvalidArgumentException("Tipo de comprobante no soportado: {$tipoDocumento}");

        return DB::transaction(function () use ($columna, $puntoEmisionId) {
            $punto = $puntoEmisionId
                ? self::lockForUpdate()->findOrFail($puntoEmisionId)
                : self::where('activo', true)->lockForUpdate()->orderBy('id')->first();

            if (!$punto) {
                $punto = self::create([
                    'estab' => '001',
                    'pto_emi' => '001',
                    'descripcion' => 'Punto de emisión principal',
                    'activo' => true,
                ]);
            }

            $punto->increment($columna);
            $secuencial = str_pad((string) $punto->{$columna}, 9, '0', STR_PAD_LEFT);

            return [
                'punto' => $punto,
                'estab' => $punto->estab,
                'pto_emi' => $punto->pto_emi,
                'secuencial' => $secuencial,
                'numero_completo' => "{$punto->estab}-{$punto->pto_emi}-{$secuencial}",
            ];
        });
    }

    public function getEtiquetaAttribute(): string
    {
        return "{$this->estab}-{$this->pto_emi}";
    }
}
