<?php

namespace App\Services\Sales;

use App\Models\Interview\InterviewAnswer;
use App\Models\Interview\InterviewAttachment;
use App\Models\Interview\InterviewCategory;
use App\Models\Interview\InterviewKnowledge;
use App\Models\Interview\InterviewProject;
use App\Models\Interview\InterviewQuestion;
use App\Models\Interview\InterviewSession;
use App\Models\Interview\InterviewTemplate;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;

class InterviewScenarioService
{
    // ============================================================
    // 카테고리 CRUD
    // ============================================================

    public function getCategories()
    {
        return InterviewCategory::whereNull('parent_id')
            ->with(['children' => fn ($q) => $q->orderBy('sort_order')->orderBy('id')])
            ->orderBy('sort_order')
            ->orderBy('id')
            ->get();
    }

    public function createCategory(array $data): InterviewCategory
    {
        $tenantId = session('selected_tenant_id', 1);
        $parentId = $data['parent_id'] ?? null;

        $query = InterviewCategory::query();
        if ($parentId) {
            $query->where('parent_id', $parentId);
        } else {
            $query->whereNull('parent_id');
        }
        $maxSort = $query->max('sort_order') ?? 0;

        return InterviewCategory::create([
            'tenant_id' => $tenantId,
            'parent_id' => $parentId,
            'name' => $data['name'],
            'description' => $data['description'] ?? null,
            'sort_order' => $maxSort + 1,
            'is_active' => true,
            'created_by' => auth()->id(),
            'updated_by' => auth()->id(),
        ]);
    }

    public function updateCategory(int $id, array $data): InterviewCategory
    {
        $category = InterviewCategory::findOrFail($id);
        $category->update([
            'name' => $data['name'],
            'description' => $data['description'] ?? null,
            'updated_by' => auth()->id(),
        ]);

        return $category->fresh();
    }

    public function deleteCategory(int $id): void
    {
        $category = InterviewCategory::findOrFail($id);
        $category->update(['deleted_by' => auth()->id()]);
        $category->delete();
    }

    // ============================================================
    // 템플릿(항목) CRUD
    // ============================================================

    public function createTemplate(array $data): InterviewTemplate
    {
        $tenantId = session('selected_tenant_id', 1);
        $maxSort = InterviewTemplate::where('interview_category_id', $data['interview_category_id'])
            ->max('sort_order') ?? 0;

        return InterviewTemplate::create([
            'tenant_id' => $tenantId,
            'interview_category_id' => $data['interview_category_id'],
            'name' => $data['name'],
            'description' => $data['description'] ?? null,
            'sort_order' => $maxSort + 1,
            'is_active' => true,
            'created_by' => auth()->id(),
            'updated_by' => auth()->id(),
        ]);
    }

    public function updateTemplate(int $id, array $data): InterviewTemplate
    {
        $template = InterviewTemplate::findOrFail($id);
        $template->update([
            'name' => $data['name'],
            'description' => $data['description'] ?? null,
            'updated_by' => auth()->id(),
        ]);

        return $template->fresh();
    }

    public function deleteTemplate(int $id): void
    {
        $template = InterviewTemplate::findOrFail($id);
        $template->update(['deleted_by' => auth()->id()]);
        $template->delete();
    }

    // ============================================================
    // 질문 CRUD
    // ============================================================

    public function createQuestion(array $data): InterviewQuestion
    {
        $tenantId = session('selected_tenant_id', 1);
        $maxSort = InterviewQuestion::where('interview_template_id', $data['interview_template_id'])
            ->max('sort_order') ?? 0;

        return InterviewQuestion::create([
            'tenant_id' => $tenantId,
            'interview_template_id' => $data['interview_template_id'],
            'question_text' => $data['question_text'],
            'question_type' => $data['question_type'] ?? 'checkbox',
            'options' => $data['options'] ?? null,
            'ai_hint' => $data['ai_hint'] ?? null,
            'expected_format' => $data['expected_format'] ?? null,
            'depends_on' => $data['depends_on'] ?? null,
            'domain' => $data['domain'] ?? null,
            'is_required' => $data['is_required'] ?? false,
            'sort_order' => $maxSort + 1,
            'is_active' => true,
            'created_by' => auth()->id(),
            'updated_by' => auth()->id(),
        ]);
    }

