<?php

namespace App\Services;

use App\Models\BadDebts\BadDebt;
use App\Models\Orders\Client;
use App\Models\Tenants\Approval;
use App\Models\Tenants\ApprovalStep;
use App\Models\Tenants\Deposit;
use App\Models\Tenants\ExpectedExpense;
use Carbon\Carbon;

/**
 * 종합 분석 보고서 서비스
 */
class ComprehensiveAnalysisService extends Service
{
    /**
     * 종합 분석 데이터 조회
     */
    public function getAnalysis(array $params): array
    {
        $date = isset($params['date']) ? Carbon::parse($params['date']) : Carbon::today();
        $month = $date->month;
        $year = $date->year;

        return [
            'today_issue' => $this->getTodayIssue($date),
            'monthly_expense' => $this->getMonthlyExpense($year, $month),
            'card_management' => $this->getCardManagement($year, $month),
            'entertainment' => $this->getEntertainment($year, $month),
            'welfare' => $this->getWelfare($year, $month),
            'receivable' => $this->getReceivable($year, $month),
            'debt_collection' => $this->getDebtCollection(),
        ];
    }

    /**
     * 오늘의 이슈 - 현재 사용자가 결재할 수 있는 대기 문서
     */
    protected function getTodayIssue(Carbon $date): array
    {
        $tenantId = $this->tenantId();
        $userId = $this->apiUserId();

        // 현재 사용자가 결재자인 대기 문서만 조회
        $pendingApprovals = Approval::where('tenant_id', $tenantId)
            ->pending()
            ->whereHas('steps', function ($q) use ($userId) {
                $q->where('approver_id', $userId)
                    ->where('status', ApprovalStep::STATUS_PENDING);
            })
            ->with(['form', 'drafter'])
            ->orderBy('drafted_at', 'desc')
            ->limit(10)
            ->get();

        $categories = ['전체필터'];
        $items = [];

        foreach ($pendingApprovals as $approval) {
            $category = $approval->form?->name ?? '결재요청';
            if (! in_array($category, $categories)) {
                $categories[] = $category;
            }

            $items[] = [
                'id' => (string) $approval->id,
                'category' => $category,
                'description' => $approval->title,
                'requires_approval' => true,
                'time' => $approval->drafted_at?->format('H:i') ?? '',
            ];
        }

        return [
            'filter_options' => $categories,
            'items' => $items,
        ];
    }

