<?php

namespace App\Http\Controllers\Api\Admin\HR;

use App\Http\Controllers\Controller;
use App\Models\HR\Payroll;
use App\Services\HR\PayrollService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Symfony\Component\HttpFoundation\StreamedResponse;

class PayrollController extends Controller
{
    public function __construct(
        private PayrollService $payrollService
    ) {}

    /**
     * 급여 목록 조회 (HTMX → HTML / 일반 → JSON)
     */
    public function index(Request $request): JsonResponse|Response
    {
        $payrolls = $this->payrollService->getPayrolls(
            $request->all(),
            $request->integer('per_page', 20)
        );

        if ($request->header('HX-Request')) {
            return response(view('hr.payrolls.partials.table', compact('payrolls')));
        }

        return response()->json([
            'success' => true,
            'data' => $payrolls->items(),
            'meta' => [
                'current_page' => $payrolls->currentPage(),
                'last_page' => $payrolls->lastPage(),
                'per_page' => $payrolls->perPage(),
                'total' => $payrolls->total(),
            ],
        ]);
    }

    /**
     * 월간 통계 (HTMX → HTML / 일반 → JSON)
     */
    public function stats(Request $request): JsonResponse|Response
    {
        $stats = $this->payrollService->getMonthlyStats(
            $request->integer('year') ?: null,
            $request->integer('month') ?: null
        );

        if ($request->header('HX-Request')) {
            return response(view('hr.payrolls.partials.stats', compact('stats')));
        }

        return response()->json([
            'success' => true,
            'data' => $stats,
        ]);
    }

    /**
     * 급여 등록
     */
    public function store(Request $request): JsonResponse
    {
        $validated = $request->validate([
            'user_id' => 'required|integer|exists:users,id',
            'pay_year' => 'required|integer|min:2020|max:2100',
            'pay_month' => 'required|integer|min:1|max:12',
            'base_salary' => 'required|numeric|min:0',
            'overtime_pay' => 'nullable|numeric|min:0',
            'bonus' => 'nullable|numeric|min:0',
            'allowances' => 'nullable|array',
            'allowances.*.name' => 'required_with:allowances|string',
            'allowances.*.amount' => 'required_with:allowances|numeric|min:0',
            'deductions' => 'nullable|array',
            'deductions.*.name' => 'required_with:deductions|string',
            'deductions.*.amount' => 'required_with:deductions|numeric|min:0',
            'note' => 'nullable|string|max:500',
        ]);

        try {
            $payroll = $this->payrollService->storePayroll($validated);

            return response()->json([
                'success' => true,
                'message' => '급여가 등록되었습니다.',
                'data' => $payroll,
            ], 201);
        } catch (\InvalidArgumentException $e) {
            return response()->json([
                'success' => false,
                'message' => $e->getMessage(),
            ], 422);
        } catch (\Throwable $e) {
            report($e);

            return response()->json([
                'success' => false,
                'message' => '급여 등록 중 오류가 발생했습니다.',
                'error' => config('app.debug') ? $e->getMessage() : null,
            ], 500);
        }
    }

    /**
     * 급여 수정
     */
    public function update(Request $request, int $id): JsonResponse
    {
        $validated = $request->validate([
            'base_salary' => 'sometimes|required|numeric|min:0',
            'overtime_pay' => 'nullable|numeric|min:0',
            'bonus' => 'nullable|numeric|min:0',
            'allowances' => 'nullable|array',
            'allowances.*.name' => 'required_with:allowances|string',
            'allowances.*.amount' => 'required_with:allowances|numeric|min:0',
            'deductions' => 'nullable|array',
            'deductions.*.name' => 'required_with:deductions|string',
            'deductions.*.amount' => 'required_with:deductions|numeric|min:0',
            'note' => 'nullable|string|max:500',
        ]);

        try {
            $payroll = $this->payrollService->updatePayroll($id, $validated);

            if (! $payroll) {
                return response()->json([
                    'success' => false,
                    'message' => '급여 정보를 찾을 수 없거나 수정할 수 없는 상태입니다.',
                ], 404);
            }

            return response()->json([
                'success' => true,
                'message' => '급여가 수정되었습니다.',
                'data' => $payroll,
            ]);
        } catch (\Throwable $e) {
            report($e);

            return response()->json([
                'success' => false,
                'message' => '급여 수정 중 오류가 발생했습니다.',
                'error' => config('app.debug') ? $e->getMessage() : null,
            ], 500);
        }
    }

