<?php

namespace App\Services;

use Carbon\Carbon;
use Illuminate\Support\Facades\DB;

/**
 * 복리후생비 현황 서비스 (D1.7 리스크 감지형)
 *
 * CEO 대시보드용 복리후생비 리스크 데이터를 제공합니다.
 * 카드 4개: 비과세 한도 초과, 사적 사용 의심, 특정인 편중, 항목별 한도 초과
 */
class WelfareService extends Service
{
    // 비과세 식대 한도 (월)
    private const TAX_FREE_MEAL_LIMIT = 200000;

    // 1인당 월 복리후생비 업계 평균 범위
    private const INDUSTRY_AVG_MIN = 150000;

    private const INDUSTRY_AVG_MAX = 250000;

    // 특정인 편중 기준 (전체 대비 5% 초과)
    private const CONCENTRATION_THRESHOLD = 0.05;

    // 항목별 1인당 월 기준 금액
    private const SUB_TYPE_LIMITS = [
        'meal' => 200000,          // 식대 20만원
        'transportation' => 100000, // 교통비 10만원
        'congratulation' => 50000,  // 경조사 5만원
        'health_check' => 30000,    // 건강검진 3만원
        'education' => 80000,       // 교육비 8만원
        'welfare_point' => 100000,  // 복지포인트 10만원
    ];

