<?php

namespace App\Services;

use App\Models\Approvals\Approval;
use App\Models\Approvals\ApprovalForm;
use App\Models\Approvals\ApprovalLine;
use App\Models\Approvals\ApprovalStep;
use App\Models\Boards\File;
use App\Models\User;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Facades\DB;

class ApprovalService
{
    // =========================================================================
    // 목록 조회
    // =========================================================================

    /**
     * 기안함 (내가 기안한 문서)
     */
    public function getMyDrafts(array $filters = [], int $perPage = 15): LengthAwarePaginator
    {
        $userId = auth()->id();

        $query = Approval::with(['form', 'steps.approver'])
            ->byDrafter($userId);

        $this->applyFilters($query, $filters);

        return $query->orderByDesc('created_at')->paginate($perPage);
    }

    /**
     * 결재 대기함 (내가 현재 결재자인 문서)
     */
    public function getPendingForMe(int $userId, array $filters = [], int $perPage = 15): LengthAwarePaginator
    {
        $query = Approval::with(['form', 'drafter', 'steps.approver'])
            ->pending()
            ->whereHas('steps', function ($q) use ($userId) {
                $q->where('approver_id', $userId)
                    ->where('status', ApprovalStep::STATUS_PENDING)
                    ->approvalOnly()
                    ->where('step_order', function ($sub) {
                        $sub->selectRaw('MIN(step_order)')
                            ->from('approval_steps as inner_steps')
                            ->whereColumn('inner_steps.approval_id', 'approval_steps.approval_id')
                            ->where('inner_steps.status', ApprovalStep::STATUS_PENDING)
                            ->whereIn('inner_steps.step_type', [
                                ApprovalLine::STEP_TYPE_APPROVAL,
                                ApprovalLine::STEP_TYPE_AGREEMENT,
                            ]);
                    });
            });

        $this->applyFilters($query, $filters);

        return $query->orderByDesc('drafted_at')->paginate($perPage);
    }

    /**
     * 처리 완료함 (내가 기안한 완료 문서 + 내가 결재 처리한 문서)
     */
    public function getCompletedByMe(int $userId, array $filters = [], int $perPage = 15): LengthAwarePaginator
    {
        $query = Approval::with(['form', 'drafter', 'steps.approver'])
            ->where(function ($q) use ($userId) {
                // 내가 기안한 완료/반려/회수 문서
                $q->where(function ($sub) use ($userId) {
                    $sub->where('drafter_id', $userId)
                        ->whereIn('status', [
                            Approval::STATUS_APPROVED,
                            Approval::STATUS_REJECTED,
                            Approval::STATUS_CANCELLED,
                        ]);
                })
                // 또는 내가 결재자로 처리한 문서
                    ->orWhereHas('steps', function ($sub) use ($userId) {
                        $sub->where('approver_id', $userId)
                            ->whereIn('status', [ApprovalStep::STATUS_APPROVED, ApprovalStep::STATUS_REJECTED]);
                    });
            });

        $this->applyFilters($query, $filters);

        return $query->orderByDesc('updated_at')->paginate($perPage);
    }

    /**
     * 참조함 (내가 참조자인 문서)
     */
    public function getReferencesForMe(int $userId, array $filters = [], int $perPage = 15): LengthAwarePaginator
    {
        $query = Approval::with(['form', 'drafter', 'steps.approver'])
            ->whereHas('steps', function ($q) use ($userId, $filters) {
                $q->where('approver_id', $userId)
                    ->where('step_type', ApprovalLine::STEP_TYPE_REFERENCE);
                if (isset($filters['is_read'])) {
                    $q->where('is_read', $filters['is_read'] === 'true' || $filters['is_read'] === '1');
                }
            });

        $this->applyFilters($query, $filters);

        return $query->orderByDesc('created_at')->paginate($perPage);
    }

    // =========================================================================
    // CRUD
    // =========================================================================

    /**
     * 상세 조회
     */
    public function getApproval(int $id): Approval
    {
        return Approval::with(['form', 'drafter', 'line', 'steps.approver'])
            ->findOrFail($id);
    }

