<?php

namespace App\Controllers;

use App\Models\ActivityLogModel;
use App\Models\DocumentModel;
use App\Models\DocumentTypeModel;
use App\Models\ReferenceModel;
use App\Models\CitationModel;
use App\Models\StudyProgramModel;
use App\Models\UserProfileModel;

class SubmissionController extends BaseController
{
    public function index()
    {
        $userId = auth()->user()->id;
        $docs   = model(DocumentModel::class)->getByAuthor($userId);

        return view('student/index', [
            'title' => 'Karya Saya',
            'docs'  => $docs,
        ]);
    }

    public function show(int $id)
    {
        $doc = $this->getOwnedDoc($id);
        $refs = model(ReferenceModel::class)->getForDocument($id);

        return view('student/show', [
            'title' => $doc['title'],
            'doc'   => $doc,
            'refs'  => $refs,
        ]);
    }

    public function create()
    {
        return view('student/form', [
            'title'    => 'Unggah Karya Baru',
            'doc'      => null,
            'types'    => model(DocumentTypeModel::class)->findAll(),
            'programs' => model(StudyProgramModel::class)->orderBy('name')->findAll(),
        ]);
    }

    public function store()
    {
        $rules = $this->validationRules(isNew: true);

        if (! $this->validate($rules)) {
            return redirect()->back()->withInput()->with('errors', $this->validator->getErrors());
        }

        $user    = auth()->user();
        $profile = model(UserProfileModel::class)->findByUserId($user->id);

        try {
            $file_path = $this->uploadPdf('file');
        } catch (\RuntimeException $e) {
            return redirect()->back()->withInput()->with('error', $e->getMessage());
        }

        $cover_img = null;
        if ($this->request->getFile('cover_img')?->isValid()) {
            try {
                $cover_img = $this->uploadCover('cover_img');
            } catch (\RuntimeException $e) {
                $this->deleteStoredFile('pdf', $file_path);
                return redirect()->back()->withInput()->with('error', $e->getMessage());
            }
        }

        $docModel = model(DocumentModel::class);
        $id = $docModel->insert([
            'title'            => trim($this->request->getPost('title')),
            'author_name'      => $profile['name'] ?? $user->username,
            'author_user_id'   => $user->id,
            'nim'              => $profile['identity_number'] ?? null,
            'study_program_id' => $this->request->getPost('study_program_id') ?: null,
            'document_type_id' => $this->request->getPost('document_type_id'),
            'year'             => $this->request->getPost('year'),
            'abstract'         => trim($this->request->getPost('abstract') ?? ''),
            'keywords'         => trim($this->request->getPost('keywords') ?? ''),
            'supervisor'       => trim($this->request->getPost('supervisor') ?? ''),
            'publisher'        => trim($this->request->getPost('publisher') ?? ''),
            'file_path'        => $file_path,
            'cover_img'        => $cover_img,
            'status'           => 'draft',
        ]);

        $this->saveReferences((int) $id);

        return redirect()->to('/my-works/' . $id)
            ->with('success', 'Karya berhasil disimpan sebagai draft.');
    }

    public function edit(int $id)
    {
        $doc = $this->getOwnedDoc($id, ['draft', 'revision']);

        return view('student/form', [
            'title'    => 'Edit Karya',
            'doc'      => $doc,
            'refs'     => model(ReferenceModel::class)->getForDocument($id),
            'types'    => model(DocumentTypeModel::class)->findAll(),
            'programs' => model(StudyProgramModel::class)->orderBy('name')->findAll(),
        ]);
    }