    /**
     * 복리후생비 리스크 현황 요약 조회 (D1.7)
     *
     * @return array{cards: array, check_points: array}
     */
    public function getSummary(
        ?string $limitType = 'quarterly',
        ?string $calculationType = 'fixed',
        ?int $fixedAmountPerMonth = 200000,
        ?float $ratio = 0.05,
        ?int $year = null,
        ?int $quarter = null
    ): array {
        $tenantId = $this->tenantId();
        $now = Carbon::now();

        $year = $year ?? $now->year;
        $quarter = $quarter ?? $now->quarter;

        // 기간 범위 계산
        if ($limitType === 'annual') {
            $startDate = Carbon::create($year, 1, 1)->format('Y-m-d');
            $endDate = Carbon::create($year, 12, 31)->format('Y-m-d');
            $monthCount = 12;
        } else {
            $startDate = Carbon::create($year, ($quarter - 1) * 3 + 1, 1)->format('Y-m-d');
            $endDate = Carbon::create($year, $quarter * 3, 1)->endOfMonth()->format('Y-m-d');
            $monthCount = 3;
        }

        // 직원 수 조회
        $employeeCount = $this->getEmployeeCount($tenantId);

        // 리스크 감지 쿼리
        $taxFreeExcess = $this->getTaxFreeExcessRisk($tenantId, $startDate, $endDate, $employeeCount, $monthCount);
        $privateUse = $this->getPrivateUseRisk($tenantId, $startDate, $endDate);
        $concentration = $this->getConcentrationRisk($tenantId, $startDate, $endDate);
        $categoryExcess = $this->getCategoryExcessRisk($tenantId, $startDate, $endDate, $employeeCount, $monthCount);

        // 카드 데이터 구성
        $cards = [
            [
                'id' => 'wf_tax_excess',
                'label' => '비과세 한도 초과',
                'amount' => (int) $taxFreeExcess['total'],
                'subLabel' => "{$taxFreeExcess['count']}건",
            ],
            [
                'id' => 'wf_private_use',
                'label' => '사적 사용 의심',
                'amount' => (int) $privateUse['total'],
                'subLabel' => "{$privateUse['count']}건",
            ],
            [
                'id' => 'wf_concentration',
                'label' => '특정인 편중',
                'amount' => (int) $concentration['total'],
                'subLabel' => "{$concentration['count']}건",
            ],
            [
                'id' => 'wf_category_excess',
                'label' => '항목별 한도 초과',
                'amount' => (int) $categoryExcess['total'],
                'subLabel' => "{$categoryExcess['count']}건",
            ],
        ];

        // 체크포인트 생성
        $checkPoints = $this->generateRiskCheckPoints(
            $tenantId,
            $employeeCount,
            $monthCount,
            $startDate,
            $endDate,
            $taxFreeExcess,
            $privateUse,
            $concentration,
            $categoryExcess
        );

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

    /**
     * 비과세 한도 초과 리스크 조회
     * sub_type='meal' 1인당 월 > 200,000원
     */
    private function getTaxFreeExcessRisk(int $tenantId, string $startDate, string $endDate, int $employeeCount, int $monthCount): array
    {
        if ($employeeCount <= 0) {
            return ['count' => 0, 'total' => 0];
        }

        // 식대 총액 조회
        $mealTotal = DB::table('expense_accounts')
            ->where('tenant_id', $tenantId)
            ->where('account_type', 'welfare')
            ->where('sub_type', 'meal')
            ->whereBetween('expense_date', [$startDate, $endDate])
            ->whereNull('deleted_at')
            ->sum('amount');

        $perPersonMonthly = $mealTotal / $employeeCount / max(1, $monthCount);
        $excessAmount = max(0, $perPersonMonthly - self::TAX_FREE_MEAL_LIMIT) * $employeeCount * $monthCount;

        if ($excessAmount > 0) {
            // 초과 건수 (식대 건수 기준)
            $count = DB::table('expense_accounts')
                ->where('tenant_id', $tenantId)
                ->where('account_type', 'welfare')
                ->where('sub_type', 'meal')
                ->whereBetween('expense_date', [$startDate, $endDate])
                ->whereNull('deleted_at')
                ->count();

            return ['count' => $count, 'total' => (int) $excessAmount];
        }

        return ['count' => 0, 'total' => 0];
    }

    /**
     * 사적 사용 의심 리스크 조회
     * 주말/심야 사용 (접대비와 동일 로직, account_type='welfare')
     */
    private function getPrivateUseRisk(int $tenantId, string $startDate, string $endDate): array
    {
        // 주말 사용
        $weekendResult = DB::table('expense_accounts')
            ->where('tenant_id', $tenantId)
            ->where('account_type', 'welfare')
            ->whereBetween('expense_date', [$startDate, $endDate])
            ->whereNull('deleted_at')
            ->whereRaw('DAYOFWEEK(expense_date) IN (1, 7)')
            ->selectRaw('COUNT(*) as count, COALESCE(SUM(amount), 0) as total')
            ->first();

        // 심야 사용 (barobill 조인)
        $lateNightResult = DB::table('expense_accounts as ea')
            ->leftJoin('barobill_card_transactions as bct', function ($join) {
                $join->on('ea.receipt_no', '=', 'bct.approval_num')
                    ->on('ea.tenant_id', '=', 'bct.tenant_id');
            })
            ->where('ea.tenant_id', $tenantId)
            ->where('ea.account_type', 'welfare')
            ->whereBetween('ea.expense_date', [$startDate, $endDate])
            ->whereNull('ea.deleted_at')
            ->whereRaw('DAYOFWEEK(ea.expense_date) NOT IN (1, 7)')
            ->whereNotNull('bct.use_time')
            ->where(function ($q) {
                $q->whereRaw('CAST(SUBSTRING(bct.use_time, 1, 2) AS UNSIGNED) >= 22')
                    ->orWhereRaw('CAST(SUBSTRING(bct.use_time, 1, 2) AS UNSIGNED) < 6');
            })
            ->selectRaw('COUNT(*) as count, COALESCE(SUM(ea.amount), 0) as total')
            ->first();

        return [
            'count' => ($weekendResult->count ?? 0) + ($lateNightResult->count ?? 0),
            'total' => ($weekendResult->total ?? 0) + ($lateNightResult->total ?? 0),
        ];
    }

    /**
     * 특정인 편중 리스크 조회
     * 1인 사용비율 > 전체의 5%
     */
    private function getConcentrationRisk(int $tenantId, string $startDate, string $endDate): array
    {
        // 전체 복리후생비 사용액
        $totalAmount = DB::table('expense_accounts')
            ->where('tenant_id', $tenantId)
            ->where('account_type', 'welfare')
            ->whereBetween('expense_date', [$startDate, $endDate])
            ->whereNull('deleted_at')
            ->sum('amount');

        if ($totalAmount <= 0) {
            return ['count' => 0, 'total' => 0];
        }

        $threshold = $totalAmount * self::CONCENTRATION_THRESHOLD;

        // 사용자별 사용액 조회 (편중된 사용자)
        $concentrated = DB::table('expense_accounts')
            ->where('tenant_id', $tenantId)
            ->where('account_type', 'welfare')
            ->whereBetween('expense_date', [$startDate, $endDate])
            ->whereNull('deleted_at')
            ->groupBy('created_by')
            ->havingRaw('SUM(amount) > ?', [$threshold])
            ->selectRaw('COUNT(*) as count, SUM(amount) as total')
            ->get();

        $totalConcentrated = $concentrated->sum('total');
        $userCount = $concentrated->count();

        return ['count' => $userCount, 'total' => (int) $totalConcentrated];
    }

    /**
     * 항목별 한도 초과 리스크 조회
     * 각 sub_type별 1인당 월 기준금액 초과
     */
    private function getCategoryExcessRisk(int $tenantId, string $startDate, string $endDate, int $employeeCount, int $monthCount): array
    {
        if ($employeeCount <= 0) {
            return ['count' => 0, 'total' => 0];
        }

        $totalExcess = 0;
        $excessCount = 0;

        foreach (self::SUB_TYPE_LIMITS as $subType => $monthlyLimit) {
            $amount = DB::table('expense_accounts')
                ->where('tenant_id', $tenantId)
                ->where('account_type', 'welfare')
                ->where('sub_type', $subType)
                ->whereBetween('expense_date', [$startDate, $endDate])
                ->whereNull('deleted_at')
                ->sum('amount');

            $perPersonMonthly = $amount / $employeeCount / max(1, $monthCount);
            if ($perPersonMonthly > $monthlyLimit) {
                $excess = ($perPersonMonthly - $monthlyLimit) * $employeeCount * $monthCount;
                $totalExcess += $excess;
                $excessCount++;
            }
        }

        return ['count' => $excessCount, 'total' => (int) $totalExcess];
    }

    /**
     * 리스크 감지 체크포인트 생성
     */
    private function generateRiskCheckPoints(
        int $tenantId,
        int $employeeCount,
        int $monthCount,
        string $startDate,
        string $endDate,
        array $taxFreeExcess,
        array $privateUse,
        array $concentration,
        array $categoryExcess
    ): array {
        $checkPoints = [];

        // 1인당 월 복리후생비 계산 (업계 평균 비교)
        $usedAmount = $this->getUsedAmount($tenantId, $startDate, $endDate);
        $perPersonMonthly = $employeeCount > 0 && $monthCount > 0
            ? $usedAmount / $employeeCount / $monthCount
            : 0;
        $perPersonFormatted = number_format($perPersonMonthly / 10000);

        if ($perPersonMonthly >= self::INDUSTRY_AVG_MIN && $perPersonMonthly <= self::INDUSTRY_AVG_MAX) {
            $checkPoints[] = [
                'id' => 'wf_cp_avg',
                'type' => 'success',
                'message' => "1인당 월 복리후생비 {$perPersonFormatted}만원. 업계 평균(15~25만원) 내 정상 운영 중입니다.",
                'highlights' => [
                    ['text' => "{$perPersonFormatted}만원", 'color' => 'green'],
                ],
            ];
        } elseif ($perPersonMonthly > self::INDUSTRY_AVG_MAX) {
            $checkPoints[] = [
                'id' => 'wf_cp_avg_high',
                'type' => 'warning',
                'message' => "1인당 월 복리후생비 {$perPersonFormatted}만원. 업계 평균(15~25만원) 대비 높습니다.",
                'highlights' => [
                    ['text' => "{$perPersonFormatted}만원", 'color' => 'orange'],
                ],
            ];
        }

        // 식대 비과세 한도 체크
        $mealAmount = $this->getMonthlyMealAmount($tenantId, $startDate, $endDate);
        $perPersonMeal = $employeeCount > 0 && $monthCount > 0
            ? $mealAmount / $employeeCount / $monthCount
            : 0;

        if ($perPersonMeal > self::TAX_FREE_MEAL_LIMIT) {
            $mealFormatted = number_format($perPersonMeal / 10000);
            $limitFormatted = number_format(self::TAX_FREE_MEAL_LIMIT / 10000);
            $checkPoints[] = [
                'id' => 'wf_cp_meal',
                'type' => 'error',
                'message' => "식대가 월 {$mealFormatted}만원으로 비과세 한도({$limitFormatted}만원)를 초과했습니다. 초과분은 근로소득 과세됩니다.",
                'highlights' => [
                    ['text' => "월 {$mealFormatted}만원", 'color' => 'red'],
                    ['text' => '초과', 'color' => 'red'],
                ],
            ];
        }

        // 사적 사용 의심
        if ($privateUse['count'] > 0) {
            $amountFormatted = number_format($privateUse['total'] / 10000);
            $checkPoints[] = [
                'id' => 'wf_cp_private',
                'type' => 'warning',
                'message' => "주말/심야 사용 {$privateUse['count']}건({$amountFormatted}만원) 감지. 사적 사용 여부를 확인해주세요.",
                'highlights' => [
                    ['text' => "{$privateUse['count']}건({$amountFormatted}만원)", 'color' => 'red'],
                ],
            ];
        }

        // 특정인 편중
        if ($concentration['count'] > 0) {
            $amountFormatted = number_format($concentration['total'] / 10000);
            $checkPoints[] = [
                'id' => 'wf_cp_concentration',
                'type' => 'warning',
                'message' => "특정인 편중 {$concentration['count']}명({$amountFormatted}만원). 전체의 5% 초과 사용자가 있습니다.",
                'highlights' => [
                    ['text' => "{$concentration['count']}명({$amountFormatted}만원)", 'color' => 'orange'],
                ],
            ];
        }

        // 리스크 0건이면 정상
        $totalRisk = $taxFreeExcess['count'] + $privateUse['count'] + $concentration['count'] + $categoryExcess['count'];
        if ($totalRisk === 0 && empty($checkPoints)) {
            $checkPoints[] = [
                'id' => 'wf_cp_normal',
                'type' => 'success',
                'message' => '복리후생비 사용 현황이 정상입니다.',
                'highlights' => [
                    ['text' => '정상', 'color' => 'green'],
                ],
            ];
        }

        return $checkPoints;
    }

    /**
     * 직원 수 조회 (급여 대상 직원 기준)
     *
     * salaries 테이블에서 유니크한 employee_id 수를 카운트합니다.
     * 급여 데이터가 없으면 user_tenants 테이블에서 조회합니다.
     */
    private function getEmployeeCount(int $tenantId): int
    {
        // 1차: salaries 테이블에서 급여 대상 직원 수 조회
        $count = DB::table('salaries')
            ->where('tenant_id', $tenantId)
            ->whereNull('deleted_at')
            ->distinct('employee_id')
            ->count('employee_id');

        if ($count > 0) {
            return $count;
        }

        // 2차: salaries 데이터가 없으면 user_tenants에서 조회
        $count = DB::table('users')
            ->join('user_tenants', 'users.id', '=', 'user_tenants.user_id')
            ->where('user_tenants.tenant_id', $tenantId)
            ->where('user_tenants.is_active', true)
            ->whereNull('users.deleted_at')
            ->count();

        return $count ?: 0;
    }

    /**
     * 연간 급여 총액 조회
     *
     * salaries 테이블에서 해당 연도의 base_salary 합계를 조회합니다.
     * 연간 데이터가 부족한 경우, 최근 월 데이터를 12배하여 추정합니다.
     */
    private function getTotalSalary(int $tenantId, int $year): float
    {
        // 해당 연도의 급여 합계 조회
        $yearlyTotal = DB::table('salaries')
            ->where('tenant_id', $tenantId)
            ->where('year', $year)
            ->whereNull('deleted_at')
            ->sum('base_salary');

        if ($yearlyTotal > 0) {
            // 데이터가 있는 월 수 확인
            $monthCount = DB::table('salaries')
                ->where('tenant_id', $tenantId)
                ->where('year', $year)
                ->whereNull('deleted_at')
                ->distinct('month')
                ->count('month');

            // 연간 추정 (데이터가 일부 월만 있을 경우 12개월로 환산)
            if ($monthCount > 0 && $monthCount < 12) {
                return ($yearlyTotal / $monthCount) * 12;
            }

            return $yearlyTotal;
        }

        // 해당 연도 데이터가 없으면 최근 월 데이터로 추정
        $latestMonth = DB::table('salaries')
            ->where('tenant_id', $tenantId)
            ->whereNull('deleted_at')
            ->sum('base_salary');

        $employeeCount = $this->getEmployeeCount($tenantId);
        if ($latestMonth > 0 && $employeeCount > 0) {
            // 최근 월 급여를 12배하여 연간 추정
            return ($latestMonth / $employeeCount) * $employeeCount * 12;
        }

        return 0;
    }

    /**
     * 복리후생비 사용액 조회
     *
     * expense_accounts 테이블에서 welfare 타입 지출액을 조회합니다.
     * 데이터가 없으면 0을 반환합니다.
     */
    private function getUsedAmount(int $tenantId, string $startDate, string $endDate): float
    {
        return DB::table('expense_accounts')
            ->where('tenant_id', $tenantId)
            ->where('account_type', 'welfare')
            ->whereBetween('expense_date', [$startDate, $endDate])
            ->whereNull('deleted_at')
            ->sum('amount') ?: 0;
    }

    /**
     * 월 식대 조회
     */
    private function getMonthlyMealAmount(int $tenantId, string $startDate, string $endDate): float
    {
        // TODO: 식대 항목 조회
        $amount = DB::table('expense_accounts')
            ->where('tenant_id', $tenantId)
            ->where('account_type', 'welfare')
            ->where('sub_type', 'meal')
            ->whereBetween('expense_date', [$startDate, $endDate])
            ->whereNull('deleted_at')
            ->sum('amount');

        return $amount ?: 0;
    }

    /**
     * 복리후생비 상세 정보 조회 (모달용)
     *
     * @param  string|null  $calculationType  계산 방식 (fixed|ratio, 기본: fixed)
     * @param  int|null  $fixedAmountPerMonth  1인당 월 정액 (기본: 200000)
     * @param  float|null  $ratio  급여 대비 비율 (기본: 0.05)
     * @param  int|null  $year  연도 (기본: 현재 연도)
     * @param  int|null  $quarter  분기 (1-4, 기본: 현재 분기)
     */
    public function getDetail(
        ?string $calculationType = 'fixed',
        ?int $fixedAmountPerMonth = 200000,
        ?float $ratio = 0.05,
        ?int $year = null,
        ?int $quarter = null
    ): array {
        $tenantId = $this->tenantId();
        $now = Carbon::now();

        // 기본값 설정
        $year = $year ?? $now->year;
        $calculationType = $calculationType ?? 'fixed';
        $fixedAmountPerMonth = $fixedAmountPerMonth ?? 200000;
        $ratio = $ratio ?? 0.05;
        $quarter = $quarter ?? $now->quarter;

        // 연간 기간 범위
        $annualStartDate = Carbon::create($year, 1, 1)->format('Y-m-d');
        $annualEndDate = Carbon::create($year, 12, 31)->format('Y-m-d');

        // 분기 기간 범위
        $quarterStartDate = Carbon::create($year, ($quarter - 1) * 3 + 1, 1)->format('Y-m-d');
        $quarterEndDate = Carbon::create($year, $quarter * 3, 1)->endOfMonth()->format('Y-m-d');

        // 직원 수 조회
        $employeeCount = $this->getEmployeeCount($tenantId);

        // 한도 계산
        if ($calculationType === 'fixed') {
            $annualLimit = $fixedAmountPerMonth * 12 * $employeeCount;
            $totalSalary = 0;
        } else {
            $totalSalary = $this->getTotalSalary($tenantId, $year);
            $annualLimit = $totalSalary * $ratio;
        }

        $quarterlyLimit = $annualLimit / 4;

        // 연간/분기 사용액 조회
        $annualUsed = $this->getUsedAmount($tenantId, $annualStartDate, $annualEndDate);
        $quarterlyUsed = $this->getUsedAmount($tenantId, $quarterStartDate, $quarterEndDate);

        // 복리후생비 계정 (연간)
        $annualAccount = $this->getAccountBalance($tenantId, $year);

        // 잔여/초과 계산
        $annualRemaining = max(0, $annualLimit - $annualUsed);
        $quarterlyRemaining = max(0, $quarterlyLimit - $quarterlyUsed);
        $quarterlyExceeded = max(0, $quarterlyUsed - $quarterlyLimit);

        // 1. 요약 데이터
        $summary = [
            'annual_account' => (int) $annualAccount,
            'annual_limit' => (int) $annualLimit,
            'annual_used' => (int) $annualUsed,
            'annual_remaining' => (int) $annualRemaining,
            'quarterly_limit' => (int) $quarterlyLimit,
            'quarterly_remaining' => (int) $quarterlyRemaining,
            'quarterly_used' => (int) $quarterlyUsed,
            'quarterly_exceeded' => (int) $quarterlyExceeded,
        ];

        // 2. 월별 사용 추이
        $monthlyUsage = $this->getMonthlyUsageTrend($tenantId, $year);

        // 3. 항목별 분포
        $categoryDistribution = $this->getCategoryDistribution($tenantId, $annualStartDate, $annualEndDate);

        // 4. 일별 사용 내역
        $transactions = $this->getTransactions($tenantId, $quarterStartDate, $quarterEndDate);

        // 5. 계산 정보
        $calculation = [
            'type' => $calculationType,
            'employee_count' => $employeeCount,
            'annual_limit' => (int) $annualLimit,
        ];

        if ($calculationType === 'fixed') {
            $calculation['monthly_amount'] = $fixedAmountPerMonth;
        } else {
            $calculation['total_salary'] = (int) $totalSalary;
            $calculation['ratio'] = $ratio * 100; // 백분율로 변환
        }

        // 6. 분기별 현황
        $quarterly = $this->getQuarterlyStatus($tenantId, $year, $quarterlyLimit);

        return [
            'summary' => $summary,
            'monthly_usage' => $monthlyUsage,
            'category_distribution' => $categoryDistribution,
            'transactions' => $transactions,
            'calculation' => $calculation,
            'quarterly' => $quarterly,
        ];
    }

    /**
     * 복리후생비 계정 잔액 조회
     *
     * 해당 연도의 복리후생비 계정 지출액을 조회합니다.
     * 데이터가 없으면 0을 반환합니다.
     */
    private function getAccountBalance(int $tenantId, int $year): float
    {
        return DB::table('expense_accounts')
            ->where('tenant_id', $tenantId)
            ->where('account_type', 'welfare')
            ->whereYear('expense_date', $year)
            ->whereNull('deleted_at')
            ->sum('amount') ?: 0;
    }

    /**
     * 월별 사용 추이 조회
     */
    private function getMonthlyUsageTrend(int $tenantId, int $year): array
    {
        $monthlyData = DB::table('expense_accounts')
            ->select(DB::raw('MONTH(expense_date) as month'), DB::raw('SUM(amount) as amount'))
            ->where('tenant_id', $tenantId)
            ->where('account_type', 'welfare')
            ->whereYear('expense_date', $year)
            ->whereNull('deleted_at')
            ->groupBy(DB::raw('MONTH(expense_date)'))
            ->orderBy('month')
            ->get();

        // 12개월 모두 포함 (데이터 없는 달은 0)
        $result = [];
        for ($i = 1; $i <= 12; $i++) {
            $found = $monthlyData->firstWhere('month', $i);
            $result[] = [
                'month' => $i,
                'amount' => $found ? (int) $found->amount : 0,
            ];
        }

        return $result;
    }

    /**
     * 항목별 분포 조회
     */
    private function getCategoryDistribution(int $tenantId, string $startDate, string $endDate): array
    {
        $categoryLabels = [
            'meal' => '식비',
            'health_check' => '건강검진',
            'congratulation' => '경조사비',
            'other' => '기타',
        ];

        $distribution = DB::table('expense_accounts')
            ->select('sub_type', DB::raw('SUM(amount) as amount'))
            ->where('tenant_id', $tenantId)
            ->where('account_type', 'welfare')
            ->whereBetween('expense_date', [$startDate, $endDate])
            ->whereNull('deleted_at')
            ->groupBy('sub_type')
            ->get();

        $total = $distribution->sum('amount');

        $result = [];
        foreach ($distribution as $item) {
            $subType = $item->sub_type ?? 'other';
            $result[] = [
                'category' => $subType,
                'label' => $categoryLabels[$subType] ?? '기타',
                'amount' => (int) $item->amount,
                'ratio' => $total > 0 ? round(($item->amount / $total) * 100, 1) : 0,
            ];
        }

        // 데이터가 없는 경우 빈 배열 반환 (mock 데이터 제거)
        return $result;
    }

    /**
     * 일별 사용 내역 조회
     */
    private function getTransactions(int $tenantId, string $startDate, string $endDate): array
    {
        $categoryLabels = [
            'meal' => '식비',
            'health_check' => '건강검진',
            'congratulation' => '경조사비',
            'other' => '기타',
        ];

        $transactions = DB::table('expense_accounts as ea')
            ->leftJoin('users as u', 'ea.created_by', '=', 'u.id')
            ->select([
                'ea.id',
                'ea.card_no',
                'u.name as user_name',
                'ea.expense_date',
                'ea.vendor_name',
                'ea.amount',
                'ea.sub_type',
            ])
            ->where('ea.tenant_id', $tenantId)
            ->where('ea.account_type', 'welfare')
            ->whereBetween('ea.expense_date', [$startDate, $endDate])
            ->whereNull('ea.deleted_at')
            ->orderByDesc('ea.expense_date')
            ->limit(100)
            ->get();

        $result = [];
        foreach ($transactions as $t) {
            $subType = $t->sub_type ?? 'other';
            $result[] = [
                'id' => $t->id,
                'card_name' => $t->card_no ? '카드 *'.substr($t->card_no, -4) : '카드명',
                'user_name' => $t->user_name ?? '사용자',
                'expense_date' => Carbon::parse($t->expense_date)->format('Y-m-d H:i'),
                'vendor_name' => $t->vendor_name ?? '가맹점명',
                'amount' => (int) $t->amount,
                'sub_type' => $subType,
                'sub_type_label' => $categoryLabels[$subType] ?? '기타',
            ];
        }

        // 데이터가 없는 경우 빈 배열 반환 (mock 데이터 제거)
        return $result;
    }

    /**
     * 분기별 현황 조회
     */
    private function getQuarterlyStatus(int $tenantId, int $year, float $quarterlyLimit): array
    {
        $result = [];
        $previousRemaining = 0;

        for ($q = 1; $q <= 4; $q++) {
            $startDate = Carbon::create($year, ($q - 1) * 3 + 1, 1)->format('Y-m-d');
            $endDate = Carbon::create($year, $q * 3, 1)->endOfMonth()->format('Y-m-d');

            $used = $this->getUsedAmount($tenantId, $startDate, $endDate);
            $carryover = $previousRemaining > 0 ? $previousRemaining : 0;
            $totalLimit = $quarterlyLimit + $carryover;
            $remaining = max(0, $totalLimit - $used);
            $exceeded = max(0, $used - $totalLimit);

            $result[] = [
                'quarter' => $q,
                'limit' => (int) $quarterlyLimit,
                'carryover' => (int) $carryover,
                'used' => (int) $used,
                'remaining' => (int) $remaining,
                'exceeded' => (int) $exceeded,
            ];

            $previousRemaining = $remaining;
        }

        return $result;
    }

}
