<?php

namespace App\Observers\ExpenseSync;

use App\Models\Tenants\Bill;
use App\Models\Tenants\ExpectedExpense;

/**
 * 발행어음 데이터를 예상 지출(expected_expenses)로 자동 동기화
 * (bill_type = 'issued' 인 경우만)
 */
class BillExpenseSyncObserver
{
    /**
     * 어음 생성 시 → 발행어음인 경우 예상 지출 생성
     */
    public function created(Bill $bill): void
    {
        if ($this->isIssuedBill($bill)) {
            $this->syncToExpectedExpense($bill);
        }
    }

    /**
     * 어음 수정 시 → 발행어음 상태 변경 처리
     */
    public function updated(Bill $bill): void
    {
        $wasIssued = $bill->getOriginal('bill_type') === 'issued';
        $isIssued = $this->isIssuedBill($bill);

        if ($isIssued) {
            // 발행어음 → 동기화
            $this->syncToExpectedExpense($bill);
        } elseif ($wasIssued && ! $isIssued) {
            // 발행어음에서 수취어음으로 변경 → 예상 지출 삭제
            $this->deleteExpectedExpense($bill);
        }
    }

    /**
     * 어음 삭제 시 → 예상 지출 삭제
     */
    public function deleted(Bill $bill): void
    {
        if ($this->isIssuedBill($bill)) {
            $this->deleteExpectedExpense($bill);
        }
    }

    /**
     * 어음 복원 시 → 발행어음인 경우 예상 지출 복원
     */
    public function restored(Bill $bill): void
    {
        if (! $this->isIssuedBill($bill)) {
            return;
        }

        $expense = ExpectedExpense::withTrashed()
            ->withoutGlobalScopes()
            ->bySource('bills', $bill->id)
            ->first();

        if ($expense) {
            $expense->restore();
            $this->updateExpectedExpense($expense, $bill);
        } else {
            $this->createExpectedExpense($bill);
        }
    }

    /**
     * 어음 강제 삭제 시 → 예상 지출 강제 삭제
     */
    public function forceDeleted(Bill $bill): void
    {
        ExpectedExpense::withTrashed()
            ->withoutGlobalScopes()
            ->bySource('bills', $bill->id)
            ->forceDelete();
    }

    /**
     * 발행어음 여부 확인
     */
    protected function isIssuedBill(Bill $bill): bool
    {
        return $bill->bill_type === 'issued';
    }

    /**
     * 예상 지출에 동기화
     */
    protected function syncToExpectedExpense(Bill $bill): void
    {
        $expense = ExpectedExpense::withoutGlobalScopes()
            ->bySource('bills', $bill->id)
            ->first();

        if ($expense) {
            $this->updateExpectedExpense($expense, $bill);
        } else {
            $this->createExpectedExpense($bill);
        }
    }

    /**
     * 예상 지출 삭제
     */
    protected function deleteExpectedExpense(Bill $bill): void
    {
        ExpectedExpense::withoutGlobalScopes()
            ->bySource('bills', $bill->id)
            ->delete();
    }

    /**
     * 어음 상태 → 지급상태 매핑
     */
    protected function mapPaymentStatus(string $billStatus): string
    {
        return match ($billStatus) {
            'paymentComplete', 'collectionComplete' => 'paid',
            'dishonored' => 'overdue',
            default => 'pending',
        };
    }

    /**
     * 예상 지출 생성
     */
    protected function createExpectedExpense(Bill $bill): void
    {
        ExpectedExpense::create([
            'tenant_id' => $bill->tenant_id,
            'expected_payment_date' => $bill->maturity_date, // 만기일을 예상 지급일로
            'transaction_type' => 'bill',
            'amount' => $bill->amount,
            'client_id' => $bill->client_id,
            'client_name' => $bill->client_name,
            'bank_account_id' => $bill->bank_account_id,
            'description' => $bill->note ?? "어음번호: {$bill->bill_number}",
            'payment_status' => $this->mapPaymentStatus($bill->status),
            'approval_status' => 'none',
            'source_type' => 'bills',
            'source_id' => $bill->id,
            'created_by' => $bill->created_by,
            'updated_by' => $bill->updated_by,
        ]);
    }

    /**
     * 예상 지출 업데이트
     */
    protected function updateExpectedExpense(ExpectedExpense $expense, Bill $bill): void
    {
        $expense->update([
            'expected_payment_date' => $bill->maturity_date,
            'amount' => $bill->amount,
            'client_id' => $bill->client_id,
            'client_name' => $bill->client_name,
            'bank_account_id' => $bill->bank_account_id,
            'description' => $bill->note ?? "어음번호: {$bill->bill_number}",
            'payment_status' => $this->mapPaymentStatus($bill->status),
            'updated_by' => $bill->updated_by,
        ]);
    }
}