    public function updateQuestion(int $id, array $data): InterviewQuestion
    {
        $question = InterviewQuestion::findOrFail($id);
        $question->update([
            'question_text' => $data['question_text'],
            'question_type' => $data['question_type'] ?? $question->question_type,
            'is_required' => $data['is_required'] ?? $question->is_required,
            'updated_by' => auth()->id(),
        ]);

        return $question->fresh();
    }

    public function deleteQuestion(int $id): void
    {
        $question = InterviewQuestion::findOrFail($id);
        $question->update(['deleted_by' => auth()->id()]);
        $question->delete();
    }

    // ============================================================
    // MD 파일 일괄 가져오기
    // ============================================================

    public function bulkImport(int $categoryId, array $templates): array
    {
        return DB::transaction(function () use ($categoryId, $templates) {
            $tenantId = session('selected_tenant_id', 1);
            $userId = auth()->id();
            $maxTemplateSort = InterviewTemplate::where('interview_category_id', $categoryId)
                ->max('sort_order') ?? 0;

            $createdTemplates = 0;
            $createdQuestions = 0;

            foreach ($templates as $tpl) {
                $maxTemplateSort++;
                $template = InterviewTemplate::create([
                    'tenant_id' => $tenantId,
                    'interview_category_id' => $categoryId,
                    'name' => $tpl['name'],
                    'sort_order' => $maxTemplateSort,
                    'is_active' => true,
                    'created_by' => $userId,
                    'updated_by' => $userId,
                ]);
                $createdTemplates++;

                $questionSort = 0;
                foreach ($tpl['questions'] as $questionText) {
                    $questionSort++;
                    InterviewQuestion::create([
                        'tenant_id' => $tenantId,
                        'interview_template_id' => $template->id,
                        'question_text' => $questionText,
                        'question_type' => 'checkbox',
                        'is_required' => false,
                        'sort_order' => $questionSort,
                        'is_active' => true,
                        'created_by' => $userId,
                        'updated_by' => $userId,
                    ]);
                    $createdQuestions++;
                }
            }

            return [
                'templates_created' => $createdTemplates,
                'questions_created' => $createdQuestions,
            ];
        });
    }

    // ============================================================
    // 전체 트리 조회
    // ============================================================

    public function getTree()
    {
        return InterviewCategory::whereNull('parent_id')
            ->with([
                'children' => fn ($q) => $q->orderBy('sort_order')->orderBy('id')
                    ->with(['templates' => fn ($q2) => $q2->orderBy('sort_order')->orderBy('id')
                        ->with(['questions' => fn ($q3) => $q3->orderBy('sort_order')->orderBy('id')]),
                    ]),
                'templates' => fn ($q) => $q->orderBy('sort_order')->orderBy('id')
                    ->with(['questions' => fn ($q2) => $q2->orderBy('sort_order')->orderBy('id')]),
            ])
            ->orderBy('sort_order')
            ->orderBy('id')
            ->get();
    }

    // ============================================================
    // 세션 관리
    // ============================================================

    public function getSessions(array $filters = [])
    {
        $query = InterviewSession::with(['category', 'interviewer'])
            ->orderByDesc('interview_date')
            ->orderByDesc('id');

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

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

        return $query->paginate(20);
    }

    public function startSession(array $data): InterviewSession
    {
        return DB::transaction(function () use ($data) {
            $tenantId = session('selected_tenant_id', 1);
            $categoryId = $data['interview_category_id'];

            // 카테고리의 모든 활성 템플릿과 질문 가져오기
            $templates = InterviewTemplate::where('interview_category_id', $categoryId)
                ->where('is_active', true)
                ->with(['questions' => function ($q) {
                    $q->where('is_active', true)->orderBy('sort_order');
                }])
                ->orderBy('sort_order')
                ->get();

            $totalQuestions = $templates->sum(fn ($t) => $t->questions->count());

            // 세션 생성
            $session = InterviewSession::create([
                'tenant_id' => $tenantId,
                'interview_category_id' => $categoryId,
                'interviewer_id' => auth()->id(),
                'interviewee_name' => $data['interviewee_name'] ?? null,
                'interviewee_company' => $data['interviewee_company'] ?? null,
                'interview_date' => $data['interview_date'] ?? now()->toDateString(),
                'status' => 'in_progress',
                'total_questions' => $totalQuestions,
                'answered_questions' => 0,
                'memo' => $data['memo'] ?? null,
                'created_by' => auth()->id(),
                'updated_by' => auth()->id(),
            ]);

            // 모든 질문에 대해 빈 답변 레코드 생성
            foreach ($templates as $template) {
                foreach ($template->questions as $question) {
                    InterviewAnswer::create([
                        'tenant_id' => $tenantId,
                        'interview_session_id' => $session->id,
                        'interview_question_id' => $question->id,
                        'interview_template_id' => $template->id,
                        'is_checked' => false,
                    ]);
                }
            }

            return $session;
        });
    }

