<?php

namespace App\Services\Exams;

use App\Models\ClassSection;
use App\Models\ExamDraft;
use Illuminate\Support\Facades\DB;

class ExamDraftAdminService
{
    public function __construct(
        private ExamDraftConfigService $configService,
        private ExamDraftFileService $fileService
    ) {
    }

    public function list(): array
    {
        $context = $this->configService->context();
        $teacherUserColumn = (string) ($context['teacher_user_column'] ?? '');
        $adminUserColumn = (string) ($context['admin_user_column'] ?? '');

        $draftsQuery = DB::table('exam_drafts as ed')
            ->leftJoin('classSection as cs', 'cs.class_section_id', '=', 'ed.class_section_id')
            ->select(
                'ed.*',
                'cs.class_section_name',
            );

        if ($teacherUserColumn !== '') {
            $draftsQuery
                ->leftJoin('users as u', "u.id", '=', "ed.{$teacherUserColumn}")
                ->addSelect(
                    'u.firstname as teacher_first',
                    'u.lastname as teacher_last'
                );
        } else {
            $draftsQuery->addSelect(
                DB::raw('NULL as teacher_first'),
                DB::raw('NULL as teacher_last')
            );
        }

        if ($adminUserColumn !== '') {
            $draftsQuery
                ->leftJoin('users as a', 'a.id', '=', "ed.{$adminUserColumn}")
                ->addSelect(
                    'a.firstname as admin_first',
                    'a.lastname as admin_last'
                );
        } else {
            $draftsQuery->addSelect(
                DB::raw('NULL as admin_first'),
                DB::raw('NULL as admin_last')
            );
        }

        $drafts = $draftsQuery
            ->orderByDesc('ed.created_at')
            ->get()
            ->map(fn ($r) => (array) $r)
            ->all();

        $classSections = ClassSection::query()
            ->select('class_section_id', 'class_section_name')
            ->whereExists(function ($query) use ($context) {
                $query->selectRaw('1')
                    ->from('student_class as sc')
                    ->join('students as s', 's.id', '=', 'sc.student_id')
                    ->whereColumn('sc.class_section_id', 'classSection.class_section_id')
                    ->where('s.is_active', 1);

                $schoolYear = (string) ($context['school_year'] ?? '');
                if ($schoolYear !== '') {
                    $query->where('sc.school_year', $schoolYear);
                }
            })
            ->orderBy('class_section_name')
            ->get()
            ->toArray();

        $legacyByClass = [];
        if ($context['has_legacy'] ?? false) {
            foreach ($drafts as $row) {
                $isLegacy = !empty($row['is_legacy']);
                if (!$isLegacy) {
                    continue;
                }
                $cid = (int) ($row['class_section_id'] ?? 0);
                if (!isset($legacyByClass[$cid])) {
                    $legacyByClass[$cid] = [
                        'class_section_id' => $cid,
                        'class_section_name' => $row['class_section_name'] ?? 'Class ' . $cid,
                        'items' => [],
                    ];
                }
                $legacyByClass[$cid]['items'][] = $row;
            }
        }

        return [
            'drafts' => $drafts,
            'classSections' => $classSections,
            'legacyByClass' => $legacyByClass,
            'examTypes' => ExamDraftConfigService::EXAM_TYPES,
            'statusOptions' => ExamDraftConfigService::STATUS_OPTIONS,
            'schoolYear' => (string) ($context['school_year'] ?? ''),
            'semester' => (string) ($context['semester'] ?? ''),
            'allowedExtensions' => ExamDraftConfigService::ADMIN_ALLOWED_EXTENSIONS,
            'maxUploadBytes' => ExamDraftConfigService::MAX_UPLOAD_BYTES,
        ];
    }

    public function uploadLegacy(int $adminId, array $payload, \Illuminate\Http\UploadedFile $file): array
    {
        $context = $this->configService->context();
        $adminUserColumn = (string) ($context['admin_user_column'] ?? '');
        $classSectionId = (int) ($payload['class_section_id'] ?? 0);
        $schoolYear = trim((string) ($payload['school_year'] ?? $context['school_year'] ?? ''));
        $semester = trim((string) ($payload['semester'] ?? $context['semester'] ?? ''));
        $examType = trim((string) ($payload['exam_type'] ?? ''));

        if ($classSectionId <= 0 || $schoolYear === '' || $semester === '') {
            return ['ok' => false, 'message' => 'Select class section, school year, and semester.'];
        }

        $stored = $this->fileService->storeUploadedFile(
            $file,
            ExamDraftConfigService::FINAL_UPLOAD_DIR,
            ExamDraftConfigService::ADMIN_ALLOWED_EXTENSIONS,
            ExamDraftConfigService::MAX_UPLOAD_BYTES
        );
        if ($stored === null) {
            return ['ok' => false, 'message' => 'File type not allowed or upload failed.'];
        }

        $pdfName = $stored['extension'] === 'pdf'
            ? $stored['stored']
            : $this->fileService->ensurePdfExists(
                $stored['stored'],
                $stored['extension'],
                ExamDraftConfigService::FINAL_UPLOAD_DIR
            );

        if ($pdfName === null) {
            return ['ok' => false, 'message' => 'Unable to convert the uploaded exam to PDF.'];
        }

        $finalFilename = $stored['extension'] === 'pdf'
            ? $stored['original']
            : (pathinfo($stored['original'], PATHINFO_FILENAME) . '.pdf');

        $payload = [
            'class_section_id' => $classSectionId,
            'semester' => ucfirst(strtolower($semester)),
            'school_year' => $schoolYear,
            'exam_type' => $examType !== '' ? $examType : null,
            'draft_title' => $examType !== '' ? $examType : 'Legacy Exam',
            'final_file' => $pdfName,
            'status' => 'finalized',
            'version' => 1,
        ];

        if ($context['has_teacher_id'] ?? false) {
            $payload['teacher_id'] = $adminId;
        }
        if ($context['has_author_id'] ?? false) {
            $payload['author_id'] = $adminId;
        }

        if ($context['has_final_filename'] ?? false) {
            $payload['final_filename'] = $finalFilename;
        }
        if ($context['has_admin_id'] ?? false) {
            $payload['admin_id'] = $adminId;
        } elseif ($adminUserColumn === 'reviewer_id') {
            $payload['reviewer_id'] = $adminId;
        }
        if ($context['has_reviewed_at'] ?? false) {
            $payload['reviewed_at'] = now();
        }

        if ($context['has_legacy'] ?? false) {
            $payload['is_legacy'] = 1;
        }

        if ($context['has_final_pdf'] ?? false) {
            $payload['final_pdf_file'] = $pdfName;
        }

        $draft = ExamDraft::query()->create($payload);

        return ['ok' => true, 'draft' => $draft->toArray()];
    }