    /**
     * 생성 (임시저장)
     */
    public function createApproval(array $data): Approval
    {
        return DB::transaction(function () use ($data) {
            $tenantId = session('selected_tenant_id');
            $userId = auth()->id();

            $approval = Approval::create([
                'tenant_id' => $tenantId,
                'document_number' => $this->generateDocumentNumber($tenantId),
                'form_id' => $data['form_id'],
                'line_id' => $data['line_id'] ?? null,
                'title' => $data['title'],
                'content' => $data['content'] ?? [],
                'body' => $data['body'] ?? null,
                'status' => Approval::STATUS_DRAFT,
                'is_urgent' => $data['is_urgent'] ?? false,
                'drafter_id' => $userId,
                'department_id' => $data['department_id'] ?? null,
                'current_step' => 0,
                'created_by' => $userId,
                'updated_by' => $userId,
            ]);

            if (! empty($data['steps'])) {
                $this->saveApprovalSteps($approval, $data['steps']);
            }

            // 첨부파일 연결
            if (! empty($data['attachment_file_ids'])) {
                $this->linkAttachments($approval, $data['attachment_file_ids']);
            }

            return $approval->load(['form', 'drafter', 'steps.approver']);
        });
    }

    /**
     * 수정 (draft/rejected만)
     */
    public function updateApproval(int $id, array $data): Approval
    {
        return DB::transaction(function () use ($id, $data) {
            $approval = Approval::findOrFail($id);

            if (! $approval->isEditable()) {
                throw new \InvalidArgumentException('수정할 수 없는 상태입니다.');
            }

            $approval->update([
                'form_id' => $data['form_id'] ?? $approval->form_id,
                'line_id' => $data['line_id'] ?? $approval->line_id,
                'title' => $data['title'] ?? $approval->title,
                'content' => $data['content'] ?? $approval->content,
                'body' => $data['body'] ?? $approval->body,
                'is_urgent' => $data['is_urgent'] ?? $approval->is_urgent,
                'department_id' => $data['department_id'] ?? $approval->department_id,
                'updated_by' => auth()->id(),
            ]);

            if (isset($data['steps'])) {
                $approval->steps()->delete();
                $this->saveApprovalSteps($approval, $data['steps']);
            }

            // 첨부파일 갱신
            if (array_key_exists('attachment_file_ids', $data)) {
                $this->linkAttachments($approval, $data['attachment_file_ids'] ?? []);
            }

            return $approval->load(['form', 'drafter', 'steps.approver']);
        });
    }

    /**
     * 삭제 (일반: draft만 / 관리자: 모든 상태)
     */
    public function deleteApproval(int $id, ?User $user = null): bool
    {
        $approval = Approval::with('form')->findOrFail($id);
        $user = $user ?? auth()->user();

        if (! $approval->isDeletableBy($user)) {
            throw new \InvalidArgumentException('삭제 권한이 없습니다.');
        }

        // 진행 중/보류 문서 삭제 시 연동 후처리 (휴가 등)
        if (in_array($approval->status, [Approval::STATUS_PENDING, Approval::STATUS_ON_HOLD])) {
            $this->handleApprovalDeleted($approval);
        }

        $approval->steps()->delete();
        $approval->update(['deleted_by' => $user->id]);

        return $approval->delete();
    }

    // =========================================================================
    // 워크플로우
    // =========================================================================

    /**
     * 상신 (draft/rejected → pending)
     */
    public function submit(int $id): Approval
    {
        return DB::transaction(function () use ($id) {
            $approval = Approval::with('steps')->findOrFail($id);

            if (! $approval->isSubmittable()) {
                throw new \InvalidArgumentException('상신할 수 없는 상태입니다.');
            }

            $approverSteps = $approval->steps
                ->whereIn('step_type', [ApprovalLine::STEP_TYPE_APPROVAL, ApprovalLine::STEP_TYPE_AGREEMENT]);

            if ($approverSteps->isEmpty()) {
                throw new \InvalidArgumentException('결재선을 설정해주세요.');
            }

            // 반려 후 재상신이면 모든 step 초기화
            if ($approval->status === Approval::STATUS_REJECTED) {
                $approval->steps()->update([
                    'status' => ApprovalStep::STATUS_PENDING,
                    'comment' => null,
                    'acted_at' => null,
                ]);
            }

            $approval->update([
                'status' => Approval::STATUS_PENDING,
                'drafted_at' => now(),
                'current_step' => 1,
                'updated_by' => auth()->id(),
            ]);

            return $approval->fresh(['form', 'drafter', 'steps.approver']);
        });
    }