    public function getSessionDetail(int $id)
    {
        return InterviewSession::with([
            'category',
            'interviewer',
            'answers' => function ($q) {
                $q->with(['question', 'template']);
            },
        ])->findOrFail($id);
    }

    public function toggleAnswer(array $data): InterviewAnswer
    {
        $answer = InterviewAnswer::where('interview_session_id', $data['session_id'])
            ->where('interview_question_id', $data['question_id'])
            ->firstOrFail();

        $answer->update([
            'is_checked' => ! $answer->is_checked,
            'answer_text' => $data['answer_text'] ?? $answer->answer_text,
            'memo' => $data['memo'] ?? $answer->memo,
        ]);

        // answered_questions 갱신
        $session = InterviewSession::findOrFail($data['session_id']);
        $answeredCount = InterviewAnswer::where('interview_session_id', $session->id)
            ->where('is_checked', true)
            ->count();
        $session->update([
            'answered_questions' => $answeredCount,
            'updated_by' => auth()->id(),
        ]);

        return $answer->fresh();
    }

    public function completeSession(int $id): InterviewSession
    {
        $session = InterviewSession::findOrFail($id);

        $answeredCount = InterviewAnswer::where('interview_session_id', $session->id)
            ->where('is_checked', true)
            ->count();

        $session->update([
            'status' => 'completed',
            'answered_questions' => $answeredCount,
            'completed_at' => now(),
            'updated_by' => auth()->id(),
        ]);

        return $session->fresh();
    }

    // ============================================================
    // 프로젝트 CRUD
    // ============================================================

    public function getProjects(array $filters = [])
    {
        $query = InterviewProject::with('creator')
            ->orderByDesc('id');

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

        if (! empty($filters['search'])) {
            $search = $filters['search'];
            $query->where(function ($q) use ($search) {
                $q->where('company_name', 'like', "%{$search}%")
                    ->orWhere('company_type', 'like', "%{$search}%");
            });
        }

        return $query->paginate(20);
    }

    public function getProject(int $id): InterviewProject
    {
        return InterviewProject::with([
            'categories.templates.questions',
            'attachments',
            'sessions',
        ])->findOrFail($id);
    }

    public function createProject(array $data): InterviewProject
    {
        $tenantId = session('selected_tenant_id', 1);

        return DB::transaction(function () use ($data, $tenantId) {
            $project = InterviewProject::create([
                'tenant_id' => $tenantId,
                'company_name' => $data['company_name'],
                'company_type' => $data['company_type'] ?? null,
                'contact_person' => $data['contact_person'] ?? null,
                'contact_info' => $data['contact_info'] ?? null,
                'status' => 'draft',
                'product_categories' => $data['product_categories'] ?? null,
                'progress_percent' => 0,
                'created_by' => auth()->id(),
                'updated_by' => auth()->id(),
            ]);

            // 마스터 질문 데이터에서 8개 도메인 카테고리 복제
            $this->cloneMasterQuestionsToProject($project);

            return $project->fresh();
        });
    }

    public function updateProject(int $id, array $data): InterviewProject
    {
        $project = InterviewProject::findOrFail($id);
        $project->update([
            ...$data,
            'updated_by' => auth()->id(),
        ]);

        return $project->fresh();
    }

    public function deleteProject(int $id): void
    {
        $project = InterviewProject::findOrFail($id);
        $project->update(['deleted_by' => auth()->id()]);
        $project->delete();
    }

