<?php

declare(strict_types=1);

namespace App\Http\Controllers\Api\Admin;

use App\Http\Controllers\Api\Admin\Concerns\AuthorizesOwnedResources;
use App\Http\Controllers\Controller;
use App\Models\OperationLog;
use App\Models\Question;
use App\Models\QuestionBank;
use App\Services\QuestionImportService;
use App\Support\ApiResponse;
use hg\apidoc\annotation as Apidoc;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

#[Apidoc\Group('后台')]
#[Apidoc\Title('题目管理')]
#[Apidoc\RouteMiddleware(['jwt.auth'])]
final class QuestionController extends Controller
{
    use AuthorizesOwnedResources;

    #[Apidoc\Title('题目列表')]
    #[Apidoc\Url('/admin/questions')]
    #[Apidoc\Method('GET')]
    #[Apidoc\RouteMiddleware(['permission:questions'])]
    public function index(Request $request): JsonResponse
    {
        $query = Question::query()->with(['bank', 'options', 'tags'])->latest();
        if ($request->user()->role !== 'admin') {
            $query->whereHas('bank', fn ($bankQuery) => $bankQuery->where('owner_id', $request->user()->id));
        }
        if ($bankId = $request->query('question_bank_id')) {
            $query->where('question_bank_id', $bankId);
        }
        if ($type = $request->query('type')) {
            $query->where('type', $type);
        }
        if ($keyword = $request->query('keyword')) {
            $query->where('content', 'like', '%'.$keyword.'%');
        }
        if ($request->filled('is_active')) {
            $query->where('is_active', $request->boolean('is_active'));
        }

        return ApiResponse::page($query->paginate((int) $request->query('per_page', 20)));
    }

    #[Apidoc\Title('创建题目')]
    #[Apidoc\Url('/admin/questions')]
    #[Apidoc\Method('POST')]
    #[Apidoc\RouteMiddleware(['permission:questions.import'])]
    public function store(Request $request, QuestionImportService $service): JsonResponse
    {
        $data = $request->validate([
            'question_bank_id' => ['required', 'exists:question_banks,id'],
            'content' => ['required', 'string'],
            'type' => ['required', 'in:single,multiple,judge,blank'],
            'explanation' => ['nullable', 'string'],
            'options' => ['array'],
            'answers' => ['array'],
        ]);

        $bank = QuestionBank::findOrFail($data['question_bank_id']);
        $this->authorizeBankOwner($request, $bank);
        $job = $service->importRows($bank, $request->user(), [[
            'content' => $data['content'],
            'type' => $data['type'],
            'explanation' => $data['explanation'] ?? null,
            'options' => $data['options'] ?? [],
            'answer' => implode('|', $data['answers'] ?? []),
        ]], 'manual');

        return ApiResponse::success($job->load('bank'), '题目已创建');
    }

    #[Apidoc\Title('批量导入题目')]
    #[Apidoc\Url('/admin/banks/{bank}/imports')]
    #[Apidoc\Method('POST')]
    #[Apidoc\RouteMiddleware(['permission:questions.import'])]
    public function import(Request $request, mixed $bank, QuestionImportService $service): JsonResponse
    {
        $bank = $this->resolveBank($bank);
        $this->authorizeBankOwner($request, $bank);
        $request->validate([
            'file' => ['required', 'file', 'mimes:json,xlsx,xls,csv,txt'],
        ]);

        $job = $service->importUploadedFile($bank, $request->user(), $request->file('file'));
        OperationLog::create([
            'user_id' => $request->user()->id,
            'action' => 'questions.imported',
            'target_type' => QuestionBank::class,
            'target_id' => $bank->id,
            'ip' => $request->ip(),
            'payload' => ['job_id' => $job->id, 'success_count' => $job->success_count, 'skipped_count' => $job->skipped_count],
        ]);

        return ApiResponse::success($job, '导入完成');
    }

    #[Apidoc\Title('校验导入题目')]
    #[Apidoc\Url('/admin/banks/{bank}/imports/validate')]
    #[Apidoc\Method('POST')]
    #[Apidoc\RouteMiddleware(['permission:questions.import'])]
    public function validateImport(Request $request, mixed $bank, QuestionImportService $service): JsonResponse
    {
        $bank = $this->resolveBank($bank);
        $this->authorizeBankOwner($request, $bank);
        $request->validate([
            'file' => ['required', 'file', 'mimes:json,xlsx,xls,csv,txt'],
        ]);

        $prepared = $service->prepareUploadedFile($request->file('file'));

        return ApiResponse::success([
            ...$service->validateRows($prepared['rows'], $bank),
            'type' => $prepared['type'],
            'file_path' => $prepared['path'],
        ], '校验完成');
    }

