<?php

namespace App\Services;

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

/**
 * 복리후생비 현황 서비스
 *
 * CEO 대시보드용 복리후생비 데이터를 제공합니다.
 */
class WelfareService extends Service
{
    // 비과세 식대 한도 (월)
    private const TAX_FREE_MEAL_LIMIT = 200000;

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

    /**
     * 복리후생비 현황 요약 조회
     *
     * @param  string|null  $limitType  기간 타입 (annual|quarterly, 기본: quarterly)
     * @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, 기본: 현재 분기)
     * @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;
        $limitType = $limitType ?? 'quarterly';
        $calculationType = $calculationType ?? 'fixed';
        $fixedAmountPerMonth = $fixedAmountPerMonth ?? 200000;
        $ratio = $ratio ?? 0.05;
        $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');
            $periodLabel = "{$year}년";
            $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');
            $periodLabel = "{$quarter}사분기";
            $monthCount = 3;
        }

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

        // 한도 계산
        if ($calculationType === 'fixed') {
            $annualLimit = $fixedAmountPerMonth * 12 * $employeeCount;
        } else {
            // 급여 총액 기반 비율 계산
            $totalSalary = $this->getTotalSalary($tenantId, $year);
            $annualLimit = $totalSalary * $ratio;
        }

        $periodLimit = $limitType === 'annual' ? $annualLimit : ($annualLimit / 4);

        // 복리후생비 사용액 조회
        $usedAmount = $this->getUsedAmount($tenantId, $startDate, $endDate);

        // 잔여 한도
        $remainingLimit = max(0, $periodLimit - $usedAmount);

        // 카드 데이터 구성
        $cards = [
            [
                'id' => 'wf_annual_limit',
                'label' => '당해년도 복리후생비 한도',
                'amount' => (int) $annualLimit,
            ],
            [
                'id' => 'wf_period_limit',
                'label' => "{{$periodLabel}} 복리후생비 총 한도",
                'amount' => (int) $periodLimit,
            ],
            [
                'id' => 'wf_remaining',
                'label' => "{{$periodLabel}} 복리후생비 잔여한도",
                'amount' => (int) $remainingLimit,
            ],
            [
                'id' => 'wf_used',
                'label' => "{{$periodLabel}} 복리후생비 사용금액",
                'amount' => (int) $usedAmount,
            ],
        ];

        // 체크포인트 생성
        $checkPoints = $this->generateCheckPoints(
            $tenantId,
            $employeeCount,
            $usedAmount,
            $monthCount,
            $startDate,
            $endDate
        );

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

    /**
     * 직원 수 조회
     */
    private function getEmployeeCount(int $tenantId): int
    {
        $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 ?: 50; // 임시 기본값
    }

    /**
     * 연간 급여 총액 조회
     */
    private function getTotalSalary(int $tenantId, int $year): float
    {
        // TODO: 실제 급여 테이블에서 조회
        // payroll 또는 salary_histories에서 연간 급여 합계
        return 2000000000; // 임시 기본값 (20억)
    }

    /**
     * 복리후생비 사용액 조회
     */
    private function getUsedAmount(int $tenantId, string $startDate, string $endDate): float
    {
        // TODO: 실제 복리후생비 계정과목에서 조회
        $amount = DB::table('expense_accounts')
            ->where('tenant_id', $tenantId)
            ->where('account_type', 'welfare')
            ->whereBetween('expense_date', [$startDate, $endDate])
            ->whereNull('deleted_at')
            ->sum('amount');

        return $amount ?: 5123000; // 임시 기본값
    }

    /**
     * 월 식대 조회
     */
    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;
    }

    /**
     * 체크포인트 생성
     */
    private function generateCheckPoints(
        int $tenantId,
        int $employeeCount,
        float $usedAmount,
        int $monthCount,
        string $startDate,
        string $endDate
    ): array {
        $checkPoints = [];

        // 1인당 월 복리후생비 계산
        $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_normal',
                'type' => 'success',
                'message' => "1인당 월 복리후생비 {$perPersonFormatted}만원. 업계 평균(15~25만원) 내 정상 운영 중입니다.",
                'highlights' => [
                    ['text' => "1인당 월 복리후생비 {$perPersonFormatted}만원", 'color' => 'green'],
                ],
            ];
        } elseif ($perPersonMonthly < self::INDUSTRY_AVG_MIN) {
            $checkPoints[] = [
                'id' => 'wf_cp_low',
                'type' => 'warning',
                'message' => "1인당 월 복리후생비 {$perPersonFormatted}만원. 업계 평균(15~25만원) 대비 낮습니다.",
                'highlights' => [
                    ['text' => "1인당 월 복리후생비 {$perPersonFormatted}만원", 'color' => 'orange'],
                ],
            ];
        } else {
            $checkPoints[] = [
                'id' => 'wf_cp_high',
                'type' => 'warning',
                'message' => "1인당 월 복리후생비 {$perPersonFormatted}만원. 업계 평균(15~25만원) 대비 높습니다.",
                'highlights' => [
                    ['text' => "1인당 월 복리후생비 {$perPersonFormatted}만원", 'color' => 'orange'],
                ],
            ];
        }

        // 식대 비과세 한도 체크
        $mealAmount = $this->getMonthlyMealAmount($tenantId, $startDate, $endDate);
        $perPersonMeal = $employeeCount > 0 ? $mealAmount / $employeeCount : 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'],
                ],
            ];
        }

        return $checkPoints;
    }
}