    /**
     * 승인
     */
    public function approve(int $id, ?string $comment = null): Approval
    {
        return DB::transaction(function () use ($id, $comment) {
            $approval = Approval::with('steps')->findOrFail($id);

            if (! $approval->isActionable()) {
                throw new \InvalidArgumentException('승인할 수 없는 상태입니다.');
            }

            $currentStep = $approval->getCurrentApproverStep();
            if (! $currentStep || $currentStep->approver_id !== auth()->id()) {
                throw new \InvalidArgumentException('현재 결재자가 아닙니다.');
            }

            $currentStep->update([
                'status' => ApprovalStep::STATUS_APPROVED,
                'comment' => $comment,
                'acted_at' => now(),
            ]);

            // 다음 결재자 확인
            $nextStep = $approval->steps()
                ->whereIn('step_type', [ApprovalLine::STEP_TYPE_APPROVAL, ApprovalLine::STEP_TYPE_AGREEMENT])
                ->where('status', ApprovalStep::STATUS_PENDING)
                ->orderBy('step_order')
                ->first();

            if ($nextStep) {
                $approval->update([
                    'current_step' => $nextStep->step_order,
                    'updated_by' => auth()->id(),
                ]);
            } else {
                // 마지막 결재자 → 문서 승인 완료
                $approval->update([
                    'status' => Approval::STATUS_APPROVED,
                    'completed_at' => now(),
                    'updated_by' => auth()->id(),
                ]);

                // 연동 후처리 (휴가 등)
                $this->handleApprovalCompleted($approval);
            }

            return $approval->fresh(['form', 'drafter', 'steps.approver']);
        });
    }

    /**
     * 반려
     */
    public function reject(int $id, string $comment): Approval
    {
        return DB::transaction(function () use ($id, $comment) {
            $approval = Approval::with('steps')->findOrFail($id);

            if (! $approval->isActionable()) {
                throw new \InvalidArgumentException('반려할 수 없는 상태입니다.');
            }

            $currentStep = $approval->getCurrentApproverStep();
            if (! $currentStep || $currentStep->approver_id !== auth()->id()) {
                throw new \InvalidArgumentException('현재 결재자가 아닙니다.');
            }

            if (empty($comment)) {
                throw new \InvalidArgumentException('반려 사유를 입력해주세요.');
            }

            $currentStep->update([
                'status' => ApprovalStep::STATUS_REJECTED,
                'comment' => $comment,
                'acted_at' => now(),
            ]);

            $approval->update([
                'status' => Approval::STATUS_REJECTED,
                'completed_at' => now(),
                'updated_by' => auth()->id(),
            ]);

            // 연동 후처리 (휴가 등)
            $this->handleApprovalRejected($approval, $comment);

            return $approval->fresh(['form', 'drafter', 'steps.approver']);
        });
    }

    /**
     * 회수 (기안자만, pending/on_hold → cancelled)
     */
    public function cancel(int $id, ?string $recallReason = null): Approval
    {
        return DB::transaction(function () use ($id, $recallReason) {
            $approval = Approval::with('steps')->findOrFail($id);

            if (! $approval->isCancellable()) {
                throw new \InvalidArgumentException('회수할 수 없는 상태입니다.');
            }

            if ($approval->drafter_id !== auth()->id()) {
                throw new \InvalidArgumentException('기안자만 회수할 수 있습니다.');
            }

            // 첫 번째 결재자가 이미 처리했으면 회수 불가
            $firstApproverStep = $approval->steps()
                ->approvalOnly()
                ->orderBy('step_order')
                ->first();

            if ($firstApproverStep && $firstApproverStep->status !== ApprovalStep::STATUS_PENDING
                && $firstApproverStep->status !== ApprovalStep::STATUS_ON_HOLD) {
                throw new \InvalidArgumentException('첫 번째 결재자가 이미 처리하여 회수할 수 없습니다.');
            }

            // 모든 pending/on_hold steps → skipped
            $approval->steps()
                ->whereIn('status', [ApprovalStep::STATUS_PENDING, ApprovalStep::STATUS_ON_HOLD])
                ->update(['status' => ApprovalStep::STATUS_SKIPPED]);

            $approval->update([
                'status' => Approval::STATUS_CANCELLED,
                'completed_at' => now(),
                'recall_reason' => $recallReason,
                'updated_by' => auth()->id(),
            ]);

            // 연동 후처리 (휴가 회수)
            $this->handleApprovalCancelled($approval);

            return $approval->fresh(['form', 'drafter', 'steps.approver']);
        });
    }