    public function review(int $adminId, array $payload, ?\Illuminate\Http\UploadedFile $file): array
    {
        $draftId = (int) ($payload['draft_id'] ?? 0);
        if ($draftId <= 0) {
            return ['ok' => false, 'message' => 'Invalid submission selected.'];
        }

        $draft = ExamDraft::query()->find($draftId);
        if (!$draft) {
            return ['ok' => false, 'message' => 'Submission not found.'];
        }

        $comments = trim((string) ($payload['admin_comments'] ?? ''));
        $statusInput = trim((string) ($payload['review_status'] ?? ''));
        $currentStatus = (string) ($draft->status ?? 'draft');
        $status = $this->normalizeStatus($statusInput !== '' ? $statusInput : $currentStatus, $currentStatus);
        if (!in_array($status, ExamDraftConfigService::STATUS_OPTIONS, true)) {
            $status = 'reviewed';
        }

        $context = $this->configService->context();

        $update = [
            'status' => $status,
        ];

        if ($context['has_admin_comments'] ?? false) {
            $update['admin_comments'] = $comments !== '' ? $comments : null;
        } elseif ($context['has_reviewer_comments'] ?? false) {
            $update['reviewer_comments'] = $comments !== '' ? $comments : null;
        }
        if ($context['has_admin_id'] ?? false) {
            $update['admin_id'] = $adminId;
        } elseif (($context['admin_user_column'] ?? null) === 'reviewer_id') {
            $update['reviewer_id'] = $adminId;
        }
        if ($context['has_reviewed_at'] ?? false) {
            $update['reviewed_at'] = now();
        }

        if ($file) {
            $stored = $this->fileService->storeUploadedFile(
                $file,
                ExamDraftConfigService::FINAL_UPLOAD_DIR,
                ExamDraftConfigService::ADMIN_ALLOWED_EXTENSIONS,
                ExamDraftConfigService::MAX_UPLOAD_BYTES
            );
            if ($stored === null) {
                return ['ok' => false, 'message' => 'Unable to store the final draft.'];
            }
            $update['final_file'] = $stored['stored'];
            if ($context['has_final_filename'] ?? false) {
                $update['final_filename'] = $stored['original'];
            }
            $pdfName = $this->fileService->ensurePdfExists(
                $stored['stored'],
                $stored['extension'],
                ExamDraftConfigService::FINAL_UPLOAD_DIR
            );
            if ($pdfName !== null && ($this->configService->context()['has_final_pdf'] ?? false)) {
                $update['final_pdf_file'] = $pdfName;
            }
        } elseif ($status === 'finalized' && !empty($draft->teacher_file ?: $draft->author_file)) {
            $copied = $this->fileService->copyDraftToFinal(
                (string) ($draft->teacher_file ?? $draft->author_file),
                ExamDraftConfigService::TEACHER_UPLOAD_DIR,
                ExamDraftConfigService::FINAL_UPLOAD_DIR
            );
            if ($copied !== null) {
                $update['final_file'] = $copied;
                if ($context['has_final_filename'] ?? false) {
                    $update['final_filename'] = $draft->teacher_filename ?? $draft->author_filename ?? $draft->teacher_file ?? $draft->author_file;
                }
                $pdfName = $this->fileService->ensurePdfExists(
                    $copied,
                    pathinfo($copied, PATHINFO_EXTENSION),
                    ExamDraftConfigService::FINAL_UPLOAD_DIR
                );
                if ($pdfName !== null && ($context['has_final_pdf'] ?? false)) {
                    $update['final_pdf_file'] = $pdfName;
                }
            }
        }

        if ($status === 'finalized' && ($context['has_legacy'] ?? false)) {
            $update['is_legacy'] = 1;
        }

        $draft->update($update);

        return ['ok' => true, 'draft' => $draft->fresh()->toArray()];
    }

    private function normalizeStatus(string $input, string $default): string
    {
        $input = strtolower(trim($input));
        $aliases = [
            'pending' => 'submitted',
            'final' => 'finalized',
            'approved' => 'finalized',
        ];
        if (isset($aliases[$input])) {
            $input = $aliases[$input];
        }
        return in_array($input, ExamDraftConfigService::STATUS_OPTIONS, true) ? $input : $default;
    }
}