    /**
     * 당월 예상 지출 내역
     */
    protected function getMonthlyExpense(int $year, int $month): array
    {
        $tenantId = $this->tenantId();

        // 이번 달 예상 지출 합계 (유형별)
        $expenses = ExpectedExpense::where('tenant_id', $tenantId)
            ->whereYear('expected_payment_date', $year)
            ->whereMonth('expected_payment_date', $month)
            ->selectRaw('transaction_type, SUM(amount) as total')
            ->groupBy('transaction_type')
            ->get()
            ->keyBy('transaction_type');

        // 전월 데이터
        $lastMonth = $month === 1 ? 12 : $month - 1;
        $lastYear = $month === 1 ? $year - 1 : $year;
        $lastMonthExpenses = ExpectedExpense::where('tenant_id', $tenantId)
            ->whereYear('expected_payment_date', $lastYear)
            ->whereMonth('expected_payment_date', $lastMonth)
            ->selectRaw('transaction_type, SUM(amount) as total')
            ->groupBy('transaction_type')
            ->get()
            ->keyBy('transaction_type');

        // 실제 데이터 추출
        $purchaseTotal = (float) ($expenses['purchase']->total ?? 0);
        $cardTotal = (float) ($expenses['card']->total ?? 0);
        $billTotal = (float) ($expenses['bill']->total ?? 0);

        $lastPurchase = (float) ($lastMonthExpenses['purchase']->total ?? 0);
        $lastCard = (float) ($lastMonthExpenses['card']->total ?? 0);
        $lastBill = (float) ($lastMonthExpenses['bill']->total ?? 0);

        // 데이터가 없으면 더미 데이터 사용
        $hasData = $purchaseTotal > 0 || $cardTotal > 0 || $billTotal > 0;

        if (! $hasData) {
            $purchaseTotal = 45000000; // 매입 4,500만원
            $cardTotal = 8500000; // 카드 850만원
            $billTotal = 12000000; // 발행어음 1,200만원
            $lastPurchase = 42000000; // 전월 매입 4,200만원
            $lastCard = 7800000; // 전월 카드 780만원
            $lastBill = 11500000; // 전월 발행어음 1,150만원
        }

        $totalExpense = $purchaseTotal + $cardTotal + $billTotal;
        $lastTotalExpense = $lastPurchase + $lastCard + $lastBill;

        // 전월 대비 증감률 계산
        $calculateChange = function ($current, $previous) {
            if ($previous == 0) {
                return $current > 0 ? '+100%' : '0%';
            }
            $change = (($current - $previous) / $previous) * 100;

            return ($change >= 0 ? '+' : '').number_format($change, 1).'%';
        };

        $cards = [
            [
                'id' => 'expense-1',
                'label' => '매입',
                'amount' => $purchaseTotal,
                'previous_amount' => $lastPurchase,
                'previous_label' => '전월 대비 '.$calculateChange($purchaseTotal, $lastPurchase),
            ],
            [
                'id' => 'expense-2',
                'label' => '카드',
                'amount' => $cardTotal,
                'previous_amount' => $lastCard,
                'previous_label' => '전월 대비 '.$calculateChange($cardTotal, $lastCard),
            ],
            [
                'id' => 'expense-3',
                'label' => '발행어음',
                'amount' => $billTotal,
                'previous_amount' => $lastBill,
                'previous_label' => '전월 대비 '.$calculateChange($billTotal, $lastBill),
            ],
            [
                'id' => 'expense-4',
                'label' => '총 예상 지출 합계',
                'amount' => $totalExpense,
                'previous_amount' => $lastTotalExpense,
                'previous_label' => '전월 대비 '.$calculateChange($totalExpense, $lastTotalExpense),
            ],
        ];

        $checkPoints = [];
        $changeRate = $lastTotalExpense > 0 ? (($totalExpense - $lastTotalExpense) / $lastTotalExpense) * 100 : 0;

        if ($changeRate > 15) {
            $checkPoints[] = [
                'id' => 'expense-cp-1',
                'type' => 'warning',
                'message' => '이번 달 예상 지출이',
                'highlight' => '전월 대비 '.number_format($changeRate, 0).'% 증가했습니다. 매입 비용 증가가 주요 원인입니다.',
            ];
        } elseif ($changeRate < -5) {
            $checkPoints[] = [
                'id' => 'expense-cp-1',
                'type' => 'success',
                'message' => '이번 달 예상 지출이',
                'highlight' => '전월 대비 '.number_format(abs($changeRate), 0).'% 감소했습니다.',
            ];
        } else {
            $checkPoints[] = [
                'id' => 'expense-cp-1',
                'type' => 'info',
                'message' => '이번 달 예상 지출이',
                'highlight' => '전월과 비슷한 수준입니다.',
            ];
        }

        return [
            'cards' => $cards,
            'check_points' => $checkPoints,
        ];
    }

    /**
     * 카드/가지급금 관리
     */
    protected function getCardManagement(int $year, int $month): array
    {
        $tenantId = $this->tenantId();

        // 가지급금 (suspense)
        $suspenseTotal = ExpectedExpense::where('tenant_id', $tenantId)
            ->where('transaction_type', 'suspense')
            ->where('payment_status', '!=', 'paid')
            ->sum('amount');

        // 선급금 (advance)
        $advanceTotal = ExpectedExpense::where('tenant_id', $tenantId)
            ->where('transaction_type', 'advance')
            ->where('payment_status', '!=', 'paid')
            ->sum('amount');

        // 이번 달 카드 사용액 (가상 - 실제로는 CardTransaction 등 필요)
        $monthlyCardUsage = ExpectedExpense::where('tenant_id', $tenantId)
            ->whereIn('transaction_type', ['suspense', 'advance'])
            ->whereYear('expected_payment_date', $year)
            ->whereMonth('expected_payment_date', $month)
            ->sum('amount');

        // 미정산 금액
        $unsettledTotal = ExpectedExpense::where('tenant_id', $tenantId)
            ->whereIn('transaction_type', ['suspense', 'advance'])
            ->where('payment_status', 'pending')
            ->sum('amount');

        $cards = [
            ['id' => 'card-1', 'label' => '가지급금 잔액', 'amount' => (float) $suspenseTotal],
            ['id' => 'card-2', 'label' => '선급금 잔액', 'amount' => (float) $advanceTotal],
            ['id' => 'card-3', 'label' => '이번 달 카드 사용액', 'amount' => (float) $monthlyCardUsage],
            ['id' => 'card-4', 'label' => '미정산 금액', 'amount' => (float) $unsettledTotal],
        ];

        $checkPoints = [];
        if ($suspenseTotal > 10000000) {
            $checkPoints[] = [
                'id' => 'card-cp-1',
                'type' => 'warning',
                'message' => '가지급금이 1,000만원을 초과했습니다.',
                'highlight' => '정산이 필요합니다.',
            ];
        }
        if ($unsettledTotal > 0) {
            $checkPoints[] = [
                'id' => 'card-cp-2',
                'type' => 'info',
                'message' => '미정산 금액이 '.number_format($unsettledTotal).'원 있습니다.',
            ];
        }

        return [
            'cards' => $cards,
            'check_points' => $checkPoints,
        ];
    }

