<?php
/// file: app/Controllers/Admin/JournalAdminController.php

declare(strict_types=1);

namespace App\Controllers\Admin;

use App\Core\Controller;
use App\Core\Csrf;
use App\Core\Request;
use App\Core\Response;
use App\Core\Session;
use App\Models\JournalPost;

final class JournalAdminController extends Controller
{
    public function index(Request $request): Response
    {
        $rows = JournalPost::all('id DESC');
        $html = $this->adminView('admin/journal/index', ['posts' => $rows]);
        return Response::html($html);
    }

    public function create(Request $request): Response
    {
        $flash = Session::pullFlash();
        $old = Session::get('_old_journal');
        Session::remove('_old_journal');
        $html = $this->adminView('admin/journal/form', [
            'post' => is_array($old) ? $old : null,
            'errors' => $flash['errors'] ?? [],
        ]);
        return Response::html($html);
    }

    public function store(Request $request): Response
    {
        if (! Csrf::verify($request->input('_csrf'))) {
            return $this->redirect(url('/admin/journal'));
        }
        $data = $this->collect($request);
        $errors = $this->validate($data);
        if ($errors !== []) {
            Session::flash('errors', $errors);
            Session::set('_old_journal', $data);
            return $this->redirect(url('/admin/journal/create'));
        }
        $this->app->pdo()->prepare(
            'INSERT INTO journal_posts (title, slug, excerpt, body, category, reading_time, cover_path, status, published_at) VALUES (?,?,?,?,?,?,?,?,?)'
        )->execute([
            $data['title'], $data['slug'], $data['excerpt'], $data['body'], $data['category'],
            $data['reading_time'], $data['cover_path'], $data['status'], $data['published_at'],
        ]);
        return $this->redirect(url('/admin/journal'));
    }

    public function edit(Request $request): Response
    {
        $id = (int) ($request->param('id') ?? 0);
        $post = JournalPost::find($id);
        if ($post === null) {
            return $this->redirect(url('/admin/journal'));
        }
        $flash = Session::pullFlash();
        $old = Session::get('_old_journal');
        Session::remove('_old_journal');
        if (is_array($old)) {
            $post = array_merge($post, $old);
        }
        $html = $this->adminView('admin/journal/form', ['post' => $post, 'errors' => $flash['errors'] ?? []]);
        return Response::html($html);
    }

    public function update(Request $request): Response
    {
        if (! Csrf::verify($request->input('_csrf'))) {
            return $this->redirect(url('/admin/journal'));
        }
        $id = (int) ($request->param('id') ?? 0);
        $data = $this->collect($request);
        $errors = $this->validate($data, $id);
        if ($errors !== []) {
            Session::flash('errors', $errors);
            Session::set('_old_journal', array_merge($data, ['id' => $id]));
            return $this->redirect(url('/admin/journal/edit/' . $id));
        }
        $this->app->pdo()->prepare(
            'UPDATE journal_posts SET title=?, slug=?, excerpt=?, body=?, category=?, reading_time=?, cover_path=?, status=?, published_at=? WHERE id=?'
        )->execute([
            $data['title'], $data['slug'], $data['excerpt'], $data['body'], $data['category'],
            $data['reading_time'], $data['cover_path'], $data['status'], $data['published_at'], $id,
        ]);
        return $this->redirect(url('/admin/journal'));
    }

    public function destroy(Request $request): Response
    {
        if (! Csrf::verify($request->input('_csrf'))) {
            return $this->redirect(url('/admin/journal'));
        }
        $id = (int) ($request->param('id') ?? 0);
        $this->app->pdo()->prepare('DELETE FROM journal_posts WHERE id = ?')->execute([$id]);
        return $this->redirect(url('/admin/journal'));
    }

    /** @return array<string, mixed> */
    private function collect(Request $request): array
    {
        return [
            'title' => trim((string) $request->input('title', '')),
            'slug' => trim((string) $request->input('slug', '')),
            'excerpt' => trim((string) $request->input('excerpt', '')),
            'body' => trim((string) $request->input('body', '')),
            'category' => trim((string) $request->input('category', 'studio')),
            'reading_time' => (int) $request->input('reading_time', '5'),
            'cover_path' => trim((string) $request->input('cover_path', '')),
            'status' => $request->input('status', 'published') === 'draft' ? 'draft' : 'published',
            'published_at' => trim((string) $request->input('published_at', date('Y-m-d'))) ?: date('Y-m-d'),
        ];
    }

    /** @return array<string, string> */
    private function validate(array $data, ?int $ignoreId = null): array
    {
        $errors = [];
        if ($data['title'] === '' || $data['slug'] === '') {
            $errors['title'] = 'Title and slug required.';
        }
        $pdo = $this->app->pdo();
        $q = 'SELECT id FROM journal_posts WHERE slug = ?';
        $params = [$data['slug']];
        if ($ignoreId) {
            $q .= ' AND id != ?';
            $params[] = $ignoreId;
        }
        $st = $pdo->prepare($q . ' LIMIT 1');
        $st->execute($params);
        if ($st->fetch()) {
            $errors['slug'] = 'Slug in use.';
        }
        return $errors;
    }
}