    #[Apidoc\Title('提交已校验题目')]
    #[Apidoc\Url('/admin/banks/{bank}/imports/rows')]
    #[Apidoc\Method('POST')]
    #[Apidoc\RouteMiddleware(['permission:questions.import'])]
    public function importRows(Request $request, mixed $bank, QuestionImportService $service): JsonResponse
    {
        $bank = $this->resolveBank($bank);
        $this->authorizeBankOwner($request, $bank);
        $data = $request->validate([
            'rows' => ['required', 'array'],
            'type' => ['nullable', 'string'],
            'file_path' => ['nullable', 'string'],
        ]);

        $validation = $service->validateRows($data['rows'], $bank);
        if (! $validation['valid']) {
            return ApiResponse::success($validation, '校验未通过');
        }

        $job = $service->importRows($bank, $request->user(), $data['rows'], $data['type'] ?? 'manual', $data['file_path'] ?? null);

        return ApiResponse::success($job, '导入完成');
    }

    #[Apidoc\Title('校验已编辑题目')]
    #[Apidoc\Url('/admin/banks/{bank}/imports/rows/validate')]
    #[Apidoc\Method('POST')]
    #[Apidoc\RouteMiddleware(['permission:questions.import'])]
    public function validateRows(Request $request, mixed $bank, QuestionImportService $service): JsonResponse
    {
        $bank = $this->resolveBank($bank);
        $this->authorizeBankOwner($request, $bank);
        $data = $request->validate([
            'rows' => ['required', 'array'],
        ]);

        return ApiResponse::success($service->validateRows($data['rows'], $bank), '校验完成');
    }

    private function resolveBank(mixed $bank): QuestionBank
    {
        if ($bank instanceof QuestionBank && $bank->exists) {
            return $bank;
        }

        return QuestionBank::query()->findOrFail((int) $bank);
    }

    #[Apidoc\Title('更新题目状态')]
    #[Apidoc\Url('/admin/questions/{question}')]
    #[Apidoc\Method('PUT')]
    #[Apidoc\RouteMiddleware(['permission:banks.update'])]
    public function update(Request $request, mixed $question): JsonResponse
    {
        $question = $this->resolveQuestion($question);
        $this->authorizeQuestionOwner($request, $question);
        $data = $request->validate([
            'content' => ['sometimes', 'string'],
            'type' => ['sometimes', 'in:single,multiple,judge,blank'],
            'explanation' => ['nullable', 'string'],
            'is_active' => ['sometimes', 'boolean'],
            'options' => ['sometimes', 'array'],
            'options.*.text' => ['nullable', 'string'],
            'options.*.content' => ['nullable', 'string'],
            'options.*.correct' => ['nullable', 'boolean'],
            'options.*.is_correct' => ['nullable', 'boolean'],
            'answers' => ['sometimes', 'array'],
        ]);

        DB::transaction(function () use ($question, $data): void {
            $question->update(collect($data)->only(['content', 'type', 'explanation', 'is_active'])->all());

            if (array_key_exists('answers', $data)) {
                $question->update(['answers' => array_values(array_filter($data['answers']))]);
            }

            if (array_key_exists('options', $data)) {
                $question->options()->delete();
                foreach ($data['options'] as $sort => $option) {
                    $content = trim((string) ($option['text'] ?? $option['content'] ?? ''));
                    if ($content === '') {
                        continue;
                    }

                    $question->options()->create([
                        'content' => $content,
                        'is_correct' => (bool) ($option['correct'] ?? $option['is_correct'] ?? false),
                        'sort' => $sort,
                    ]);
                }
            }
        });

        return ApiResponse::success($question->fresh('options'), '题目已更新');
    }

    #[Apidoc\Title('删除题目')]
    #[Apidoc\Url('/admin/questions/{question}')]
    #[Apidoc\Method('DELETE')]
    #[Apidoc\RouteMiddleware(['permission:banks.update'])]
    public function destroy(Request $request, mixed $question): JsonResponse
    {
        $question = $this->resolveQuestion($question);
        $this->authorizeQuestionOwner($request, $question);
        $question->delete();
        OperationLog::create([
            'user_id' => $request->user()->id,
            'action' => 'question.deleted',
            'target_type' => Question::class,
            'target_id' => $question->id,
            'ip' => $request->ip(),
            'payload' => ['question_bank_id' => $question->question_bank_id],
        ]);

        return ApiResponse::success(null, '题目已删除');
    }

    private function resolveQuestion(mixed $question): Question
    {
        if ($question instanceof Question && $question->exists) {
            return $question;
        }

        return Question::query()->findOrFail((int) $question);
    }
}