    /**
     * 접대비 현황
     */
    protected function getEntertainment(int $year, int $month): array
    {
        $tenantId = $this->tenantId();

        // 실제로는 expense_category 등으로 접대비 분류 필요
        $monthlyTotal = ExpectedExpense::where('tenant_id', $tenantId)
            ->whereYear('expected_payment_date', $year)
            ->whereMonth('expected_payment_date', $month)
            ->where('transaction_type', 'other')
            ->sum('amount');

        $yearlyTotal = ExpectedExpense::where('tenant_id', $tenantId)
            ->whereYear('expected_payment_date', $year)
            ->where('transaction_type', 'other')
            ->sum('amount');

        // 실제 데이터가 없으면 더미 데이터 사용
        $annualLimit = 40000000; // 연간 한도 4,000만원
        $monthlyUsage = $monthlyTotal > 0 ? (float) $monthlyTotal : 2400000; // 이번 달 240만원
        $yearlyUsage = $yearlyTotal > 0 ? (float) $yearlyTotal : 24000000; // 연간 누계 2,400만원
        $remainingLimit = $annualLimit - $yearlyUsage;
        $lastMonthUsage = 1850000; // 전월 185만원 (더미)

        $cards = [
            ['id' => 'ent-1', 'label' => '접대비 한도', 'amount' => (float) $annualLimit, 'sub_amount' => $yearlyUsage, 'sub_label' => '사용'],
            ['id' => 'ent-2', 'label' => '접대비 사용액', 'amount' => $monthlyUsage],
            ['id' => 'ent-3', 'label' => '한도 잔액', 'amount' => $remainingLimit],
            ['id' => 'ent-4', 'label' => '전월 사용액', 'amount' => $lastMonthUsage],
        ];

        $usageRate = ($yearlyUsage / $annualLimit) * 100;
        $checkPoints = [];

        if ($usageRate >= 100) {
            $overAmount = $yearlyUsage - $annualLimit;
            $checkPoints[] = [
                'id' => 'ent-cp-1',
                'type' => 'error',
                'message' => '접대비 한도 초과 '.number_format($overAmount).'원 발생.',
                'highlight' => '손금불산입되어 법인세 부담 증가합니다.',
            ];
        } elseif ($usageRate >= 85) {
            $checkPoints[] = [
                'id' => 'ent-cp-1',
                'type' => 'warning',
                'message' => '접대비 '.round($usageRate).'% 도달. 연내 한도 '.number_format($remainingLimit).'원 잔액입니다.',
                'highlight' => '사용 계획에 집중해 주세요.',
            ];
        } else {
            $checkPoints[] = [
                'id' => 'ent-cp-1',
                'type' => 'success',
                'message' => '접대비 사용 총 '.number_format($yearlyUsage).'원 / 한도 '.number_format($annualLimit).'원 ('.round($usageRate).'%).',
                'highlight' => '여유 있게 운영 중입니다.',
            ];
        }

        return [
            'cards' => $cards,
            'check_points' => $checkPoints,
        ];
    }

