<?php

namespace App\Services\HR;

use App\Models\HR\BusinessIncomeEarner;
use App\Models\HR\BusinessIncomePayment;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Facades\DB;

class BusinessIncomePaymentService
{
    /**
     * 월별 사업소득 지급 내역 조회
     */
    public function getPayments(int $year, int $month): Collection
    {
        $tenantId = session('selected_tenant_id', 1);

        return BusinessIncomePayment::query()
            ->with('user:id,name')
            ->forTenant($tenantId)
            ->forPeriod($year, $month)
            ->orderBy('id')
            ->get();
    }

    /**
     * 활성 사업소득자 목록
     */
    public function getActiveEarners(): Collection
    {
        $tenantId = session('selected_tenant_id', 1);

        return BusinessIncomeEarner::query()
            ->with('user:id,name')
            ->forTenant($tenantId)
            ->activeEmployees()
            ->orderBy('display_name')
            ->get();
    }

    /**
     * 일괄 저장
     *
     * - payment_id 기반 기존 레코드 조회 (수정 시)
     * - payment_id 없고 user_id 있으면 기존 방식 조회
     * - 둘 다 없으면 신규 생성
     * - 지급총액 == 0: draft면 삭제, confirmed/paid는 무시
     * - 제출되지 않은 기존 draft 행 자동 삭제 (사용자가 행을 삭제한 경우)
     */
    public function bulkSave(int $year, int $month, array $items): array
    {
        $tenantId = session('selected_tenant_id', 1);
        $saved = 0;
        $deleted = 0;
        $skipped = 0;

        DB::transaction(function () use ($items, $tenantId, $year, $month, &$saved, &$deleted, &$skipped) {
            $submittedPaymentIds = [];

            foreach ($items as $item) {
                $paymentId = ! empty($item['payment_id']) ? (int) $item['payment_id'] : null;
                $userId = ! empty($item['user_id']) ? (int) $item['user_id'] : null;
                $displayName = trim($item['display_name'] ?? '');
                $businessRegNumber = $item['business_reg_number'] ?? null;
                $grossAmount = (float) ($item['gross_amount'] ?? 0);

                if (empty($displayName)) {
                    continue;
                }

                $existing = null;

                // payment_id로 기존 레코드 조회
                if ($paymentId) {
                    $existing = BusinessIncomePayment::where('id', $paymentId)
                        ->where('tenant_id', $tenantId)
                        ->lockForUpdate()
                        ->first();
                }

                // user_id로 기존 레코드 조회 (payment_id 없고 user_id 있는 경우)
                if (! $existing && $userId) {
                    $existing = BusinessIncomePayment::withTrashed()
                        ->where('tenant_id', $tenantId)
                        ->where('user_id', $userId)
                        ->where('pay_year', $year)
                        ->where('pay_month', $month)
                        ->lockForUpdate()
                        ->first();
                }

                if ($grossAmount <= 0) {
                    // 지급총액 0: draft면 삭제
                    if ($existing && ! $existing->trashed() && $existing->isEditable()) {
                        $existing->update(['deleted_by' => auth()->id()]);
                        $existing->delete();
                        $deleted++;
                    }

                    continue;
                }

                // confirmed/paid 상태는 수정하지 않음
                if ($existing && ! $existing->trashed() && ! $existing->isEditable()) {
                    $submittedPaymentIds[] = $existing->id;
                    $skipped++;

                    continue;
                }

                $tax = BusinessIncomePayment::calculateTax($grossAmount);

                $data = [
                    'tenant_id' => $tenantId,
                    'user_id' => $userId,
                    'display_name' => $displayName,
                    'business_reg_number' => $businessRegNumber,
                    'pay_year' => $year,
                    'pay_month' => $month,
                    'service_content' => $item['service_content'] ?? null,
                    'gross_amount' => (int) $grossAmount,
                    'income_tax' => $tax['income_tax'],
                    'local_income_tax' => $tax['local_income_tax'],
                    'total_deductions' => $tax['total_deductions'],
                    'net_amount' => $tax['net_amount'],
                    'payment_date' => ! empty($item['payment_date']) ? $item['payment_date'] : null,
                    'note' => $item['note'] ?? null,
                    'updated_by' => auth()->id(),
                ];

                if ($existing && $existing->trashed()) {
                    $existing->forceDelete();
                    $existing = null;
                }

                if ($existing) {
                    $existing->update($data);
                    $submittedPaymentIds[] = $existing->id;
                } else {
                    $data['status'] = 'draft';
                    $data['created_by'] = auth()->id();
                    $record = BusinessIncomePayment::create($data);
                    $submittedPaymentIds[] = $record->id;
                }

                $saved++;
            }

            // 제출되지 않은 기존 draft 행 자동 삭제 (사용자가 행을 삭제한 경우)
            $orphanDrafts = BusinessIncomePayment::where('tenant_id', $tenantId)
                ->where('pay_year', $year)
                ->where('pay_month', $month)
                ->where('status', 'draft')
                ->when(count($submittedPaymentIds) > 0, fn ($q) => $q->whereNotIn('id', $submittedPaymentIds))
                ->get();

            foreach ($orphanDrafts as $orphan) {
                $orphan->update(['deleted_by' => auth()->id()]);
                $orphan->delete();
                $deleted++;
            }
        });

        return [
            'saved' => $saved,
            'deleted' => $deleted,
            'skipped' => $skipped,
        ];
    }

    /**
     * 월간 통계 (통계 카드용)
     */
    public function getMonthlyStats(int $year, int $month): array
    {
        $tenantId = session('selected_tenant_id', 1);

        $result = BusinessIncomePayment::query()
            ->forTenant($tenantId)
            ->forPeriod($year, $month)
            ->select(
                DB::raw('COUNT(*) as total_count'),
                DB::raw('SUM(gross_amount) as total_gross'),
                DB::raw('SUM(total_deductions) as total_deductions'),
                DB::raw('SUM(net_amount) as total_net'),
                DB::raw("SUM(CASE WHEN status = 'draft' THEN 1 ELSE 0 END) as draft_count"),
                DB::raw("SUM(CASE WHEN status = 'confirmed' THEN 1 ELSE 0 END) as confirmed_count"),
                DB::raw("SUM(CASE WHEN status = 'paid' THEN 1 ELSE 0 END) as paid_count"),
            )
            ->first();

        return [
            'total_gross' => (int) ($result->total_gross ?? 0),
            'total_deductions' => (int) ($result->total_deductions ?? 0),
            'total_net' => (int) ($result->total_net ?? 0),
            'total_count' => (int) ($result->total_count ?? 0),
            'draft_count' => (int) ($result->draft_count ?? 0),
            'confirmed_count' => (int) ($result->confirmed_count ?? 0),
            'paid_count' => (int) ($result->paid_count ?? 0),
        ];
    }

    /**
     * XLSX 내보내기 데이터
     */
    public function getExportData(int $year, int $month): Collection
    {
        $tenantId = session('selected_tenant_id', 1);

        return BusinessIncomePayment::query()
            ->with('user:id,name')
            ->forTenant($tenantId)
            ->forPeriod($year, $month)
            ->orderBy('id')
            ->get();
    }
}
