<?php

namespace App\Models\Finance;

use App\Models\Tenants\Tenant;
use App\Traits\BelongsToTenant;
use App\Traits\ModelTrait;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\SoftDeletes;

/**
 * 자금계획일정 모델
 */
class FundSchedule extends Model
{
    use BelongsToTenant, ModelTrait, SoftDeletes;

    // 일정 유형 상수
    public const TYPE_INCOME = 'income';

    public const TYPE_EXPENSE = 'expense';

    // 상태 상수
    public const STATUS_PENDING = 'pending';

    public const STATUS_COMPLETED = 'completed';

    public const STATUS_CANCELLED = 'cancelled';

    // 반복 규칙 상수
    public const RECURRENCE_DAILY = 'daily';

    public const RECURRENCE_WEEKLY = 'weekly';

    public const RECURRENCE_MONTHLY = 'monthly';

    public const RECURRENCE_YEARLY = 'yearly';

    protected $fillable = [
        'tenant_id',
        'title',
        'description',
        'schedule_type',
        'scheduled_date',
        'amount',
        'currency',
        'related_bank_account_id',
        'counterparty',
        'category',
        'status',
        'is_recurring',
        'recurrence_rule',
        'recurrence_end_date',
        'completed_date',
        'completed_amount',
        'memo',
        'created_by',
        'updated_by',
        'deleted_by',
    ];

    protected $hidden = [
        'created_by',
        'updated_by',
        'deleted_by',
        'deleted_at',
    ];

    protected $casts = [
        'amount' => 'decimal:2',
        'completed_amount' => 'decimal:2',
        'scheduled_date' => 'date:Y-m-d',
        'completed_date' => 'date:Y-m-d',
        'recurrence_end_date' => 'date:Y-m-d',
        'is_recurring' => 'boolean',
    ];

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

    /**
     * 테넌트
     */
    public function tenant(): BelongsTo
    {
        return $this->belongsTo(Tenant::class);
    }

    /**
     * 관련 은행 계좌
     */
    public function bankAccount(): BelongsTo
    {
        return $this->belongsTo(BankAccount::class, 'related_bank_account_id');
    }

    // ============================================================
    // Accessors
    // ============================================================

    /**
     * 포맷된 금액
     */
    public function getFormattedAmountAttribute(): string
    {
        $amount = abs($this->amount);

        if ($amount >= 100000000) {
            return number_format($amount / 100000000, 1).'억원';
        } elseif ($amount >= 10000000) {
            return number_format($amount / 10000000, 1).'천만원';
        } elseif ($amount >= 10000) {
            return number_format($amount / 10000, 0).'만원';
        }

        return number_format($amount).'원';
    }

    /**
     * 일정 유형 라벨
     */
    public function getTypeLabelAttribute(): string
    {
        return match ($this->schedule_type) {
            self::TYPE_INCOME => '입금 예정',
            self::TYPE_EXPENSE => '지급 예정',
            default => '기타',
        };
    }

    /**
     * 상태 라벨
     */
    public function getStatusLabelAttribute(): string
    {
        return match ($this->status) {
            self::STATUS_PENDING => '예정',
            self::STATUS_COMPLETED => '완료',
            self::STATUS_CANCELLED => '취소',
            default => '미정',
        };
    }

    /**
     * 일정 유형별 색상 클래스
     */
    public function getTypeColorClassAttribute(): string
    {
        return match ($this->schedule_type) {
            self::TYPE_INCOME => 'bg-green-100 text-green-800 border-green-200',
            self::TYPE_EXPENSE => 'bg-red-100 text-red-800 border-red-200',
            default => 'bg-gray-100 text-gray-800 border-gray-200',
        };
    }

    /**
     * 상태별 색상 클래스
     */
    public function getStatusColorClassAttribute(): string
    {
        return match ($this->status) {
            self::STATUS_PENDING => 'bg-yellow-100 text-yellow-800',
            self::STATUS_COMPLETED => 'bg-green-100 text-green-800',
            self::STATUS_CANCELLED => 'bg-gray-100 text-gray-500',
            default => 'bg-gray-100 text-gray-800',
        };
    }

    // ============================================================
    // Scopes
    // ============================================================

    /**
     * 입금 예정만
     */
    public function scopeIncome($query)
    {
        return $query->where('schedule_type', self::TYPE_INCOME);
    }

    /**
     * 지급 예정만
     */
    public function scopeExpense($query)
    {
        return $query->where('schedule_type', self::TYPE_EXPENSE);
    }

    /**
     * 예정 상태만
     */
    public function scopePending($query)
    {
        return $query->where('status', self::STATUS_PENDING);
    }

    /**
     * 완료 상태만
     */
    public function scopeCompleted($query)
    {
        return $query->where('status', self::STATUS_COMPLETED);
    }

    /**
     * 특정 월의 일정
     */
    public function scopeForMonth($query, int $year, int $month)
    {
        return $query->whereYear('scheduled_date', $year)
            ->whereMonth('scheduled_date', $month);
    }

    /**
     * 날짜 범위 필터
     */
    public function scopeDateBetween($query, string $startDate, string $endDate)
    {
        return $query->whereBetween('scheduled_date', [$startDate, $endDate]);
    }

    /**
     * 정렬 (예정일 기준)
     */
    public function scopeOrdered($query)
    {
        return $query->orderBy('scheduled_date')->orderBy('id');
    }

    // ============================================================
    // 메서드
    // ============================================================

    /**
     * 입금 예정인지 확인
     */
    public function isIncome(): bool
    {
        return $this->schedule_type === self::TYPE_INCOME;
    }

    /**
     * 지급 예정인지 확인
     */
    public function isExpense(): bool
    {
        return $this->schedule_type === self::TYPE_EXPENSE;
    }

    /**
     * 예정 상태인지 확인
     */
    public function isPending(): bool
    {
        return $this->status === self::STATUS_PENDING;
    }

    /**
     * 완료 상태인지 확인
     */
    public function isCompleted(): bool
    {
        return $this->status === self::STATUS_COMPLETED;
    }

    /**
     * 완료 처리
     */
    public function markAsCompleted(?float $actualAmount = null, ?string $completedDate = null): void
    {
        $this->update([
            'status' => self::STATUS_COMPLETED,
            'completed_date' => $completedDate ?? now()->toDateString(),
            'completed_amount' => $actualAmount ?? $this->amount,
            'updated_by' => auth()->id(),
        ]);
    }

    /**
     * 취소 처리
     */
    public function markAsCancelled(): void
    {
        $this->update([
            'status' => self::STATUS_CANCELLED,
            'updated_by' => auth()->id(),
        ]);
    }

    /**
     * 일정 유형 목록
     */
    public static function getTypeOptions(): array
    {
        return [
            self::TYPE_INCOME => '입금 예정',
            self::TYPE_EXPENSE => '지급 예정',
        ];
    }

    /**
     * 상태 목록
     */
    public static function getStatusOptions(): array
    {
        return [
            self::STATUS_PENDING => '예정',
            self::STATUS_COMPLETED => '완료',
            self::STATUS_CANCELLED => '취소',
        ];
    }

    /**
     * 반복 규칙 목록
     */
    public static function getRecurrenceOptions(): array
    {
        return [
            self::RECURRENCE_DAILY => '매일',
            self::RECURRENCE_WEEKLY => '매주',
            self::RECURRENCE_MONTHLY => '매월',
            self::RECURRENCE_YEARLY => '매년',
        ];
    }
}
