<?php

namespace App\Models\Tenants;

use App\Traits\Auditable;
use App\Traits\BelongsToTenant;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\MorphTo;
use Illuminate\Database\Eloquent\SoftDeletes;

class TaxInvoice extends Model
{
    use Auditable, BelongsToTenant, SoftDeletes;

    // =========================================================================
    // 상수 정의
    // =========================================================================

    /**
     * 세금계산서 유형
     */
    public const TYPE_TAX_INVOICE = 'tax_invoice';           // 세금계산서

    public const TYPE_INVOICE = 'invoice';                   // 계산서 (면세)

    public const TYPE_MODIFIED_TAX_INVOICE = 'modified';     // 수정세금계산서

    public const INVOICE_TYPES = [
        self::TYPE_TAX_INVOICE,
        self::TYPE_INVOICE,
        self::TYPE_MODIFIED_TAX_INVOICE,
    ];

    /**
     * 발행 유형
     */
    public const ISSUE_TYPE_NORMAL = 'normal';        // 정발행

    public const ISSUE_TYPE_REVERSE = 'reverse';      // 역발행

    public const ISSUE_TYPE_TRUSTEE = 'trustee';      // 위수탁

    public const ISSUE_TYPES = [
        self::ISSUE_TYPE_NORMAL,
        self::ISSUE_TYPE_REVERSE,
        self::ISSUE_TYPE_TRUSTEE,
    ];

    /**
     * 방향
     */
    public const DIRECTION_SALES = 'sales';           // 매출

    public const DIRECTION_PURCHASES = 'purchases';   // 매입

    public const DIRECTIONS = [
        self::DIRECTION_SALES,
        self::DIRECTION_PURCHASES,
    ];

    /**
     * 상태
     */
    public const STATUS_DRAFT = 'draft';              // 임시저장

    public const STATUS_ISSUED = 'issued';            // 발행완료

    public const STATUS_SENT = 'sent';                // 국세청 전송완료

    public const STATUS_CANCELLED = 'cancelled';      // 취소

    public const STATUS_FAILED = 'failed';            // 발행실패

    public const STATUSES = [
        self::STATUS_DRAFT,
        self::STATUS_ISSUED,
        self::STATUS_SENT,
        self::STATUS_CANCELLED,
        self::STATUS_FAILED,
    ];

    /**
     * 상태 라벨
     */
    public const STATUS_LABELS = [
        self::STATUS_DRAFT => '임시저장',
        self::STATUS_ISSUED => '발행완료',
        self::STATUS_SENT => '국세청 전송',
        self::STATUS_CANCELLED => '취소',
        self::STATUS_FAILED => '발행실패',
    ];

    // =========================================================================
    // 모델 설정
    // =========================================================================

    protected $fillable = [
        'tenant_id',
        'nts_confirm_num',
        'invoice_type',
        'issue_type',
        'direction',
        'supplier_corp_num',
        'supplier_corp_name',
        'supplier_ceo_name',
        'supplier_addr',
        'supplier_biz_type',
        'supplier_biz_class',
        'supplier_contact_id',
        'buyer_corp_num',
        'buyer_corp_name',
        'buyer_ceo_name',
        'buyer_addr',
        'buyer_biz_type',
        'buyer_biz_class',
        'buyer_contact_id',
        'issue_date',
        'supply_amount',
        'tax_amount',
        'total_amount',
        'items',
        'status',
        'nts_send_status',
        'issued_at',
        'sent_at',
        'cancelled_at',
        'barobill_invoice_id',
        'description',
        'error_message',
        'reference_type',
        'reference_id',
        'created_by',
        'updated_by',
        'deleted_by',
    ];

    protected $casts = [
        'issue_date' => 'date',
        'supply_amount' => 'decimal:2',
        'tax_amount' => 'decimal:2',
        'total_amount' => 'decimal:2',
        'items' => 'array',
        'issued_at' => 'datetime',
        'sent_at' => 'datetime',
        'cancelled_at' => 'datetime',
    ];

    // =========================================================================
    // 관계 정의
    // =========================================================================

    /**
     * 참조 관계 (Sale 또는 Purchase)
     */
    public function reference(): MorphTo
    {
        return $this->morphTo(__FUNCTION__, 'reference_type', 'reference_id');
    }

    /**
     * 생성자 관계
     */
    public function creator(): BelongsTo
    {
        return $this->belongsTo(\App\Models\Members\User::class, 'created_by');
    }

    /**
     * 수정자 관계
     */
    public function updater(): BelongsTo
    {
        return $this->belongsTo(\App\Models\Members\User::class, 'updated_by');
    }

    // =========================================================================
    // 접근자 (Accessors)
    // =========================================================================

    /**
     * 상태 라벨
     */
    public function getStatusLabelAttribute(): string
    {
        return self::STATUS_LABELS[$this->status] ?? $this->status;
    }

    /**
     * 세금계산서 유형 라벨
     */
    public function getInvoiceTypeLabelAttribute(): string
    {
        return match ($this->invoice_type) {
            self::TYPE_TAX_INVOICE => '세금계산서',
            self::TYPE_INVOICE => '계산서',
            self::TYPE_MODIFIED_TAX_INVOICE => '수정세금계산서',
            default => $this->invoice_type,
        };
    }

    /**
     * 발행 유형 라벨
     */
    public function getIssueTypeLabelAttribute(): string
    {
        return match ($this->issue_type) {
            self::ISSUE_TYPE_NORMAL => '정발행',
            self::ISSUE_TYPE_REVERSE => '역발행',
            self::ISSUE_TYPE_TRUSTEE => '위수탁',
            default => $this->issue_type,
        };
    }

    /**
     * 방향 라벨
     */
    public function getDirectionLabelAttribute(): string
    {
        return $this->direction === self::DIRECTION_SALES ? '매출' : '매입';
    }

    /**
     * 공급자 사업자번호 포맷
     */
    public function getFormattedSupplierCorpNumAttribute(): string
    {
        return $this->formatCorpNum($this->supplier_corp_num);
    }

    /**
     * 공급받는자 사업자번호 포맷
     */
    public function getFormattedBuyerCorpNumAttribute(): string
    {
        return $this->formatCorpNum($this->buyer_corp_num);
    }

    // =========================================================================
    // 상태 체크 메서드
    // =========================================================================

    /**
     * 취소 가능 여부
     */
    public function canCancel(): bool
    {
        return in_array($this->status, [self::STATUS_ISSUED, self::STATUS_SENT]);
    }

    /**
     * 수정 가능 여부
     */
    public function canEdit(): bool
    {
        return $this->status === self::STATUS_DRAFT;
    }

    /**
     * 발행 완료 여부
     */
    public function isIssued(): bool
    {
        return in_array($this->status, [self::STATUS_ISSUED, self::STATUS_SENT]);
    }

    // =========================================================================
    // 헬퍼 메서드
    // =========================================================================

    /**
     * 사업자번호 포맷팅
     */
    private function formatCorpNum(?string $num): string
    {
        if (! $num || strlen($num) !== 10) {
            return $num ?? '';
        }

        return substr($num, 0, 3).'-'.substr($num, 3, 2).'-'.substr($num, 5);
    }
}
