<?php

namespace App\Models\Tenants;

use App\Models\Members\User;
use App\Traits\Auditable;
use App\Traits\BelongsToTenant;
use App\Traits\ModelTrait;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\SoftDeletes;

class Loan extends Model
{
    use Auditable, BelongsToTenant, HasFactory, ModelTrait, SoftDeletes;

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

    /**
     * 상태 상수
     */
    public const STATUS_OUTSTANDING = 'outstanding'; // 미정산

    public const STATUS_SETTLED = 'settled';         // 정산완료

    public const STATUS_PARTIAL = 'partial';         // 부분정산

    public const STATUS_HOLDING = 'holding';         // 보유 (상품권)

    public const STATUS_USED = 'used';               // 사용 (상품권)

    public const STATUS_DISPOSED = 'disposed';       // 폐기 (상품권)

    /**
     * 상태 목록
     */
    public const STATUSES = [
        self::STATUS_OUTSTANDING,
        self::STATUS_SETTLED,
        self::STATUS_PARTIAL,
        self::STATUS_HOLDING,
        self::STATUS_USED,
        self::STATUS_DISPOSED,
    ];

    /**
     * 카테고리 상수 (D1.7 기획서)
     */
    public const CATEGORY_CARD = 'card';                       // 카드

    public const CATEGORY_CONGRATULATORY = 'congratulatory';   // 경조사

    public const CATEGORY_GIFT_CERTIFICATE = 'gift_certificate'; // 상품권

    public const CATEGORY_ENTERTAINMENT = 'entertainment';     // 접대비

    /**
     * 카테고리 목록
     */
    public const CATEGORIES = [
        self::CATEGORY_CARD,
        self::CATEGORY_CONGRATULATORY,
        self::CATEGORY_GIFT_CERTIFICATE,
        self::CATEGORY_ENTERTAINMENT,
    ];

    /**
     * 카테고리 라벨 매핑
     */
    public const CATEGORY_LABELS = [
        self::CATEGORY_CARD => '카드',
        self::CATEGORY_CONGRATULATORY => '경조사',
        self::CATEGORY_GIFT_CERTIFICATE => '상품권',
        self::CATEGORY_ENTERTAINMENT => '접대비',
    ];

    /**
     * 인정이자율 (연도별)
     */
    public const INTEREST_RATES = [
        2024 => 4.6,
        2025 => 4.6,
    ];

    /**
     * 기본 인정이자율 (연도 미설정시)
     */
    public const DEFAULT_INTEREST_RATE = 4.6;

    /**
     * 세금 요율
     */
    public const CORPORATE_TAX_RATE = 0.19;   // 법인세 추가 19%

    public const INCOME_TAX_RATE = 0.35;      // 소득세 추가 35%

    public const LOCAL_TAX_RATE = 0.10;       // 지방소득세 10%

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

    protected $fillable = [
        'tenant_id',
        'user_id',
        'loan_date',
        'amount',
        'purpose',
        'settlement_date',
        'settlement_amount',
        'status',
        'category',
        'metadata',
        'withdrawal_id',
        'created_by',
        'updated_by',
        'deleted_by',
    ];

    protected $casts = [
        'loan_date' => 'date',
        'settlement_date' => 'date',
        'amount' => 'decimal:2',
        'settlement_amount' => 'decimal:2',
        'metadata' => 'array',
    ];

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

    /**
     * 가지급금 수령자
     */
    public function user(): BelongsTo
    {
        return $this->belongsTo(User::class);
    }

    /**
     * 출금 내역
     */
    public function withdrawal(): BelongsTo
    {
        return $this->belongsTo(Withdrawal::class);
    }

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

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

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

    /**
     * 상태 레이블
     */
    public function getStatusLabelAttribute(): string
    {
        return match ($this->status) {
            self::STATUS_OUTSTANDING => '미정산',
            self::STATUS_SETTLED => '정산완료',
            self::STATUS_PARTIAL => '부분정산',
            self::STATUS_HOLDING => '보유',
            self::STATUS_USED => '사용',
            self::STATUS_DISPOSED => '폐기',
            default => $this->status,
        };
    }

    /**
     * 카테고리 라벨
     */
    public function getCategoryLabelAttribute(): string
    {
        return self::CATEGORY_LABELS[$this->category] ?? $this->category ?? '카드';
    }

    /**
     * 미정산 잔액
     */
    public function getOutstandingAmountAttribute(): float
    {
        $settlementAmount = (float) ($this->settlement_amount ?? 0);

        return (float) $this->amount - $settlementAmount;
    }

    /**
     * 경과일수 계산
     */
    public function getElapsedDaysAttribute(): int
    {
        if ($this->settlement_date) {
            return $this->loan_date->diffInDays($this->settlement_date);
        }

        return $this->loan_date->diffInDays(now());
    }

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

    /**
     * 수정 가능 여부 (미정산 상태 또는 상품권)
     */
    public function isEditable(): bool
    {
        if ($this->category === self::CATEGORY_GIFT_CERTIFICATE) {
            return true;
        }

        return in_array($this->status, [
            self::STATUS_OUTSTANDING,
            self::STATUS_HOLDING,
        ]);
    }

    /**
     * 삭제 가능 여부 (미정산/보유 상태 또는 상품권)
     */
    public function isDeletable(): bool
    {
        if ($this->category === self::CATEGORY_GIFT_CERTIFICATE) {
            return true;
        }

        return in_array($this->status, [
            self::STATUS_OUTSTANDING,
            self::STATUS_HOLDING,
        ]);
    }

    /**
     * 정산 가능 여부
     */
    public function isSettleable(): bool
    {
        return in_array($this->status, [self::STATUS_OUTSTANDING, self::STATUS_PARTIAL]);
    }

    // =========================================================================
    // 인정이자 계산 메서드
    // =========================================================================

    /**
     * 연도별 인정이자율 조회
     */
    public static function getInterestRate(int $year): float
    {
        return self::INTEREST_RATES[$year] ?? self::DEFAULT_INTEREST_RATE;
    }

    /**
     * 인정이자 계산
     *
     * @param  int|null  $elapsedDays  경과일수 (미지정시 자동 계산)
     * @param  int|null  $year  연도 (미지정시 지급일 연도)
     */
    public function calculateRecognizedInterest(?int $elapsedDays = null, ?int $year = null): float
    {
        $days = $elapsedDays ?? $this->elapsed_days;
        $rateYear = $year ?? $this->loan_date->year;
        $annualRate = self::getInterestRate($rateYear);
        $dailyRate = $annualRate / 365 / 100;

        return (float) $this->outstanding_amount * $dailyRate * $days;
    }

    /**
     * 세금 계산 (인정이자 기반)
     *
     * @param  float|null  $recognizedInterest  인정이자 (미지정시 자동 계산)
     */
    public function calculateTaxes(?float $recognizedInterest = null): array
    {
        $interest = $recognizedInterest ?? $this->calculateRecognizedInterest();

        $corporateTax = $interest * self::CORPORATE_TAX_RATE;
        $incomeTax = $interest * self::INCOME_TAX_RATE;
        $localTax = $incomeTax * self::LOCAL_TAX_RATE;
        $totalTax = $corporateTax + $incomeTax + $localTax;

        return [
            'recognized_interest' => round($interest, 2),
            'corporate_tax' => round($corporateTax, 2),
            'income_tax' => round($incomeTax, 2),
            'local_tax' => round($localTax, 2),
            'total_tax' => round($totalTax, 2),
        ];
    }
}