    /**
     * 마스터 질문 데이터를 프로젝트에 복제
     */
    private function cloneMasterQuestionsToProject(InterviewProject $project): void
    {
        $tenantId = $project->tenant_id;
        $userId = auth()->id();

        // 루트 마스터 카테고리 (parent_id=null, project=null)
        $masterRoots = InterviewCategory::withoutGlobalScopes()
            ->where('tenant_id', $tenantId)
            ->whereNull('interview_project_id')
            ->whereNull('parent_id')
            ->with(['children.templates.questions', 'templates.questions'])
            ->orderBy('sort_order')
            ->get();

        foreach ($masterRoots as $masterRoot) {
            // 루트 카테고리 복제
            $newRoot = InterviewCategory::create([
                'tenant_id' => $tenantId,
                'interview_project_id' => $project->id,
                'parent_id' => null,
                'name' => $masterRoot->name,
                'description' => $masterRoot->description,
                'domain' => $masterRoot->domain,
                'sort_order' => $masterRoot->sort_order,
                'is_active' => true,
                'created_by' => $userId,
                'updated_by' => $userId,
            ]);

            // 루트의 직접 templates 복제
            $this->cloneTemplates($masterRoot->templates, $newRoot->id, $tenantId, $userId);

            // 자식 카테고리 복제
            foreach ($masterRoot->children as $masterChild) {
                $newChild = InterviewCategory::create([
                    'tenant_id' => $tenantId,
                    'interview_project_id' => $project->id,
                    'parent_id' => $newRoot->id,
                    'name' => $masterChild->name,
                    'description' => $masterChild->description,
                    'domain' => $masterChild->domain,
                    'sort_order' => $masterChild->sort_order,
                    'is_active' => true,
                    'created_by' => $userId,
                    'updated_by' => $userId,
                ]);

                $this->cloneTemplates($masterChild->templates, $newChild->id, $tenantId, $userId);
            }
        }
    }

    private function cloneTemplates($templates, int $categoryId, int $tenantId, ?int $userId): void
    {
        foreach ($templates as $masterTpl) {
            $newTpl = InterviewTemplate::create([
                'tenant_id' => $tenantId,
                'interview_category_id' => $categoryId,
                'name' => $masterTpl->name,
                'description' => $masterTpl->description,
                'sort_order' => $masterTpl->sort_order,
                'is_active' => true,
                'created_by' => $userId,
                'updated_by' => $userId,
            ]);

            foreach ($masterTpl->questions as $masterQ) {
                InterviewQuestion::create([
                    'tenant_id' => $tenantId,
                    'interview_template_id' => $newTpl->id,
                    'question_text' => $masterQ->question_text,
                    'question_type' => $masterQ->question_type,
                    'options' => $masterQ->options,
                    'ai_hint' => $masterQ->ai_hint,
                    'expected_format' => $masterQ->expected_format,
                    'depends_on' => $masterQ->depends_on,
                    'domain' => $masterQ->domain,
                    'is_required' => $masterQ->is_required,
                    'sort_order' => $masterQ->sort_order,
                    'is_active' => true,
                    'created_by' => $userId,
                    'updated_by' => $userId,
                ]);
            }
        }
    }

    /**
     * 프로젝트별 트리 조회
     */
    public function getProjectTree(int $projectId)
    {
        return InterviewCategory::where('interview_project_id', $projectId)
            ->whereNull('parent_id')
            ->with([
                'children' => fn ($q) => $q->orderBy('sort_order')->orderBy('id')
                    ->with(['templates' => fn ($q2) => $q2->orderBy('sort_order')->orderBy('id')
                        ->with(['questions' => fn ($q3) => $q3->orderBy('sort_order')->orderBy('id')]),
                    ]),
                'templates' => fn ($q) => $q->orderBy('sort_order')->orderBy('id')
                    ->with(['questions' => fn ($q2) => $q2->orderBy('sort_order')->orderBy('id')]),
            ])
            ->orderBy('sort_order')
            ->orderBy('id')
            ->get();
    }

    /**
     * 프로젝트 진행률 갱신
     */
    public function updateProjectProgress(int $projectId): InterviewProject
    {
        $project = InterviewProject::findOrFail($projectId);

        // 프로젝트 연결 카테고리의 모든 질문 수
        $totalQuestions = InterviewQuestion::whereHas('template.category', function ($q) use ($projectId) {
            $q->where('interview_project_id', $projectId);
        })->where('is_active', true)->count();

        if ($totalQuestions === 0) {
            $project->update(['progress_percent' => 0, 'updated_by' => auth()->id()]);

            return $project->fresh();
        }

        // 프로젝트 세션의 답변 완료 수
        $answeredQuestions = InterviewAnswer::whereHas('session', function ($q) use ($projectId) {
            $q->where('interview_project_id', $projectId);
        })->where('is_checked', true)->count();

        $progress = min(100, (int) round(($answeredQuestions / $totalQuestions) * 100));
        $project->update(['progress_percent' => $progress, 'updated_by' => auth()->id()]);

        return $project->fresh();
    }

    // ============================================================
    // 첨부파일 관리
    // ============================================================

