<?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\HasMany;
use Illuminate\Database\Eloquent\SoftDeletes;

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

    protected $fillable = [
        'tenant_id',
        'bill_number',
        'bill_type',
        'client_id',
        'client_name',
        'amount',
        'issue_date',
        'maturity_date',
        'status',
        'reason',
        'installment_count',
        'note',
        'is_electronic',
        'bank_account_id',
        'created_by',
        'updated_by',
        'deleted_by',
        // V8 확장 필드
        'instrument_type',
        'medium',
        'bill_category',
        'electronic_bill_no',
        'registration_org',
        'drawee',
        'acceptance_status',
        'acceptance_date',
        'acceptance_refusal_date',
        'acceptance_refusal_reason',
        'endorsement',
        'endorsement_order',
        'storage_place',
        'issuer_bank',
        'is_discounted',
        'discount_date',
        'discount_bank',
        'discount_rate',
        'discount_amount',
        'endorsement_date',
        'endorsee',
        'endorsement_reason',
        'collection_bank',
        'collection_request_date',
        'collection_fee',
        'collection_complete_date',
        'collection_result',
        'collection_deposit_date',
        'collection_deposit_amount',
        'settlement_bank',
        'payment_method',
        'actual_payment_date',
        'payment_place',
        'payment_place_detail',
        'renewal_date',
        'renewal_new_bill_no',
        'renewal_reason',
        'recourse_date',
        'recourse_amount',
        'recourse_target',
        'recourse_reason',
        'buyback_date',
        'buyback_amount',
        'buyback_bank',
        'dishonored_date',
        'dishonored_reason',
        'has_protest',
        'protest_date',
        'recourse_notice_date',
        'recourse_notice_deadline',
        'is_split',
    ];

    protected $casts = [
        'issue_date' => 'date',
        'maturity_date' => 'date',
        'amount' => 'decimal:2',
        'client_id' => 'integer',
        'bank_account_id' => 'integer',
        'installment_count' => 'integer',
        'is_electronic' => 'boolean',
        // V8 확장 casts
        'acceptance_date' => 'date',
        'acceptance_refusal_date' => 'date',
        'discount_date' => 'date',
        'discount_rate' => 'decimal:2',
        'discount_amount' => 'decimal:2',
        'endorsement_date' => 'date',
        'collection_request_date' => 'date',
        'collection_fee' => 'decimal:2',
        'collection_complete_date' => 'date',
        'collection_deposit_date' => 'date',
        'collection_deposit_amount' => 'decimal:2',
        'actual_payment_date' => 'date',
        'renewal_date' => 'date',
        'recourse_date' => 'date',
        'recourse_amount' => 'decimal:2',
        'buyback_date' => 'date',
        'buyback_amount' => 'decimal:2',
        'dishonored_date' => 'date',
        'protest_date' => 'date',
        'recourse_notice_date' => 'date',
        'recourse_notice_deadline' => 'date',
        'is_discounted' => 'boolean',
        'has_protest' => 'boolean',
        'is_split' => 'boolean',
    ];

    /**
     * 배열/JSON 변환 시 날짜 형식 지정
     */
    /**
     * 날짜 cast 필드 목록 (toArray에서 Y-m-d 형식 변환용)
     */
    private const DATE_FIELDS = [
        'issue_date', 'maturity_date',
        'acceptance_date', 'acceptance_refusal_date',
        'discount_date', 'endorsement_date',
        'collection_request_date', 'collection_complete_date', 'collection_deposit_date',
        'actual_payment_date',
        'renewal_date', 'recourse_date', 'buyback_date',
        'dishonored_date', 'protest_date', 'recourse_notice_date', 'recourse_notice_deadline',
    ];

    public function toArray(): array
    {
        $array = parent::toArray();

        foreach (self::DATE_FIELDS as $field) {
            if (isset($array[$field]) && $this->{$field}) {
                $array[$field] = $this->{$field}->format('Y-m-d');
            }
        }

        return $array;
    }

    /**
     * 어음 구분 목록
     */
    public const BILL_TYPES = [
        'received' => '수취',
        'issued' => '발행',
    ];

    /**
     * 증권종류
     */
    public const INSTRUMENT_TYPES = [
        'promissory' => '약속어음',
        'exchange' => '환어음',
        'cashierCheck' => '자기앞수표',
        'currentCheck' => '당좌수표',
    ];

    /**
     * 수취 어음 상태 목록
     */
    public const RECEIVED_STATUSES = [
        'stored' => '보관중',
        'endorsed' => '배서양도',
        'discounted' => '할인',
        'collectionRequest' => '추심의뢰',
        'collectionComplete' => '추심완료',
        'maturityDeposit' => '만기입금',
        'paymentComplete' => '결제완료',
        'dishonored' => '부도',
        'renewed' => '개서',
        'buyback' => '환매',
        // 하위호환
        'maturityAlert' => '만기입금(7일전)',
        'maturityResult' => '만기결과',
    ];

    /**
     * 수취 수표 상태 목록
     */
    public const RECEIVED_CHECK_STATUSES = [
        'stored' => '보관중',
        'endorsed' => '배서양도',
        'deposited' => '입금',
        'dishonored' => '부도',
    ];

    /**
     * 발행 어음 상태 목록
     */
    public const ISSUED_STATUSES = [
        'stored' => '보관중',
        'issued' => '지급대기',
        'maturityPayment' => '만기결제',
        'paymentComplete' => '결제완료',
        'dishonored' => '부도',
        'renewed' => '개서',
        // 하위호환
        'maturityAlert' => '만기입금(7일전)',
        'collectionRequest' => '추심의뢰',
        'collectionComplete' => '추심완료',
        'suing' => '추소중',
    ];

    /**
     * 발행 수표 상태 목록
     */
    public const ISSUED_CHECK_STATUSES = [
        'stored' => '보관중',
        'issued' => '지급대기',
        'cashed' => '현금화',
        'dishonored' => '부도',
    ];

    /**
     * 거래처 관계
     */
    public function client(): BelongsTo
    {
        return $this->belongsTo(\App\Models\Orders\Client::class);
    }

    /**
     * 입금/출금 계좌 관계
     */
    public function bankAccount(): BelongsTo
    {
        return $this->belongsTo(BankAccount::class);
    }

    /**
     * 차수 관계
     */
    public function installments(): HasMany
    {
        return $this->hasMany(BillInstallment::class);
    }

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

    /**
     * 거래처명 조회 (회원/비회원 통합)
     */
    public function getDisplayClientNameAttribute(): string
    {
        if ($this->client) {
            return $this->client->name;
        }

        return $this->client_name ?? '';
    }

    /**
     * 어음 구분 라벨
     */
    public function getBillTypeLabelAttribute(): string
    {
        return self::BILL_TYPES[$this->bill_type] ?? $this->bill_type;
    }

    /**
     * 상태 라벨
     */
    public function getStatusLabelAttribute(): string
    {
        $isCheck = in_array($this->instrument_type, ['cashierCheck', 'currentCheck']);

        if ($this->bill_type === 'received') {
            $statuses = $isCheck ? self::RECEIVED_CHECK_STATUSES : self::RECEIVED_STATUSES;

            return $statuses[$this->status] ?? self::RECEIVED_STATUSES[$this->status] ?? $this->status;
        }

        $statuses = $isCheck ? self::ISSUED_CHECK_STATUSES : self::ISSUED_STATUSES;

        return $statuses[$this->status] ?? self::ISSUED_STATUSES[$this->status] ?? $this->status;
    }

    /**
     * 증권종류 라벨
     */
    public function getInstrumentTypeLabelAttribute(): string
    {
        return self::INSTRUMENT_TYPES[$this->instrument_type] ?? $this->instrument_type ?? '약속어음';
    }

    /**
     * 만기까지 남은 일수
     */
    public function getDaysToMaturityAttribute(): int
    {
        return now()->diffInDays($this->maturity_date, false);
    }

    /**
     * 만기 7일 전 여부
     */
    public function isMaturityAlertPeriod(): bool
    {
        $days = $this->days_to_maturity;

        return $days >= 0 && $days <= 7;
    }
}
