<?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 BankTransaction extends Model
{
    use BelongsToTenant, ModelTrait, SoftDeletes;

    // 거래 유형 상수
    public const TYPE_DEPOSIT = 'deposit';       // 입금

    public const TYPE_WITHDRAWAL = 'withdrawal'; // 출금

    public const TYPE_TRANSFER = 'transfer';     // 이체

    protected $fillable = [
        'tenant_id',
        'bank_account_id',
        'transaction_type',
        'amount',
        'balance_after',
        'transaction_date',
        'transaction_time',
        'description',
        'counterparty',
        'reference_number',
        'category',
        'related_order_id',
        'related_payment_id',
        'is_reconciled',
        'reconciled_at',
        'memo',
        'options',
        'created_by',
        'updated_by',
        'deleted_by',
    ];

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

    protected $casts = [
        'amount' => 'decimal:2',
        'balance_after' => 'decimal:2',
        'transaction_date' => 'date',
        'is_reconciled' => 'boolean',
        'reconciled_at' => 'datetime',
        'options' => 'array',
    ];

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

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

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

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

    /**
     * 입금 여부
     */
    public function getIsDepositAttribute(): bool
    {
        return $this->transaction_type === self::TYPE_DEPOSIT;
    }

    /**
     * 출금 여부
     */
    public function getIsWithdrawalAttribute(): bool
    {
        return $this->transaction_type === self::TYPE_WITHDRAWAL;
    }

    /**
     * 포맷된 금액 (부호 포함)
     */
    public function getFormattedAmountAttribute(): string
    {
        $prefix = $this->is_deposit ? '+' : '-';

        return $prefix.number_format(abs($this->amount)).'원';
    }

    /**
     * 포맷된 잔액
     */
    public function getFormattedBalanceAfterAttribute(): string
    {
        return number_format($this->balance_after).'원';
    }

    /**
     * 거래 유형 라벨
     */
    public function getTypeLabel(): string
    {
        return match ($this->transaction_type) {
            self::TYPE_DEPOSIT => '입금',
            self::TYPE_WITHDRAWAL => '출금',
            self::TYPE_TRANSFER => '이체',
            default => '기타',
        };
    }

    /**
     * 거래 유형 색상 클래스
     */
    public function getTypeColorClass(): string
    {
        return match ($this->transaction_type) {
            self::TYPE_DEPOSIT => 'text-green-600',
            self::TYPE_WITHDRAWAL => 'text-red-600',
            self::TYPE_TRANSFER => 'text-blue-600',
            default => 'text-gray-600',
        };
    }

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

    /**
     * 계좌별 필터
     */
    public function scopeForAccount($query, int $accountId)
    {
        return $query->where('bank_account_id', $accountId);
    }

    /**
     * 거래유형별 필터
     */
    public function scopeOfType($query, string $type)
    {
        return $query->where('transaction_type', $type);
    }

    /**
     * 입금만
     */
    public function scopeDeposits($query)
    {
        return $query->where('transaction_type', self::TYPE_DEPOSIT);
    }

    /**
     * 출금만
     */
    public function scopeWithdrawals($query)
    {
        return $query->where('transaction_type', self::TYPE_WITHDRAWAL);
    }

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

    /**
     * 대사 완료 여부
     */
    public function scopeReconciled($query, bool $isReconciled = true)
    {
        return $query->where('is_reconciled', $isReconciled);
    }

    /**
     * 최신순 정렬
     */
    public function scopeLatest($query)
    {
        return $query->orderBy('transaction_date', 'desc')
            ->orderBy('transaction_time', 'desc')
            ->orderBy('id', 'desc');
    }

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

    /**
     * 대사 완료 처리
     */
    public function markAsReconciled(): void
    {
        $this->update([
            'is_reconciled' => true,
            'reconciled_at' => now(),
        ]);
    }

    /**
     * 대사 취소
     */
    public function unmarkReconciled(): void
    {
        $this->update([
            'is_reconciled' => false,
            'reconciled_at' => null,
        ]);
    }

    /**
     * options에서 특정 키 값 조회
     */
    public function getOption(string $key, mixed $default = null): mixed
    {
        return data_get($this->options, $key, $default);
    }

    /**
     * options에 특정 키 값 설정
     */
    public function setOption(string $key, mixed $value): static
    {
        $options = $this->options ?? [];
        data_set($options, $key, $value);
        $this->options = $options;

        return $this;
    }
}
