<?php

namespace App\Http\Controllers\Api\Admin;

use App\Http\Controllers\Controller;
use App\Models\Boards\File;
use App\Services\AppointmentCertService;
use App\Services\ApprovalService;
use App\Services\CareerCertService;
use App\Services\EmploymentCertService;
use App\Services\GoogleCloudStorageService;
use App\Services\ResignationService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;

class ApprovalApiController extends Controller
{
    public function __construct(
        private readonly ApprovalService $service
    ) {}

    // =========================================================================
    // 목록
    // =========================================================================

    /**
     * 기안함
     */
    public function drafts(Request $request): JsonResponse
    {
        $result = $this->service->getMyDrafts(
            $request->only(['search', 'status', 'is_urgent', 'date_from', 'date_to']),
            (int) $request->get('per_page', 15)
        );

        return response()->json($result);
    }

    /**
     * 결재 대기함
     */
    public function pending(Request $request): JsonResponse
    {
        $result = $this->service->getPendingForMe(
            auth()->id(),
            $request->only(['search', 'is_urgent', 'date_from', 'date_to']),
            (int) $request->get('per_page', 15)
        );

        return response()->json($result);
    }

    /**
     * 처리 완료함
     */
    public function completed(Request $request): JsonResponse
    {
        $result = $this->service->getCompletedByMe(
            auth()->id(),
            $request->only(['search', 'status', 'date_from', 'date_to']),
            (int) $request->get('per_page', 15)
        );

        return response()->json($result);
    }

    /**
     * 참조함
     */
    public function references(Request $request): JsonResponse
    {
        $result = $this->service->getReferencesForMe(
            auth()->id(),
            $request->only(['search', 'date_from', 'date_to', 'is_read']),
            (int) $request->get('per_page', 15)
        );

        return response()->json($result);
    }

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