    public function update(int $id)
    {
        $doc   = $this->getOwnedDoc($id, ['draft', 'revision']);
        $rules = $this->validationRules(isNew: false);

        if (! $this->validate($rules)) {
            return redirect()->back()->withInput()->with('errors', $this->validator->getErrors());
        }

        $data = [
            'title'            => trim($this->request->getPost('title')),
            'study_program_id' => $this->request->getPost('study_program_id') ?: null,
            'document_type_id' => $this->request->getPost('document_type_id'),
            'year'             => $this->request->getPost('year'),
            'abstract'         => trim($this->request->getPost('abstract') ?? ''),
            'keywords'         => trim($this->request->getPost('keywords') ?? ''),
            'supervisor'       => trim($this->request->getPost('supervisor') ?? ''),
            'publisher'        => trim($this->request->getPost('publisher') ?? ''),
        ];

        // New PDF uploaded?
        if ($this->request->getFile('file')?->isValid()) {
            try {
                $data['file_path'] = $this->uploadPdf('file');
                $this->deleteStoredFile('pdf', $doc['file_path']);
            } catch (\RuntimeException $e) {
                return redirect()->back()->withInput()->with('error', $e->getMessage());
            }
        }

        // New cover?
        if ($this->request->getFile('cover_img')?->isValid()) {
            try {
                $data['cover_img'] = $this->uploadCover('cover_img');
                if (!empty($doc['cover_img'])) {
                    $this->deleteStoredFile('covers', $doc['cover_img']);
                }
            } catch (\RuntimeException $e) {
                return redirect()->back()->withInput()->with('error', $e->getMessage());
            }
        }

        model(DocumentModel::class)->update($id, $data);
        $this->saveReferences($id);

        return redirect()->to('/my-works/' . $id)
            ->with('success', 'Karya berhasil diperbarui.');
    }

    /** Submit draft for review */
    public function send(int $id)
    {
        $doc = $this->getOwnedDoc($id, ['draft', 'revision']);

        model(DocumentModel::class)->update($id, [
            'status'       => 'submitted',
            'submitted_at' => date('Y-m-d H:i:s'),
            'admin_note'   => null,
        ]);

        model(ActivityLogModel::class)->record('submit', auth()->user()->id, $id);

        return redirect()->to('/my-works/' . $id)
            ->with('success', 'Karya berhasil dikirim untuk ditinjau. Harap tunggu konfirmasi admin.');
    }

    public function delete(int $id)
    {
        $doc = $this->getOwnedDoc($id, ['draft', 'revision']);

        $this->deleteStoredFile('pdf', $doc['file_path']);
        if (!empty($doc['cover_img'])) {
            $this->deleteStoredFile('covers', $doc['cover_img']);
        }

        model(ReferenceModel::class)->deleteForDocument($id);
        model(DocumentModel::class)->delete($id);

        return redirect()->to('/my-works')->with('success', 'Karya berhasil dihapus.');
    }

    // ── Helpers ──────────────────────────────────────────────────────────────

    private function getOwnedDoc(int $id, array $allowedStatuses = []): array
    {
        $doc = model(DocumentModel::class)->getWithMeta($id);

        if (! $doc) {
            throw new \CodeIgniter\Exceptions\PageNotFoundException();
        }

        if ((int) $doc['author_user_id'] !== auth()->user()->id) {
            throw new \CodeIgniter\Exceptions\PageNotFoundException();
        }

        if (!empty($allowedStatuses) && ! in_array($doc['status'], $allowedStatuses, true)) {
            return redirect()->to('/my-works/' . $id)
                ->with('error', 'Karya tidak dapat diedit pada status ini.');
        }

        return $doc;
    }

    private function saveReferences(int $doc_id): void
    {
        $raw = $this->request->getPost('refs') ?? [];
        if (! is_array($raw)) return;

        $clean = [];
        foreach ($raw as $ref) {
            if (empty($ref['title']) && empty($ref['cited_document_id']) && empty($ref['raw_text'])) continue;
            $clean[] = $ref;
        }

        model(ReferenceModel::class)->saveForDocument($doc_id, $clean);
    }

    private function validationRules(bool $isNew): array
    {
        $rules = [
            'title'            => 'required|max_length[255]',
            'document_type_id' => 'required|is_natural_no_zero',
            'year'             => 'required|integer|greater_than[1900]|less_than_equal_to[' . date('Y') . ']',
        ];

        if ($isNew) {
            $rules['file'] = 'uploaded[file]|max_size[file,51200]';
        }

        return $rules;
    }
}
