<?php

namespace App\Services;

use App\Models\Tenants\Deposit;
use App\Models\Tenants\Purchase;
use App\Models\Tenants\Withdrawal;
use Carbon\Carbon;

class ReportService extends Service
{
    /**
     * 일일 일보 조회
     *
     * @param  array  $params  [date: 기준일]
     */
    public function dailyReport(array $params): array
    {
        $tenantId = $this->tenantId();
        $date = Carbon::parse($params['date'] ?? now()->toDateString());
        $previousDate = $date->copy()->subDay();

        // 전일 잔액 계산 (기준일 전일까지의 모든 입출금 합계)
        $previousBalance = $this->calculateBalanceUntilDate($tenantId, $previousDate);

        // 당일 입금 합계
        $dailyDeposit = Deposit::query()
            ->where('tenant_id', $tenantId)
            ->whereDate('deposit_date', $date)
            ->sum('amount');

        // 당일 출금 합계
        $dailyWithdrawal = Withdrawal::query()
            ->where('tenant_id', $tenantId)
            ->whereDate('withdrawal_date', $date)
            ->sum('amount');

        // 당일 잔액
        $currentBalance = $previousBalance + $dailyDeposit - $dailyWithdrawal;

        // 상세 내역 (입출금 통합)
        $details = $this->getDailyDetails($tenantId, $date);

        return [
            'date' => $date->toDateString(),
            'previous_balance' => (float) $previousBalance,
            'daily_deposit' => (float) $dailyDeposit,
            'daily_withdrawal' => (float) $dailyWithdrawal,
            'current_balance' => (float) $currentBalance,
            'details' => $details,
        ];
    }

    /**
     * 지출 예상 내역서 조회
     *
     * @param  array  $params  [year_month: YYYY-MM 형식]
     */
    public function expenseEstimate(array $params): array
    {
        $tenantId = $this->tenantId();
        $yearMonth = $params['year_month'] ?? now()->format('Y-m');
        [$year, $month] = explode('-', $yearMonth);

        $startDate = Carbon::createFromDate($year, $month, 1)->startOfMonth();
        $endDate = $startDate->copy()->endOfMonth();

        // 미결제 매입 내역 조회 (지출 예상)
        $items = Purchase::query()
            ->where('tenant_id', $tenantId)
            ->whereIn('status', ['draft', 'confirmed'])
            ->whereNull('withdrawal_id')
            ->whereBetween('purchase_date', [$startDate, $endDate])
            ->with(['client:id,name'])
            ->orderBy('purchase_date')
            ->get()
            ->map(function ($purchase) {
                return [
                    'id' => $purchase->id,
                    'expected_date' => $purchase->purchase_date->toDateString(),
                    'item_name' => $purchase->description ?? __('message.report.purchase'),
                    'amount' => (float) $purchase->total_amount,
                    'client_name' => $purchase->client?->name ?? '',
                    'account_name' => '',
                ];
            });

        // 예상 지출 합계
        $totalEstimate = $items->sum('amount');

        // 계좌 잔액 (대표 계좌 기준, 없으면 모든 계좌 합산)
        $accountBalance = $this->getAccountBalance($tenantId);

        // 예상 잔액
        $expectedBalance = $accountBalance - $totalEstimate;

        // 월별 합계
        $monthlySummary = $this->getMonthlySummary($tenantId, $startDate);

        return [
            'year_month' => $yearMonth,
            'total_estimate' => (float) $totalEstimate,
            'account_balance' => (float) $accountBalance,
            'expected_balance' => (float) $expectedBalance,
            'items' => $items->values()->toArray(),
            'monthly_summary' => $monthlySummary,
        ];
    }

    /**
     * 특정 날짜까지의 잔액 계산
     */
    private function calculateBalanceUntilDate(int $tenantId, Carbon $date): float
    {
        $totalDeposits = Deposit::query()
            ->where('tenant_id', $tenantId)
            ->whereDate('deposit_date', '<=', $date)
            ->sum('amount');

        $totalWithdrawals = Withdrawal::query()
            ->where('tenant_id', $tenantId)
            ->whereDate('withdrawal_date', '<=', $date)
            ->sum('amount');

        return (float) ($totalDeposits - $totalWithdrawals);
    }

    /**
     * 일일 상세 내역 조회 (입출금 통합)
     */
    private function getDailyDetails(int $tenantId, Carbon $date): array
    {
        // 입금 내역
        $deposits = Deposit::query()
            ->where('tenant_id', $tenantId)
            ->whereDate('deposit_date', $date)
            ->with(['client:id,name'])
            ->get()
            ->map(function ($deposit) {
                return [
                    'type' => 'deposit',
                    'type_label' => __('message.report.deposit'),
                    'client_name' => $deposit->client?->name ?? $deposit->client_name ?? '',
                    'account_code' => $deposit->account_code ?? '',
                    'deposit_amount' => (float) $deposit->amount,
                    'withdrawal_amount' => 0,
                    'description' => $deposit->description ?? '',
                    'payment_method' => $deposit->payment_method,
                ];
            });

        // 출금 내역
        $withdrawals = Withdrawal::query()
            ->where('tenant_id', $tenantId)
            ->whereDate('withdrawal_date', $date)
            ->with(['client:id,name'])
            ->get()
            ->map(function ($withdrawal) {
                return [
                    'type' => 'withdrawal',
                    'type_label' => __('message.report.withdrawal'),
                    'client_name' => $withdrawal->client?->name ?? $withdrawal->client_name ?? '',
                    'account_code' => $withdrawal->account_code ?? '',
                    'deposit_amount' => 0,
                    'withdrawal_amount' => (float) $withdrawal->amount,
                    'description' => $withdrawal->description ?? '',
                    'payment_method' => $withdrawal->payment_method,
                ];
            });

        return $deposits->concat($withdrawals)->values()->toArray();
    }

    /**
     * 계좌 잔액 조회
     * 입출금 내역 기반으로 계산
     */
    private function getAccountBalance(int $tenantId): float
    {
        return $this->calculateBalanceUntilDate($tenantId, Carbon::now());
    }

    /**
     * 월별 지출 예상 합계
     */
    private function getMonthlySummary(int $tenantId, Carbon $baseDate): array
    {
        $summary = [];

        // 기준월부터 3개월간 집계
        for ($i = 0; $i < 3; $i++) {
            $targetDate = $baseDate->copy()->addMonths($i);
            $startOfMonth = $targetDate->copy()->startOfMonth();
            $endOfMonth = $targetDate->copy()->endOfMonth();

            $total = Purchase::query()
                ->where('tenant_id', $tenantId)
                ->whereIn('status', ['draft', 'confirmed'])
                ->whereNull('withdrawal_id')
                ->whereBetween('purchase_date', [$startOfMonth, $endOfMonth])
                ->sum('total_amount');

            $summary[] = [
                'month' => $targetDate->format('Y/m'),
                'total' => (float) $total,
            ];
        }

        // 전체 합계
        $grandTotal = collect($summary)->sum('total');

        // 계좌 잔액
        $accountBalance = $this->getAccountBalance($tenantId);

        return [
            'by_month' => $summary,
            'total_expense' => $grandTotal,
            'account_balance' => $accountBalance,
            'final_difference' => $accountBalance - $grandTotal,
        ];
    }
}