    public function getAttachments(int $projectId)
    {
        return InterviewAttachment::where('interview_project_id', $projectId)
            ->with('creator')
            ->orderByDesc('id')
            ->get();
    }

    public function uploadAttachment(int $projectId, array $data, $file): InterviewAttachment
    {
        $tenantId = session('selected_tenant_id', 1);
        $path = $file->store("interviews/{$projectId}", 'local');

        return InterviewAttachment::create([
            'tenant_id' => $tenantId,
            'interview_project_id' => $projectId,
            'file_type' => $data['file_type'] ?? 'other',
            'file_name' => $file->getClientOriginalName(),
            'file_path' => $path,
            'file_size' => $file->getSize(),
            'mime_type' => $file->getMimeType(),
            'ai_analysis_status' => 'pending',
            'description' => $data['description'] ?? null,
            'created_by' => auth()->id(),
        ]);
    }

    public function deleteAttachment(int $id): void
    {
        $attachment = InterviewAttachment::findOrFail($id);

        if (Storage::disk('local')->exists($attachment->file_path)) {
            Storage::disk('local')->delete($attachment->file_path);
        }

        $attachment->delete();
    }

    // ============================================================
    // 지식 관리
    // ============================================================

    public function getKnowledge(int $projectId, array $filters = [])
    {
        $query = InterviewKnowledge::where('interview_project_id', $projectId)
            ->with('creator')
            ->orderByDesc('id');

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

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

        if (! empty($filters['min_confidence'])) {
            $query->where('confidence', '>=', (float) $filters['min_confidence']);
        }

        return $query->get();
    }

    public function createKnowledge(int $projectId, array $data): InterviewKnowledge
    {
        $tenantId = session('selected_tenant_id', 1);

        return InterviewKnowledge::create([
            'tenant_id' => $tenantId,
            'interview_project_id' => $projectId,
            'domain' => $data['domain'],
            'knowledge_type' => $data['knowledge_type'],
            'title' => $data['title'],
            'content' => $data['content'],
            'source_type' => $data['source_type'] ?? 'manual',
            'source_id' => $data['source_id'] ?? null,
            'confidence' => $data['confidence'] ?? 1.00,
            'is_verified' => $data['source_type'] === 'manual',
            'verified_by' => $data['source_type'] === 'manual' ? auth()->id() : null,
            'verified_at' => $data['source_type'] === 'manual' ? now() : null,
            'created_by' => auth()->id(),
        ]);
    }

    public function updateKnowledge(int $id, array $data): InterviewKnowledge
    {
        $knowledge = InterviewKnowledge::findOrFail($id);
        $knowledge->update($data);

        return $knowledge->fresh();
    }

    public function verifyKnowledge(int $id): InterviewKnowledge
    {
        $knowledge = InterviewKnowledge::findOrFail($id);
        $knowledge->update([
            'is_verified' => ! $knowledge->is_verified,
            'verified_by' => $knowledge->is_verified ? null : auth()->id(),
            'verified_at' => $knowledge->is_verified ? null : now(),
        ]);

        return $knowledge->fresh();
    }

    public function deleteKnowledge(int $id): void
    {
        $knowledge = InterviewKnowledge::findOrFail($id);
        $knowledge->delete();
    }

    // ============================================================
    // 답변 저장 (구조화 답변 포함)
    // ============================================================

    public function saveAnswer(array $data): InterviewAnswer
    {
        $answer = InterviewAnswer::where('interview_session_id', $data['session_id'])
            ->where('interview_question_id', $data['question_id'])
            ->firstOrFail();

        $updateData = [
            'is_checked' => $data['is_checked'] ?? $answer->is_checked,
        ];

        if (isset($data['answer_text'])) {
            $updateData['answer_text'] = $data['answer_text'];
        }
        if (isset($data['answer_data'])) {
            $updateData['answer_data'] = $data['answer_data'];
        }
        if (isset($data['attachments'])) {
            $updateData['attachments'] = $data['attachments'];
        }
        if (isset($data['memo'])) {
            $updateData['memo'] = $data['memo'];
        }

        $answer->update($updateData);

        // answered_questions 갱신
        $session = InterviewSession::findOrFail($data['session_id']);
        $answeredCount = InterviewAnswer::where('interview_session_id', $session->id)
            ->where('is_checked', true)
            ->count();
        $session->update([
            'answered_questions' => $answeredCount,
            'updated_by' => auth()->id(),
        ]);

        return $answer->fresh();
    }
}