    /**
     * 보류 (현재 결재자만, pending → on_hold)
     */
    public function hold(int $id, string $comment): Approval
    {
        return DB::transaction(function () use ($id, $comment) {
            $approval = Approval::with('steps')->findOrFail($id);

            if (! $approval->isHoldable()) {
                throw new \InvalidArgumentException('보류할 수 없는 상태입니다.');
            }

            $currentStep = $approval->getCurrentApproverStep();
            if (! $currentStep || $currentStep->approver_id !== auth()->id()) {
                throw new \InvalidArgumentException('현재 결재자가 아닙니다.');
            }

            if (empty($comment)) {
                throw new \InvalidArgumentException('보류 사유를 입력해주세요.');
            }

            $currentStep->update([
                'status' => ApprovalStep::STATUS_ON_HOLD,
                'comment' => $comment,
                'acted_at' => now(),
            ]);

            $approval->update([
                'status' => Approval::STATUS_ON_HOLD,
                'updated_by' => auth()->id(),
            ]);

            return $approval->fresh(['form', 'drafter', 'steps.approver']);
        });
    }

    /**
     * 보류 해제 (보류한 결재자만, on_hold → pending)
     */
    public function releaseHold(int $id): Approval
    {
        return DB::transaction(function () use ($id) {
            $approval = Approval::with('steps')->findOrFail($id);

            if (! $approval->isHoldReleasable()) {
                throw new \InvalidArgumentException('보류 해제할 수 없는 상태입니다.');
            }

            $holdStep = $approval->steps()
                ->where('status', ApprovalStep::STATUS_ON_HOLD)
                ->first();

            if (! $holdStep || $holdStep->approver_id !== auth()->id()) {
                throw new \InvalidArgumentException('보류한 결재자만 해제할 수 있습니다.');
            }

            $holdStep->update([
                'status' => ApprovalStep::STATUS_PENDING,
                'comment' => null,
                'acted_at' => null,
            ]);

            $approval->update([
                'status' => Approval::STATUS_PENDING,
                'updated_by' => auth()->id(),
            ]);

            return $approval->fresh(['form', 'drafter', 'steps.approver']);
        });
    }

    /**
     * 전결 (현재 결재자가 이후 모든 결재를 건너뛰고 최종 승인)
     */
    public function preDecide(int $id, ?string $comment = null): Approval
    {
        return DB::transaction(function () use ($id, $comment) {
            $approval = Approval::with('steps')->findOrFail($id);

            if (! $approval->isActionable()) {
                throw new \InvalidArgumentException('전결할 수 없는 상태입니다.');
            }

            $currentStep = $approval->getCurrentApproverStep();
            if (! $currentStep || $currentStep->approver_id !== auth()->id()) {
                throw new \InvalidArgumentException('현재 결재자가 아닙니다.');
            }

            // 현재 step → approved + pre_decided
            $currentStep->update([
                'status' => ApprovalStep::STATUS_APPROVED,
                'approval_type' => 'pre_decided',
                'comment' => $comment,
                'acted_at' => now(),
            ]);

            // 이후 모든 pending approval/agreement steps → skipped
            $approval->steps()
                ->where('step_order', '>', $currentStep->step_order)
                ->whereIn('step_type', [ApprovalLine::STEP_TYPE_APPROVAL, ApprovalLine::STEP_TYPE_AGREEMENT])
                ->where('status', ApprovalStep::STATUS_PENDING)
                ->update(['status' => ApprovalStep::STATUS_SKIPPED]);

            // 문서 최종 승인
            $approval->update([
                'status' => Approval::STATUS_APPROVED,
                'completed_at' => now(),
                'updated_by' => auth()->id(),
            ]);

            // 연동 후처리 (휴가 등)
            $this->handleApprovalCompleted($approval);

            return $approval->fresh(['form', 'drafter', 'steps.approver']);
        });
    }