    /**
     * 상세 조회
     */
    public function show(int $id): JsonResponse
    {
        $approval = $this->service->getApproval($id);

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

    /**
     * 생성 (임시저장)
     */
    public function store(Request $request): JsonResponse
    {
        $request->validate([
            'form_id' => 'required|exists:approval_forms,id',
            'title' => 'required|string|max:200',
            'body' => 'nullable|string',
            'content' => 'nullable|array',
            'is_urgent' => 'boolean',
            'steps' => 'nullable|array',
            'steps.*.user_id' => 'required_with:steps|exists:users,id',
            'steps.*.step_type' => 'required_with:steps|in:approval,agreement,reference',
            'attachment_file_ids' => 'nullable|array',
            'attachment_file_ids.*' => 'integer',
        ]);

        $approval = $this->service->createApproval($request->all());

        return response()->json([
            'success' => true,
            'message' => '결재 문서가 저장되었습니다.',
            'data' => $approval,
        ], 201);
    }

    /**
     * 수정
     */
    public function update(Request $request, int $id): JsonResponse
    {
        $request->validate([
            'title' => 'sometimes|string|max:200',
            'body' => 'nullable|string',
            'content' => 'nullable|array',
            'is_urgent' => 'boolean',
            'steps' => 'nullable|array',
            'steps.*.user_id' => 'required_with:steps|exists:users,id',
            'steps.*.step_type' => 'required_with:steps|in:approval,agreement,reference',
            'attachment_file_ids' => 'nullable|array',
            'attachment_file_ids.*' => 'integer',
        ]);

        try {
            $approval = $this->service->updateApproval($id, $request->all());

            return response()->json([
                'success' => true,
                'message' => '결재 문서가 수정되었습니다.',
                'data' => $approval,
            ]);
        } catch (\InvalidArgumentException $e) {
            return response()->json([
                'success' => false,
                'message' => $e->getMessage(),
            ], 400);
        }
    }

    /**
     * 삭제
     */
    public function destroy(int $id): JsonResponse
    {
        try {
            $user = auth()->user();
            $approval = $this->service->getApproval($id);

            if (! $approval->isDeletableBy($user)) {
                return response()->json([
                    'success' => false,
                    'message' => '삭제 권한이 없습니다.',
                ], 403);
            }

            $this->service->deleteApproval($id, $user);

            return response()->json([
                'success' => true,
                'message' => '결재 문서가 삭제되었습니다.',
            ]);
        } catch (\InvalidArgumentException $e) {
            return response()->json([
                'success' => false,
                'message' => $e->getMessage(),
            ], 400);
        }
    }

    /**
     * 영구삭제 (슈퍼관리자 전용)
     */
    public function forceDestroy(int $id): JsonResponse
    {
        if (! auth()->user()->isSuperAdmin()) {
            return response()->json([
                'success' => false,
                'message' => '슈퍼관리자만 영구삭제할 수 있습니다.',
            ], 403);
        }

        try {
            $this->service->forceDeleteApproval($id);

            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 bulkDestroy(Request $request): JsonResponse
    {
        $ids = $request->input('ids', []);
        if (empty($ids) || ! is_array($ids)) {
            return response()->json([
                'success' => false,
                'message' => '삭제할 문서를 선택하세요.',
            ], 400);
        }

        $user = auth()->user();
        $deleted = 0;
        $failed = 0;

        foreach ($ids as $id) {
            try {
                $approval = $this->service->getApproval($id);
                if ($approval->isDeletableBy($user)) {
                    $this->service->deleteApproval($id, $user);
                    $deleted++;
                } else {
                    $failed++;
                }
            } catch (\Throwable) {
                $failed++;
            }
        }

        $message = "{$deleted}건 삭제 완료";
        if ($failed > 0) {
            $message .= " ({$failed}건 삭제 불가)";
        }

        return response()->json([
            'success' => true,
            'message' => $message,
            'deleted' => $deleted,
            'failed' => $failed,
        ]);
    }

    // =========================================================================
    // 재직증명서
    // =========================================================================

    /**
     * 사원 재직증명서 정보 조회
     */
    public function certInfo(int $userId): JsonResponse
    {
        try {
            $tenantId = session('selected_tenant_id');
            $service = app(EmploymentCertService::class);
            $data = $service->getCertInfo($userId, $tenantId);

            return response()->json(['success' => true, 'data' => $data]);
        } catch (\Throwable $e) {
            return response()->json([
                'success' => false,
                'message' => '사원 정보를 불러올 수 없습니다.',
            ], 400);
        }
    }

    /**
     * 재직증명서 PDF 다운로드 (content JSON 기반 HTML→PDF)
     */
    public function certPdf(int $id)
    {
        $approval = \App\Models\Approvals\Approval::where('tenant_id', session('selected_tenant_id'))
            ->findOrFail($id);

        $content = $approval->content ?? [];
        $service = app(EmploymentCertService::class);

        return $service->generatePdfResponse($content);
    }

    // =========================================================================
    // 경력증명서
    // =========================================================================

    /**
     * 사원 경력증명서 정보 조회
     */
    public function careerCertInfo(int $userId): JsonResponse
    {
        try {
            $tenantId = session('selected_tenant_id');
            $service = app(CareerCertService::class);
            $data = $service->getCertInfo($userId, $tenantId);

            return response()->json(['success' => true, 'data' => $data]);
        } catch (\Throwable $e) {
            return response()->json([
                'success' => false,
                'message' => '사원 정보를 불러올 수 없습니다.',
            ], 400);
        }
    }

    /**
     * 경력증명서 PDF 다운로드
     */
    public function careerCertPdf(int $id)
    {
        $approval = \App\Models\Approvals\Approval::where('tenant_id', session('selected_tenant_id'))
            ->findOrFail($id);

        $content = $approval->content ?? [];
        $service = app(CareerCertService::class);

        return $service->generatePdfResponse($content);
    }

    // =========================================================================
    // 위촉증명서
    // =========================================================================

    /**
     * 사원 위촉증명서 정보 조회
     */
    public function appointmentCertInfo(int $userId): JsonResponse
    {
        try {
            $tenantId = session('selected_tenant_id');
            $service = app(AppointmentCertService::class);
            $data = $service->getCertInfo($userId, $tenantId);

            return response()->json(['success' => true, 'data' => $data]);
        } catch (\Throwable $e) {
            return response()->json([
                'success' => false,
                'message' => '사원 정보를 불러올 수 없습니다.',
            ], 400);
        }
    }

    /**
     * 위촉증명서 PDF 다운로드
     */
    public function appointmentCertPdf(int $id)
    {
        $approval = \App\Models\Approvals\Approval::where('tenant_id', session('selected_tenant_id'))
            ->findOrFail($id);

        $content = $approval->content ?? [];
        $service = app(AppointmentCertService::class);

        return $service->generatePdfResponse($content);
    }

    // =========================================================================
    // 사직서
    // =========================================================================

    /**
     * 사원 사직서 정보 조회
     */
    public function resignationInfo(int $userId): JsonResponse
    {
        try {
            $tenantId = session('selected_tenant_id');
            $service = app(ResignationService::class);
            $data = $service->getCertInfo($userId, $tenantId);

            return response()->json(['success' => true, 'data' => $data]);
        } catch (\Throwable $e) {
            return response()->json([
                'success' => false,
                'message' => '사원 정보를 불러올 수 없습니다.',
            ], 400);
        }
    }

    /**
     * 사직서 PDF 다운로드
     */
    public function resignationPdf(int $id)
    {
        $approval = \App\Models\Approvals\Approval::where('tenant_id', session('selected_tenant_id'))
            ->findOrFail($id);

        $content = $approval->content ?? [];
        $service = app(ResignationService::class);

        return $service->generatePdfResponse($content);
    }

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

    /**
     * 상신
     */
    public function submit(int $id): JsonResponse
    {
        try {
            $approval = $this->service->submit($id);

            return response()->json([
                'success' => true,
                'message' => '결재가 상신되었습니다.',
                'data' => $approval,
            ]);
        } catch (\InvalidArgumentException $e) {
            return response()->json([
                'success' => false,
                'message' => $e->getMessage(),
            ], 400);
        }
    }

    /**
     * 승인
     */
    public function approve(Request $request, int $id): JsonResponse
    {
        try {
            $approval = $this->service->approve($id, $request->get('comment'));

            return response()->json([
                'success' => true,
                'message' => '승인되었습니다.',
                'data' => $approval,
            ]);
        } catch (\InvalidArgumentException $e) {
            return response()->json([
                'success' => false,
                'message' => $e->getMessage(),
            ], 400);
        }
    }

    /**
     * 반려
     */
    public function reject(Request $request, int $id): JsonResponse
    {
        $request->validate([
            'comment' => 'required|string|max:1000',
        ]);

        try {
            $approval = $this->service->reject($id, $request->get('comment'));

            return response()->json([
                'success' => true,
                'message' => '반려되었습니다.',
                'data' => $approval,
            ]);
        } catch (\InvalidArgumentException $e) {
            return response()->json([
                'success' => false,
                'message' => $e->getMessage(),
            ], 400);
        }
    }

    /**
     * 회수
     */
    public function cancel(Request $request, int $id): JsonResponse
    {
        try {
            $approval = $this->service->cancel($id, $request->get('recall_reason'));

            return response()->json([
                'success' => true,
                'message' => '결재가 회수되었습니다.',
                'data' => $approval,
            ]);
        } catch (\InvalidArgumentException $e) {
            return response()->json([
                'success' => false,
                'message' => $e->getMessage(),
            ], 400);
        }
    }

    /**
     * 보류
     */
    public function hold(Request $request, int $id): JsonResponse
    {
        $request->validate([
            'comment' => 'required|string|max:1000',
        ]);

        try {
            $approval = $this->service->hold($id, $request->get('comment'));

            return response()->json([
                'success' => true,
                'message' => '보류되었습니다.',
                'data' => $approval,
            ]);
        } catch (\InvalidArgumentException $e) {
            return response()->json([
                'success' => false,
                'message' => $e->getMessage(),
            ], 400);
        }
    }

    /**
     * 보류 해제
     */
    public function releaseHold(int $id): JsonResponse
    {
        try {
            $approval = $this->service->releaseHold($id);

            return response()->json([
                'success' => true,
                'message' => '보류가 해제되었습니다.',
                'data' => $approval,
            ]);
        } catch (\InvalidArgumentException $e) {
            return response()->json([
                'success' => false,
                'message' => $e->getMessage(),
            ], 400);
        }
    }

    /**
     * 전결
     */
    public function preDecide(Request $request, int $id): JsonResponse
    {
        try {
            $approval = $this->service->preDecide($id, $request->get('comment'));

            return response()->json([
                'success' => true,
                'message' => '전결 처리되었습니다.',
                'data' => $approval,
            ]);
        } catch (\InvalidArgumentException $e) {
            return response()->json([
                'success' => false,
                'message' => $e->getMessage(),
            ], 400);
        }
    }

    /**
     * 복사 재기안
     */
    public function copyForRedraft(int $id): JsonResponse
    {
        try {
            $approval = $this->service->copyForRedraft($id);

            return response()->json([
                'success' => true,
                'message' => '문서가 복사되었습니다.',
                'data' => $approval,
            ]);
        } catch (\InvalidArgumentException $e) {
            return response()->json([
                'success' => false,
                'message' => $e->getMessage(),
            ], 400);
        }
    }

    /**
     * 참조 열람 추적
     */
    public function markAsRead(int $id): JsonResponse
    {
        $this->service->markAsRead($id);

        return response()->json([
            'success' => true,
            'message' => '열람 처리되었습니다.',
        ]);
    }

    // =========================================================================
    // 유틸
    // =========================================================================

    /**
     * 결재선 템플릿 목록
     */
    public function lines(): JsonResponse
    {
        $lines = $this->service->getApprovalLines();

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

    /**
     * 결재선 템플릿 생성
     */
    public function storeLine(Request $request): JsonResponse
    {
        $request->validate([
            'name' => 'required|string|max:100',
            'steps' => 'required|array|min:1',
            'steps.*.user_id' => 'required|exists:users,id',
            'steps.*.step_type' => 'required|in:approval,agreement,reference',
            'is_default' => 'boolean',
        ]);

        $line = $this->service->createLine($request->all());

        return response()->json([
            'success' => true,
            'message' => '결재선이 저장되었습니다.',
            'data' => $line,
        ], 201);
    }

    /**
     * 결재선 템플릿 수정
     */
    public function updateLine(Request $request, int $id): JsonResponse
    {
        $request->validate([
            'name' => 'required|string|max:100',
            'steps' => 'required|array|min:1',
            'steps.*.user_id' => 'required|exists:users,id',
            'steps.*.step_type' => 'required|in:approval,agreement,reference',
            'is_default' => 'boolean',
        ]);

        $line = $this->service->updateLine($id, $request->all());

        return response()->json([
            'success' => true,
            'message' => '결재선이 수정되었습니다.',
            'data' => $line,
        ]);
    }

    /**
     * 결재선 템플릿 삭제
     */
    public function destroyLine(int $id): JsonResponse
    {
        $this->service->deleteLine($id);

        return response()->json([
            'success' => true,
            'message' => '결재선이 삭제되었습니다.',
        ]);
    }

    /**
     * 지출결의서 이력 (불러오기용)
     */
    public function expenseHistory(Request $request): JsonResponse
    {
        $tenantId = session('selected_tenant_id');

        $approvals = \App\Models\Approvals\Approval::where('tenant_id', $tenantId)
            ->where('drafter_id', auth()->id())
            ->whereHas('form', fn ($q) => $q->where('code', 'expense'))
            ->whereIn('status', ['draft', 'pending', 'approved', 'rejected', 'cancelled'])
            ->whereNotNull('content')
            ->orderByDesc('created_at')
            ->limit(30)
            ->get(['id', 'title', 'content', 'status', 'created_at']);

        $data = $approvals->map(fn ($a) => [
            'id' => $a->id,
            'title' => $a->title,
            'status' => $a->status,
            'status_label' => $a->status_label,
            'total_amount' => $a->content['total_amount'] ?? 0,
            'expense_type' => $a->content['expense_type'] ?? '',
            'created_at' => $a->created_at->format('Y-m-d'),
            'content' => $a->content,
        ]);

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

    /**
     * 양식 목록
     */
    public function forms(): JsonResponse
    {
        $forms = $this->service->getApprovalForms();

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

    /**
     * 미처리 건수
     */
    public function badgeCounts(): JsonResponse
    {
        $counts = $this->service->getBadgeCounts(auth()->id());

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

    /**
     * 완료함 읽음 처리 (일괄)
     */
    public function markCompletedAsRead(): JsonResponse
    {
        $count = $this->service->markCompletedAsRead(auth()->id());

        return response()->json([
            'success' => true,
            'message' => $count > 0 ? "{$count}건 읽음 처리되었습니다." : '새로운 완료 건이 없습니다.',
            'data' => ['marked_count' => $count],
        ]);
    }

    /**
     * 개별 문서 기안자 읽음 처리
     */
    public function markReadSingle(int $id): JsonResponse
    {
        $approval = $this->service->getApproval($id);

        if ($approval->drafter_id === auth()->id() && ! $approval->drafter_read_at) {
            $approval->update(['drafter_read_at' => now()]);
        }

        return response()->json(['success' => true]);
    }

    // =========================================================================
    // 첨부파일
    // =========================================================================

    /**
     * 첨부파일 업로드
     */
    public function uploadFile(Request $request, GoogleCloudStorageService $gcs): JsonResponse
    {
        $request->validate([
            'file' => 'required|file|max:20480',
        ]);

        $file = $request->file('file');
        $tenantId = session('selected_tenant_id');
        $storedName = Str::random(40).'.'.$file->getClientOriginalExtension();
        $storagePath = "approvals/{$tenantId}/{$storedName}";

        Storage::disk('tenant')->put($storagePath, file_get_contents($file));

        $gcsUri = null;
        $gcsObjectName = null;
        if ($gcs->isAvailable()) {
            $gcsObjectName = $storagePath;
            $gcsUri = $gcs->upload($file->getRealPath(), $gcsObjectName);
        }

        $fileRecord = File::create([
            'tenant_id' => $tenantId,
            'document_type' => 'approval_attachment',
            'display_name' => $file->getClientOriginalName(),
            'original_name' => $file->getClientOriginalName(),
            'stored_name' => $storedName,
            'file_path' => $storagePath,
            'mime_type' => $file->getMimeType(),
            'file_size' => $file->getSize(),
            'file_type' => strtolower($file->getClientOriginalExtension()),
            'gcs_object_name' => $gcsObjectName,
            'gcs_uri' => $gcsUri,
            'is_temp' => true,
            'uploaded_by' => auth()->id(),
            'created_by' => auth()->id(),
        ]);

        return response()->json([
            'success' => true,
            'data' => [
                'id' => $fileRecord->id,
                'name' => $fileRecord->original_name,
                'size' => $fileRecord->file_size,
                'mime_type' => $fileRecord->mime_type,
            ],
        ]);
    }

    /**
     * 첨부파일 삭제
     */
    public function deleteFile(int $fileId): JsonResponse
    {
        $file = File::where('id', $fileId)
            ->where('uploaded_by', auth()->id())
            ->first();

        if (! $file) {
            return response()->json(['success' => false, 'message' => '파일을 찾을 수 없습니다.'], 404);
        }

        if ($file->existsInStorage()) {
            Storage::disk('tenant')->delete($file->file_path);
        }

        $file->forceDelete();

        return response()->json(['success' => true, 'message' => '파일이 삭제되었습니다.']);
    }

    /**
     * 첨부파일 다운로드
     */
    public function downloadFile(int $fileId)
    {
        $file = File::findOrFail($fileId);

        if (Storage::disk('tenant')->exists($file->file_path)) {
            return Storage::disk('tenant')->download($file->file_path, $file->original_name);
        }

        abort(404, '파일을 찾을 수 없습니다.');
    }
}