    /**
     * 급여 삭제
     */
    public function destroy(Request $request, int $id): JsonResponse|Response
    {
        try {
            $result = $this->payrollService->deletePayroll($id);

            if (! $result) {
                return response()->json([
                    'success' => false,
                    'message' => '급여 정보를 찾을 수 없거나 삭제할 수 없는 상태입니다.',
                ], 404);
            }

            if ($request->header('HX-Request')) {
                $payrolls = $this->payrollService->getPayrolls(
                    $request->all(),
                    $request->integer('per_page', 20)
                );

                return response(view('hr.payrolls.partials.table', compact('payrolls')));
            }

            return response()->json([
                'success' => true,
                'message' => '급여가 삭제되었습니다.',
            ]);
        } catch (\Throwable $e) {
            report($e);

            return response()->json([
                'success' => false,
                'message' => '급여 삭제 중 오류가 발생했습니다.',
                'error' => config('app.debug') ? $e->getMessage() : null,
            ], 500);
        }
    }

    /**
     * 급여 확정
     */
    public function confirm(Request $request, int $id): JsonResponse
    {
        try {
            $payroll = $this->payrollService->confirmPayroll($id);

            if (! $payroll) {
                return response()->json([
                    'success' => false,
                    'message' => '급여를 확정할 수 없습니다.',
                ], 404);
            }

            return response()->json([
                'success' => true,
                'message' => '급여가 확정되었습니다.',
                'data' => $payroll,
            ]);
        } catch (\Throwable $e) {
            report($e);

            return response()->json([
                'success' => false,
                'message' => '급여 확정 중 오류가 발생했습니다.',
                'error' => config('app.debug') ? $e->getMessage() : null,
            ], 500);
        }
    }

    /**
     * 급여 지급 처리
     */
    public function pay(Request $request, int $id): JsonResponse
    {
        try {
            $payroll = $this->payrollService->payPayroll($id);

            if (! $payroll) {
                return response()->json([
                    'success' => false,
                    'message' => '급여를 지급 처리할 수 없습니다.',
                ], 404);
            }

            return response()->json([
                'success' => true,
                'message' => '급여가 지급 처리되었습니다.',
                'data' => $payroll,
            ]);
        } catch (\Throwable $e) {
            report($e);

            return response()->json([
                'success' => false,
                'message' => '급여 지급 처리 중 오류가 발생했습니다.',
                'error' => config('app.debug') ? $e->getMessage() : null,
            ], 500);
        }
    }

    /**
     * 일괄 생성
     */
    public function bulkGenerate(Request $request): JsonResponse
    {
        $validated = $request->validate([
            'year' => 'required|integer|min:2020|max:2100',
            'month' => 'required|integer|min:1|max:12',
        ]);

        try {
            $result = $this->payrollService->bulkGenerate($validated['year'], $validated['month']);

            return response()->json([
                'success' => true,
                'message' => "신규 {$result['created']}건 생성, {$result['skipped']}건 건너뜀 (이미 존재).",
                'data' => $result,
            ]);
        } catch (\Throwable $e) {
            report($e);

            return response()->json([
                'success' => false,
                'message' => '일괄 생성 중 오류가 발생했습니다.',
                'error' => config('app.debug') ? $e->getMessage() : null,
            ], 500);
        }
    }

