<?php

namespace App\Controllers;

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

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

        $result = model(DocumentModel::class)->getPublished($filters, 12);

        return view('public/index', [
            'title'    => 'Repositori Digital',
            'result'   => $result,
            'filters'  => $filters,
            'types'    => model(DocumentTypeModel::class)->findAll(),
            'programs' => model(StudyProgramModel::class)->orderBy('name')->findAll(),
            'years'    => $this->getYearList(),
        ]);
    }

    public function show(int $id)
    {
        $doc = model(DocumentModel::class)->getWithMeta($id);

        if (! $doc || $doc['status'] !== 'published') {
            throw new \CodeIgniter\Exceptions\PageNotFoundException();
        }

        model(DocumentModel::class)->incrementView($id);
        model(ActivityLogModel::class)->record('view', auth()->loggedIn() ? auth()->user()->id : null, $id);

        $references = model(ReferenceModel::class)->getForDocument($id);
        $cited_by   = model(CitationModel::class)->getCitedBy($id);

        return view('public/show', [
            'title'      => $doc['title'],
            'doc'        => $doc,
            'references' => $references,
            'cited_by'   => $cited_by,
        ]);
    }

    public function read(int $id)
    {
        $doc = model(DocumentModel::class)->getWithMeta($id);

        if (! $doc || $doc['status'] !== 'published') {
            throw new \CodeIgniter\Exceptions\PageNotFoundException();
        }

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

        return view('public/reader', [
            'title'   => 'Baca: ' . $doc['title'],
            'doc'     => $doc,
            'profile' => $profile,
        ]);
    }

    public function stream(int $id)
    {
        $doc = model(DocumentModel::class)->getWithMeta($id);

        if (! $doc || $doc['status'] !== 'published') {
            return $this->response->setStatusCode(404);
        }

        $path = ROOTPATH . 'storage/pdf/' . basename($doc['file_path']);

        if (! is_file($path)) {
            return $this->response->setStatusCode(404);
        }

        return $this->response
            ->setHeader('Content-Type', 'application/pdf')
            ->setHeader('Content-Disposition', 'inline; filename="document.pdf"')
            ->setHeader('Cache-Control', 'no-store, no-cache')
            ->setHeader('X-Content-Type-Options', 'nosniff')
            ->setBody(file_get_contents($path));
    }

    public function download(int $id)
    {
        $doc = model(DocumentModel::class)->getWithMeta($id);

        if (! $doc || $doc['status'] !== 'published') {
            return $this->response->setStatusCode(404);
        }

        $path = ROOTPATH . 'storage/pdf/' . basename($doc['file_path']);

        if (! is_file($path)) {
            return $this->response->setStatusCode(404);
        }

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

        $filename = preg_replace('/[^a-zA-Z0-9_\-]/', '_', $doc['title']) . '.pdf';

        return $this->response
            ->setHeader('Content-Type', 'application/pdf')
            ->setHeader('Content-Disposition', 'attachment; filename="' . $filename . '"')
            ->setHeader('Cache-Control', 'no-store')
            ->setBody(file_get_contents($path));
    }

    public function cover(string $filename)
    {
        $filename = basename($filename); // path traversal protection
        $path     = ROOTPATH . 'storage/covers/' . $filename;

        if (! is_file($path)) {
            return $this->response->setStatusCode(404);
        }

        $finfo = new \finfo(FILEINFO_MIME_TYPE);
        $mime  = $finfo->file($path);

        return $this->response
            ->setHeader('Content-Type', $mime)
            ->setHeader('Cache-Control', 'public, max-age=86400')
            ->setBody(file_get_contents($path));
    }

    private function getYearList(): array
    {
        $rows = model(DocumentModel::class)
            ->distinct()
            ->select('year')
            ->where('status', 'published')
            ->orderBy('year', 'DESC')
            ->findAll();
        return array_column($rows, 'year');
    }
}