    /**
     * 복사 재기안 (완료/반려/회수 문서를 복사하여 새 draft 생성)
     */
    public function copyForRedraft(int $id): Approval
    {
        return DB::transaction(function () use ($id) {
            $original = Approval::with('steps')->findOrFail($id);

            if (! $original->isCopyable()) {
                throw new \InvalidArgumentException('복사할 수 없는 상태입니다.');
            }

            if ($original->drafter_id !== auth()->id()) {
                throw new \InvalidArgumentException('기안자만 복사할 수 있습니다.');
            }

            $tenantId = session('selected_tenant_id');

            // 새 문서 생성
            $newApproval = Approval::create([
                'tenant_id' => $tenantId,
                'document_number' => $this->generateDocumentNumber($tenantId),
                'form_id' => $original->form_id,
                'line_id' => $original->line_id,
                'title' => $original->title,
                'content' => $original->content,
                'body' => $original->body,
                'status' => Approval::STATUS_DRAFT,
                'is_urgent' => $original->is_urgent,
                'drafter_id' => auth()->id(),
                'department_id' => $original->department_id,
                'current_step' => 0,
                'parent_doc_id' => $original->id,
                'created_by' => auth()->id(),
                'updated_by' => auth()->id(),
            ]);

            // 결재선 복사 (모두 pending 상태로)
            foreach ($original->steps as $step) {
                ApprovalStep::create([
                    'approval_id' => $newApproval->id,
                    'step_order' => $step->step_order,
                    'step_type' => $step->step_type,
                    'approver_id' => $step->approver_id,
                    'approver_name' => $step->approver_name,
                    'approver_department' => $step->approver_department,
                    'approver_position' => $step->approver_position,
                    'status' => ApprovalStep::STATUS_PENDING,
                ]);
            }

            return $newApproval->load(['form', 'drafter', 'steps.approver']);
        });
    }

    /**
     * 참조 열람 추적
     */
    public function markAsRead(int $approvalId): void
    {
        $userId = auth()->id();

        ApprovalStep::where('approval_id', $approvalId)
            ->where('approver_id', $userId)
            ->where('step_type', ApprovalLine::STEP_TYPE_REFERENCE)
            ->where('is_read', false)
            ->update([
                'is_read' => true,
                'read_at' => now(),
            ]);
    }

    // =========================================================================
    // 결재선
    // =========================================================================

    /**
     * 결재선 템플릿 목록
     */
    public function getApprovalLines(): Collection
    {
        return ApprovalLine::orderBy('name')->get();
    }

    /**
     * 결재선 템플릿 생성
     */
    public function createLine(array $data): ApprovalLine
    {
        $tenantId = session('selected_tenant_id');
        $steps = $this->enrichLineSteps($data['steps']);

        return ApprovalLine::create([
            'tenant_id' => $tenantId,
            'name' => $data['name'],
            'steps' => $steps,
            'is_default' => $data['is_default'] ?? false,
            'created_by' => auth()->id(),
            'updated_by' => auth()->id(),
        ]);
    }

    /**
     * 결재선 템플릿 수정
     */
    public function updateLine(int $id, array $data): ApprovalLine
    {
        $line = ApprovalLine::findOrFail($id);
        $steps = $this->enrichLineSteps($data['steps']);

        $line->update([
            'name' => $data['name'],
            'steps' => $steps,
            'is_default' => $data['is_default'] ?? false,
            'updated_by' => auth()->id(),
        ]);

        return $line->fresh();
    }

    /**
     * 결재선 템플릿 삭제
     */
    public function deleteLine(int $id): bool
    {
        $line = ApprovalLine::findOrFail($id);
        $line->update(['deleted_by' => auth()->id()]);

        return $line->delete();
    }