    /**
     * 복리후생비 현황
     */
    protected function getWelfare(int $year, int $month): array
    {
        $tenantId = $this->tenantId();

        // 실제로는 expense_category 등으로 복리후생비 분류 필요
        $monthlyTotal = ExpectedExpense::where('tenant_id', $tenantId)
            ->whereYear('expected_payment_date', $year)
            ->whereMonth('expected_payment_date', $month)
            ->whereIn('transaction_type', ['salary', 'insurance'])
            ->sum('amount');

        $salaryTotal = ExpectedExpense::where('tenant_id', $tenantId)
            ->whereYear('expected_payment_date', $year)
            ->whereMonth('expected_payment_date', $month)
            ->where('transaction_type', 'salary')
            ->sum('amount');

        $insuranceTotal = ExpectedExpense::where('tenant_id', $tenantId)
            ->whereYear('expected_payment_date', $year)
            ->whereMonth('expected_payment_date', $month)
            ->where('transaction_type', 'insurance')
            ->sum('amount');

        $yearlyTotal = ExpectedExpense::where('tenant_id', $tenantId)
            ->whereYear('expected_payment_date', $year)
            ->whereIn('transaction_type', ['salary', 'insurance'])
            ->sum('amount');

        // 실제 데이터가 없으면 더미 데이터 사용
        $hasData = $monthlyTotal > 0 || $yearlyTotal > 0;
        $employeeCount = 15; // 직원 수 (더미)
        $perPersonLimit = 200000; // 1인당 월 20만원 한도

        $totalLimit = $employeeCount * $perPersonLimit; // 총 한도 300만원
        $monthlyWelfare = $hasData ? (float) $monthlyTotal : 2700000; // 이번 달 270만원
        $yearlyWelfare = $hasData ? (float) $yearlyTotal : 32400000; // 연간 누계 3,240만원
        $perPersonMonthly = $monthlyWelfare / $employeeCount; // 1인당 18만원

        $cards = [
            ['id' => 'wf-1', 'label' => '총 복리후생비 한도', 'amount' => (float) $totalLimit],
            ['id' => 'wf-2', 'label' => '누적 복리후생비 사용', 'amount' => $yearlyWelfare],
            ['id' => 'wf-3', 'label' => '이번 달 복리후생비', 'amount' => $monthlyWelfare],
            ['id' => 'wf-4', 'label' => '1인당 월 복리후생비', 'amount' => $perPersonMonthly],
        ];

        $checkPoints = [];

        // 1인당 복리후생비 기준 체크
        if ($perPersonMonthly >= 150000 && $perPersonMonthly <= 250000) {
            $checkPoints[] = [
                'id' => 'wf-cp-1',
                'type' => 'success',
                'message' => '1인당 월 복리후생비 '.number_format($perPersonMonthly).'원. 업계 평균(15~25만원) 내',
                'highlight' => '정상 운영 중입니다.',
            ];
        } elseif ($perPersonMonthly > 250000) {
            $checkPoints[] = [
                'id' => 'wf-cp-1',
                'type' => 'warning',
                'message' => '1인당 월 복리후생비가 '.number_format($perPersonMonthly).'원으로',
                'highlight' => '업계 평균(15~25만원)을 초과했습니다.',
            ];
        } else {
            $checkPoints[] = [
                'id' => 'wf-cp-1',
                'type' => 'info',
                'message' => '1인당 월 복리후생비가 '.number_format($perPersonMonthly).'원으로',
                'highlight' => '업계 평균보다 낮습니다.',
            ];
        }

        // 식대 비과세 한도 체크 (더미 경고)
        $mealAllowance = 250000; // 식대 25만원 (더미)
        if ($mealAllowance > 200000) {
            $checkPoints[] = [
                'id' => 'wf-cp-2',
                'type' => 'warning',
                'message' => '식대가 월 '.number_format($mealAllowance).'원으로',
                'highlight' => '비과세 한도(20만원)를 초과했습니다. 초과분은 근로소득 과세됩니다.',
            ];
        }

        return [
            'cards' => $cards,
            'check_points' => $checkPoints,
        ];
    }

