<?php

namespace App\Controllers\Admin;

use App\Controllers\BaseController;
use App\Models\ActivityLogModel;
use App\Models\CitationModel;
use App\Models\DocumentModel;
use App\Models\DocumentTypeModel;
use App\Models\ReferenceModel;
use App\Models\StudyProgramModel;

class DocumentController extends BaseController
{
    public function index()
    {
        $filters = [
            'status'  => $this->request->getGet('status'),
            'type'    => $this->request->getGet('type'),
            'program' => $this->request->getGet('program'),
            'search'  => $this->request->getGet('q'),
            'page'    => $this->request->getGet('page') ?? 1,
        ];

        $result = model(DocumentModel::class)->getAllAdmin($filters, 20);

        return view('admin/documents/index', [
            'title'    => 'Dokumen',
            'result'   => $result,
            'filters'  => $filters,
            'types'    => model(DocumentTypeModel::class)->findAll(),
            'programs' => model(StudyProgramModel::class)->orderBy('name')->findAll(),
        ]);
    }

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

        return view('admin/documents/show', [
            'title' => 'Detail: ' . $doc['title'],
            'doc'   => $doc,
            'refs'  => $refs,
        ]);
    }

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

    public function store()
    {
        if (! $this->validate([
            'title'            => 'required|max_length[255]',
            'author_name'      => 'required|max_length[255]',
            'document_type_id' => 'required|is_natural_no_zero',
            'year'             => 'required|integer|greater_than[1900]',
            'file'             => 'uploaded[file]|max_size[file,51200]',
        ])) {
            return redirect()->back()->withInput()->with('errors', $this->validator->getErrors());
        }

        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());
            }
        }

        $status = $this->request->getPost('status') === 'published' ? 'published' : 'draft';

        $id = model(DocumentModel::class)->insert([
            'title'            => trim($this->request->getPost('title')),
            'author_name'      => trim($this->request->getPost('author_name')),
            'nim'              => trim($this->request->getPost('nim') ?? ''),
            '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'           => $status,
            'published_at'     => $status === 'published' ? date('Y-m-d H:i:s') : null,
        ]);

        return redirect()->to('/admin/documents/' . $id)
            ->with('success', 'Dokumen berhasil ditambahkan.');
    }

    public function edit(int $id)
    {
        $doc = $this->findOrFail($id);

        return view('admin/documents/form', [
            'title'    => 'Edit Dokumen',
            'doc'      => $doc,
            'types'    => model(DocumentTypeModel::class)->findAll(),
            'programs' => model(StudyProgramModel::class)->orderBy('name')->findAll(),
        ]);
    }

    public function update(int $id)
    {
        $doc = $this->findOrFail($id);

        if (! $this->validate([
            'title'            => 'required|max_length[255]',
            'author_name'      => 'required|max_length[255]',
            'document_type_id' => 'required|is_natural_no_zero',
            'year'             => 'required|integer|greater_than[1900]',
        ])) {
            return redirect()->back()->withInput()->with('errors', $this->validator->getErrors());
        }

        $data = [
            'title'            => trim($this->request->getPost('title')),
            'author_name'      => trim($this->request->getPost('author_name')),
            'nim'              => trim($this->request->getPost('nim') ?? ''),
            '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') ?? ''),
        ];

        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());
            }
        }

        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);

        return redirect()->to('/admin/documents/' . $id)
            ->with('success', 'Dokumen berhasil diperbarui.');
    }

    public function approve(int $id)
    {
        $doc = $this->findOrFail($id);

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

        // Activate internal citations
        model(CitationModel::class)->createFromDocument($id);

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

        return redirect()->to('/admin/documents/' . $id)
            ->with('success', 'Dokumen berhasil diterbitkan.');
    }

    public function reject(int $id)
    {
        $note = trim($this->request->getPost('admin_note') ?? '');

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

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

        return redirect()->to('/admin/documents/' . $id)
            ->with('success', 'Dokumen ditolak.');
    }

    public function requestRevision(int $id)
    {
        $note = trim($this->request->getPost('admin_note') ?? '');

        if (empty($note)) {
            return redirect()->back()->with('error', 'Catatan revisi wajib diisi.');
        }

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

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

        return redirect()->to('/admin/documents/' . $id)
            ->with('success', 'Permintaan revisi dikirim ke pengaju.');
    }

    public function unpublish(int $id)
    {
        // Reverse citations
        model(CitationModel::class)->removeFromDocument($id);

        model(DocumentModel::class)->update($id, [
            'status'       => 'draft',
            'published_at' => null,
        ]);

        return redirect()->to('/admin/documents/' . $id)
            ->with('success', 'Dokumen ditarik dari publikasi.');
    }

    public function delete(int $id)
    {
        $doc = $this->findOrFail($id);

        model(CitationModel::class)->removeFromDocument($id);
        model(ReferenceModel::class)->deleteForDocument($id);
        $this->deleteStoredFile('pdf', $doc['file_path']);
        if (!empty($doc['cover_img'])) $this->deleteStoredFile('covers', $doc['cover_img']);
        model(DocumentModel::class)->delete($id);

        return redirect()->to('/admin/documents')->with('success', 'Dokumen dihapus.');
    }

    private function findOrFail(int $id): array
    {
        $doc = model(DocumentModel::class)->getWithMeta($id);
        if (! $doc) throw new \CodeIgniter\Exceptions\PageNotFoundException();
        return $doc;
    }
}
