<?php

namespace App\Services\Stats;

use App\Models\Stats\Daily\StatFinanceDaily;
use App\Models\Stats\Monthly\StatFinanceMonthly;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;

class FinanceStatService implements StatDomainServiceInterface
{
    public function aggregateDaily(int $tenantId, Carbon $date): int
    {
        $dateStr = $date->format('Y-m-d');

        // 입금 (deposits)
        $depositStats = DB::connection('mysql')
            ->table('deposits')
            ->where('tenant_id', $tenantId)
            ->where('deposit_date', $dateStr)
            ->whereNull('deleted_at')
            ->selectRaw('COUNT(*) as cnt, COALESCE(SUM(amount), 0) as total')
            ->first();

        // 출금 (withdrawals)
        $withdrawalStats = DB::connection('mysql')
            ->table('withdrawals')
            ->where('tenant_id', $tenantId)
            ->where('withdrawal_date', $dateStr)
            ->whereNull('deleted_at')
            ->selectRaw('COUNT(*) as cnt, COALESCE(SUM(amount), 0) as total')
            ->first();

        // 매입 (purchases)
        $purchaseStats = DB::connection('mysql')
            ->table('purchases')
            ->where('tenant_id', $tenantId)
            ->where('purchase_date', $dateStr)
            ->whereNull('deleted_at')
            ->selectRaw('
                COUNT(*) as cnt,
                COALESCE(SUM(supply_amount), 0) as supply_total,
                COALESCE(SUM(tax_amount), 0) as tax_total
            ')
            ->first();

        // 어음 발행 (bills - issued on this date)
        $billIssuedStats = DB::connection('mysql')
            ->table('bills')
            ->where('tenant_id', $tenantId)
            ->where('issue_date', $dateStr)
            ->whereNull('deleted_at')
            ->selectRaw('COUNT(*) as cnt, COALESCE(SUM(amount), 0) as total')
            ->first();

        // 어음 만기 (bills - matured on this date)
        $billMaturedStats = DB::connection('mysql')
            ->table('bills')
            ->where('tenant_id', $tenantId)
            ->where('maturity_date', $dateStr)
            ->whereNull('deleted_at')
            ->selectRaw('COUNT(*) as cnt, COALESCE(SUM(amount), 0) as total')
            ->first();

        // 카드 거래 (withdrawals with card_id)
        $cardStats = DB::connection('mysql')
            ->table('withdrawals')
            ->where('tenant_id', $tenantId)
            ->where('withdrawal_date', $dateStr)
            ->whereNotNull('card_id')
            ->whereNull('deleted_at')
            ->selectRaw('COUNT(*) as cnt, COALESCE(SUM(amount), 0) as total')
            ->first();

        // 은행 잔액 합계 (bank_transactions - 계좌별 최신 잔액)
        $bankBalance = DB::connection('mysql')
            ->query()
            ->fromSub(function ($query) use ($tenantId, $dateStr) {
                $query->from('bank_transactions')
                    ->where('tenant_id', $tenantId)
                    ->where('transaction_date', '<=', $dateStr)
                    ->whereNull('deleted_at')
                    ->selectRaw('bank_account_id, balance_after as latest_balance,
                        ROW_NUMBER() OVER(PARTITION BY bank_account_id ORDER BY transaction_date DESC, id DESC) as rn');
            }, 'sub')
            ->where('rn', 1)
            ->selectRaw('COALESCE(SUM(latest_balance), 0) as total_balance')
            ->first();

        $depositAmount = $depositStats->total ?? 0;
        $withdrawalAmount = $withdrawalStats->total ?? 0;

        StatFinanceDaily::updateOrCreate(
            ['tenant_id' => $tenantId, 'stat_date' => $dateStr],
            [
                'deposit_count' => $depositStats->cnt ?? 0,
                'deposit_amount' => $depositAmount,
                'withdrawal_count' => $withdrawalStats->cnt ?? 0,
                'withdrawal_amount' => $withdrawalAmount,
                'net_cashflow' => $depositAmount - $withdrawalAmount,
                'purchase_count' => $purchaseStats->cnt ?? 0,
                'purchase_amount' => $purchaseStats->supply_total ?? 0,
                'purchase_tax_amount' => $purchaseStats->tax_total ?? 0,
                'receivable_balance' => 0, // Phase 3에서 미수금 로직 추가
                'payable_balance' => 0,
                'overdue_receivable' => 0,
                'bill_issued_count' => $billIssuedStats->cnt ?? 0,
                'bill_issued_amount' => $billIssuedStats->total ?? 0,
                'bill_matured_count' => $billMaturedStats->cnt ?? 0,
                'bill_matured_amount' => $billMaturedStats->total ?? 0,
                'card_transaction_count' => $cardStats->cnt ?? 0,
                'card_transaction_amount' => $cardStats->total ?? 0,
                'bank_balance_total' => $bankBalance->total_balance ?? 0,
            ]
        );

        return 1;
    }

    public function aggregateMonthly(int $tenantId, int $year, int $month): int
    {
        $dailySum = StatFinanceDaily::where('tenant_id', $tenantId)
            ->whereYear('stat_date', $year)
            ->whereMonth('stat_date', $month)
            ->selectRaw('
                SUM(deposit_amount) as deposit_total,
                SUM(withdrawal_amount) as withdrawal_total,
                SUM(net_cashflow) as net_cashflow,
                SUM(purchase_amount) as purchase_total,
                SUM(card_transaction_amount) as card_total
            ')
            ->first();

        // 월말 데이터 (해당 월의 마지막 일간 레코드)
        $lastDay = StatFinanceDaily::where('tenant_id', $tenantId)
            ->whereYear('stat_date', $year)
            ->whereMonth('stat_date', $month)
            ->orderByDesc('stat_date')
            ->first();

        // 전월 대비 현금흐름 변화
        $prevMonth = StatFinanceMonthly::where('tenant_id', $tenantId)
            ->where(function ($q) use ($year, $month) {
                $prev = Carbon::create($year, $month, 1)->subMonth();
                $q->where('stat_year', $prev->year)->where('stat_month', $prev->month);
            })
            ->first();

        $netCashflow = $dailySum->net_cashflow ?? 0;
        $momChange = null;
        if ($prevMonth && $prevMonth->net_cashflow != 0) {
            $momChange = (($netCashflow - $prevMonth->net_cashflow) / abs($prevMonth->net_cashflow)) * 100;
        }

        StatFinanceMonthly::updateOrCreate(
            ['tenant_id' => $tenantId, 'stat_year' => $year, 'stat_month' => $month],
            [
                'deposit_total' => $dailySum->deposit_total ?? 0,
                'withdrawal_total' => $dailySum->withdrawal_total ?? 0,
                'net_cashflow' => $netCashflow,
                'purchase_total' => $dailySum->purchase_total ?? 0,
                'card_total' => $dailySum->card_total ?? 0,
                'receivable_end' => $lastDay->receivable_balance ?? 0,
                'payable_end' => $lastDay->payable_balance ?? 0,
                'bank_balance_end' => $lastDay->bank_balance_total ?? 0,
                'mom_cashflow_change' => $momChange,
            ]
        );

        return 1;
    }
}