    /**
     * 미수금 현황
     */
    protected function getReceivable(int $year, int $month): array
    {
        $tenantId = $this->tenantId();

        // 총 미수금 (거래처별)
        $totalReceivable = Client::where('tenant_id', $tenantId)
            ->where('is_active', true)
            ->sum('outstanding_balance');

        // 이번 달 입금
        $monthlyDeposit = Deposit::where('tenant_id', $tenantId)
            ->whereYear('deposit_date', $year)
            ->whereMonth('deposit_date', $month)
            ->sum('amount');

        // 오늘 입금
        $todayDeposit = Deposit::where('tenant_id', $tenantId)
            ->whereDate('deposit_date', Carbon::today())
            ->sum('amount');

        // 연체 미수금 (credit_limit 초과 거래처)
        $overdueReceivable = Client::where('tenant_id', $tenantId)
            ->where('is_active', true)
            ->whereColumn('outstanding_balance', '>', 'credit_limit')
            ->sum('outstanding_balance');

        $cards = [
            [
                'id' => 'rcv-1',
                'label' => '총 미수금',
                'amount' => (float) $totalReceivable,
                'sub_amount' => (float) $overdueReceivable,
                'sub_label' => '한도초과',
            ],
            [
                'id' => 'rcv-2',
                'label' => '이번 달 입금',
                'amount' => (float) $monthlyDeposit,
            ],
            [
                'id' => 'rcv-3',
                'label' => '오늘 입금',
                'amount' => (float) $todayDeposit,
            ],
            [
                'id' => 'rcv-4',
                'label' => '연체 미수금',
                'amount' => (float) $overdueReceivable,
            ],
        ];

        $checkPoints = [];

        // 한도 초과 거래처
        $overdueClients = Client::where('tenant_id', $tenantId)
            ->where('is_active', true)
            ->whereColumn('outstanding_balance', '>', 'credit_limit')
            ->select('name', 'outstanding_balance')
            ->limit(3)
            ->get();

        foreach ($overdueClients as $client) {
            $checkPoints[] = [
                'id' => 'rcv-cp-'.($client->id ?? uniqid()),
                'type' => 'error',
                'message' => $client->name.'의 미수금이 한도를 초과했습니다.',
                'highlight' => '거래 주의가 필요합니다.',
            ];
        }

        return [
            'cards' => $cards,
            'check_points' => $checkPoints,
            'has_detail_button' => true,
            'detail_button_label' => '거래처별 미수금 현황',
            'detail_button_path' => '/accounting/receivables-status',
        ];
    }

    /**
     * 채권추심 현황
     */
    protected function getDebtCollection(): array
    {
        $tenantId = $this->tenantId();

        // 추심중 건수 및 금액
        $collectingData = BadDebt::where('tenant_id', $tenantId)
            ->collecting()
            ->selectRaw('COUNT(*) as count, SUM(debt_amount) as total')
            ->first();

        // 법적조치 건수 및 금액
        $legalData = BadDebt::where('tenant_id', $tenantId)
            ->legalAction()
            ->selectRaw('COUNT(*) as count, SUM(debt_amount) as total')
            ->first();

        // 회수완료 금액 (이번 년도)
        $recoveredTotal = BadDebt::where('tenant_id', $tenantId)
            ->recovered()
            ->whereYear('closed_at', Carbon::now()->year)
            ->sum('debt_amount');

        // 대손처리 금액
        $badDebtTotal = BadDebt::where('tenant_id', $tenantId)
            ->badDebt()
            ->sum('debt_amount');

        $cards = [
            ['id' => 'debt-1', 'label' => '추심중', 'amount' => (float) ($collectingData->total ?? 0)],
            ['id' => 'debt-2', 'label' => '법적조치 진행', 'amount' => (float) ($legalData->total ?? 0)],
            ['id' => 'debt-3', 'label' => '올해 회수 완료', 'amount' => (float) $recoveredTotal],
            ['id' => 'debt-4', 'label' => '대손처리 금액', 'amount' => (float) $badDebtTotal],
        ];

        $checkPoints = [];
        $collectingCount = $collectingData->count ?? 0;
        $legalCount = $legalData->count ?? 0;

        if ($collectingCount > 0) {
            $checkPoints[] = [
                'id' => 'debt-cp-1',
                'type' => 'info',
                'message' => '현재 추심 진행 중인 건이 '.$collectingCount.'건 있습니다.',
            ];
        }
        if ($legalCount > 0) {
            $checkPoints[] = [
                'id' => 'debt-cp-2',
                'type' => 'warning',
                'message' => '법적조치 진행 중인 건이 '.$legalCount.'건 있습니다.',
            ];
        }

        return [
            'cards' => $cards,
            'check_points' => $checkPoints,
        ];
    }
}