    /**
     * 양식 목록
     */
    public function getApprovalForms(): Collection
    {
        return ApprovalForm::active()->orderBy('name')->get();
    }

    /**
     * 결재 단계 저장 + 스냅샷
     */
    public function saveApprovalSteps(Approval $approval, array $steps): void
    {
        foreach ($steps as $index => $step) {
            $user = User::find($step['user_id']);
            $tenantId = session('selected_tenant_id');

            $departmentName = null;
            $positionName = null;

            if ($user) {
                $employee = $user->tenantProfiles()
                    ->where('tenant_id', $tenantId)
                    ->first();

                if ($employee) {
                    $departmentName = $employee->department?->name;
                    $positionName = $employee->position_label ?? $employee->job_title_label;
                }
            }

            ApprovalStep::create([
                'approval_id' => $approval->id,
                'step_order' => $index + 1,
                'step_type' => $step['step_type'] ?? ApprovalLine::STEP_TYPE_APPROVAL,
                'approver_id' => $step['user_id'],
                'approver_name' => $user?->name ?? '',
                'approver_department' => $departmentName,
                'approver_position' => $positionName,
                'status' => ApprovalStep::STATUS_PENDING,
            ]);
        }
    }

    /**
     * 첨부파일 연결
     */
    public function linkAttachments(Approval $approval, array $fileIds): void
    {
        $attachments = [];

        if (! empty($fileIds)) {
            $files = File::whereIn('id', $fileIds)
                ->where('uploaded_by', auth()->id())
                ->get();

            foreach ($files as $file) {
                $attachments[] = [
                    'id' => $file->id,
                    'name' => $file->original_name,
                    'size' => $file->file_size,
                    'mime_type' => $file->mime_type,
                ];

                $file->update([
                    'is_temp' => false,
                    'document_id' => $approval->id,
                    'document_type' => 'approval',
                ]);
            }
        }

        $approval->update(['attachments' => $attachments]);
    }

    /**
     * 미처리 건수 (뱃지용)
     */
    public function getBadgeCounts(int $userId): array
    {
        $pendingCount = Approval::pending()
            ->whereHas('steps', function ($q) use ($userId) {
                $q->where('approver_id', $userId)
                    ->where('status', ApprovalStep::STATUS_PENDING)
                    ->approvalOnly()
                    ->where('step_order', function ($sub) {
                        $sub->selectRaw('MIN(step_order)')
                            ->from('approval_steps as inner_steps')
                            ->whereColumn('inner_steps.approval_id', 'approval_steps.approval_id')
                            ->where('inner_steps.status', ApprovalStep::STATUS_PENDING)
                            ->whereIn('inner_steps.step_type', [
                                ApprovalLine::STEP_TYPE_APPROVAL,
                                ApprovalLine::STEP_TYPE_AGREEMENT,
                            ]);
                    });
            })
            ->count();

        $draftCount = Approval::pending()->byDrafter($userId)->count();

        $referenceUnreadCount = ApprovalStep::where('approver_id', $userId)
            ->where('step_type', ApprovalLine::STEP_TYPE_REFERENCE)
            ->where('is_read', false)
            ->count();

        return [
            'pending' => $pendingCount,
            'draft' => $draftCount,
            'reference_unread' => $referenceUnreadCount,
        ];
    }

    // =========================================================================
    // Private 헬퍼
    // =========================================================================

    /**
     * 휴가/근태신청/사유서 관련 결재 양식인지 확인
     */
    private function isLeaveRelatedForm(?string $code): bool
    {
        return in_array($code, ['leave', 'attendance_request', 'reason_report']);
    }

    /**
     * 결재 최종 승인 시 연동 처리 (휴가/근태신청/사유서)
     */
    private function handleApprovalCompleted(Approval $approval): void
    {
        if (! $approval->form || ! $this->isLeaveRelatedForm($approval->form->code)) {
            return;
        }

        $leave = \App\Models\HR\Leave::where('approval_id', $approval->id)->first();
        if ($leave && $leave->status === 'pending') {
            app(\App\Services\HR\LeaveService::class)->approveByApproval($leave, $approval);
        }
    }