    /**
     * 엑셀(CSV) 내보내기
     */
    public function export(Request $request): StreamedResponse
    {
        $payrolls = $this->payrollService->getExportData($request->all());
        $year = $request->input('year', now()->year);
        $month = $request->input('month', now()->month);

        $filename = "급여관리_{$year}년{$month}월_".now()->format('Ymd').'.csv';

        return response()->streamDownload(function () use ($payrolls) {
            $file = fopen('php://output', 'w');
            fwrite($file, "\xEF\xBB\xBF"); // UTF-8 BOM

            fputcsv($file, ['사원명', '부서', '기본급', '고정연장근로수당', '상여금', '총지급액', '국민연금', '건강보험', '고용보험', '근로소득세', '지방소득세', '총공제액', '실수령액', '상태']);

            foreach ($payrolls as $payroll) {
                $profile = $payroll->user?->tenantProfiles?->first();
                $displayName = $profile?->display_name ?? $payroll->user?->name ?? '-';
                $department = $profile?->department?->name ?? '-';
                $statusLabel = Payroll::STATUS_MAP[$payroll->status] ?? $payroll->status;

                fputcsv($file, [
                    $displayName,
                    $department,
                    $payroll->base_salary,
                    $payroll->overtime_pay,
                    $payroll->bonus,
                    $payroll->gross_salary,
                    $payroll->pension,
                    $payroll->health_insurance,
                    $payroll->employment_insurance,
                    $payroll->income_tax,
                    $payroll->resident_tax,
                    $payroll->total_deductions,
                    $payroll->net_salary,
                    $statusLabel,
                ]);
            }

            fclose($file);
        }, $filename, [
            'Content-Type' => 'text/csv; charset=UTF-8',
        ]);
    }

    /**
     * 급여 설정 조회 (HTMX → HTML / 일반 → JSON)
     */
    public function settingsIndex(Request $request): JsonResponse|Response
    {
        $settings = $this->payrollService->getSettings();

        if ($request->header('HX-Request')) {
            return response(view('hr.payrolls.partials.settings', compact('settings')));
        }

        return response()->json([
            'success' => true,
            'data' => $settings,
        ]);
    }

    /**
     * 급여 설정 수정
     */
    public function settingsUpdate(Request $request): JsonResponse
    {
        $validated = $request->validate([
            'health_insurance_rate' => 'nullable|numeric|min:0|max:100',
            'long_term_care_rate' => 'nullable|numeric|min:0|max:100',
            'pension_rate' => 'nullable|numeric|min:0|max:100',
            'employment_insurance_rate' => 'nullable|numeric|min:0|max:100',
            'pension_max_salary' => 'nullable|numeric|min:0',
            'pension_min_salary' => 'nullable|numeric|min:0',
            'pay_day' => 'nullable|integer|min:1|max:31',
            'auto_calculate' => 'nullable|boolean',
        ]);

        try {
            $settings = $this->payrollService->updateSettings($validated);

            return response()->json([
                'success' => true,
                'message' => '급여 설정이 저장되었습니다.',
                'data' => $settings,
            ]);
        } catch (\Throwable $e) {
            report($e);

            return response()->json([
                'success' => false,
                'message' => '설정 저장 중 오류가 발생했습니다.',
                'error' => config('app.debug') ? $e->getMessage() : null,
            ], 500);
        }
    }

    /**
     * 급여 계산 미리보기 (AJAX)
     */
    public function calculate(Request $request): JsonResponse
    {
        $validated = $request->validate([
            'base_salary' => 'required|numeric|min:0',
            'overtime_pay' => 'nullable|numeric|min:0',
            'bonus' => 'nullable|numeric|min:0',
            'allowances' => 'nullable|array',
            'deductions' => 'nullable|array',
        ]);

        $result = $this->payrollService->calculateAmounts($validated);

        return response()->json([
            'success' => true,
            'data' => $result,
        ]);
    }
}