    /**
     * 결재 반려 시 연동 처리 (휴가/근태신청/사유서)
     */
    private function handleApprovalRejected(Approval $approval, string $comment): void
    {
        if (! $approval->form || ! $this->isLeaveRelatedForm($approval->form->code)) {
            return;
        }

        $leave = \App\Models\HR\Leave::where('approval_id', $approval->id)->first();
        if ($leave && $leave->status === 'pending') {
            app(\App\Services\HR\LeaveService::class)->rejectByApproval(
                $leave,
                $comment,
                auth()->id()
            );
        }
    }

    /**
     * 결재 삭제 시 연동 처리 (휴가/근태신청/사유서)
     */
    private function handleApprovalDeleted(Approval $approval): void
    {
        if (! $approval->form || ! $this->isLeaveRelatedForm($approval->form->code)) {
            return;
        }

        $leave = \App\Models\HR\Leave::where('approval_id', $approval->id)->first();
        if ($leave && in_array($leave->status, ['pending', 'approved'])) {
            $leave->update([
                'status' => 'cancelled',
                'updated_by' => auth()->id(),
            ]);
        }
    }

    /**
     * 결재 회수 시 연동 처리 (휴가/근태신청/사유서)
     */
    private function handleApprovalCancelled(Approval $approval): void
    {
        if (! $approval->form || ! $this->isLeaveRelatedForm($approval->form->code)) {
            return;
        }

        $leave = \App\Models\HR\Leave::where('approval_id', $approval->id)->first();
        if ($leave && $leave->status === 'pending') {
            $leave->update([
                'status' => 'cancelled',
                'updated_by' => auth()->id(),
            ]);
        }
    }

    /**
     * 결재선 steps에 user_name, department, position 스냅샷 보강
     */
    private function enrichLineSteps(array $steps): array
    {
        $tenantId = session('selected_tenant_id');

        return collect($steps)->map(function ($step) use ($tenantId) {
            $user = User::find($step['user_id']);
            $profile = $user?->tenantProfiles()->where('tenant_id', $tenantId)->first();

            return [
                'user_id' => $step['user_id'],
                'user_name' => $user?->name ?? '',
                'department' => $profile?->department?->name ?? $step['department'] ?? '',
                'position' => $profile?->position_label ?? $profile?->job_title_label ?? $step['position'] ?? '',
                'step_type' => $step['step_type'] ?? 'approval',
            ];
        })->toArray();
    }

    /**
     * 문서번호 채번 (APR-YYMMDD-001)
     */
    private function generateDocumentNumber(int $tenantId): string
    {
        $prefix = 'APR';
        $dateKey = now()->format('ymd');
        $documentType = 'approval';
        $periodKey = $dateKey;

        DB::statement(
            'INSERT INTO numbering_sequences
                (tenant_id, document_type, scope_key, period_key, last_sequence, created_at, updated_at)
             VALUES (?, ?, ?, ?, 1, NOW(), NOW())
             ON DUPLICATE KEY UPDATE
                last_sequence = last_sequence + 1,
                updated_at = NOW()',
            [$tenantId, $documentType, '', $periodKey]
        );

        $sequence = (int) DB::table('numbering_sequences')
            ->where('tenant_id', $tenantId)
            ->where('document_type', $documentType)
            ->where('scope_key', '')
            ->where('period_key', $periodKey)
            ->value('last_sequence');

        return $prefix.'-'.$dateKey.'-'.str_pad((string) $sequence, 3, '0', STR_PAD_LEFT);
    }

    /**
     * 공통 필터 적용
     */
    private function applyFilters($query, array $filters): void
    {
        if (! empty($filters['search'])) {
            $search = $filters['search'];
            $query->where(function ($q) use ($search) {
                $q->where('title', 'like', "%{$search}%")
                    ->orWhere('document_number', 'like', "%{$search}%");
            });
        }

        if (! empty($filters['status'])) {
            $query->where('status', $filters['status']);
        }

        if (! empty($filters['is_urgent'])) {
            $query->where('is_urgent', true);
        }

        if (! empty($filters['date_from'])) {
            $query->where('created_at', '>=', $filters['date_from']);
        }

        if (! empty($filters['date_to'])) {
            $query->where('created_at', '<=', $filters['date_to'].' 23:59:59');
        }
    }
}
