<?php
/// file: app/Controllers/Admin/ProjectAdminController.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\Project;

final class ProjectAdminController extends Controller
{
    public function index(Request $request): Response
    {
        $pdo = $this->app->pdo();
        $rows = $pdo->query('SELECT * FROM projects ORDER BY sort_order ASC, id DESC')->fetchAll(\PDO::FETCH_ASSOC) ?: [];
        $html = $this->adminView('admin/projects/index', ['projects' => $rows]);
        return Response::html($html);
    }

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

    public function store(Request $request): Response
    {
        if (! Csrf::verify($request->input('_csrf'))) {
            return $this->redirect(url('/admin/projects'));
        }
        $data = $this->collect($request, null);
        $errors = $this->validate($data);
        if ($errors !== []) {
            Session::flash('errors', $errors);
            Session::set('_old_project', $data);
            return $this->redirect(url('/admin/projects/create'));
        }
        $pdo = $this->app->pdo();
        $pdo->prepare(
            'INSERT INTO projects (title, slug, client, year, sector, category, services, summary, challenge, creative_direction, process, outcomes, cover_type, cover_path, status, sort_order)
             VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)'
        )->execute([
            $data['title'], $data['slug'], $data['client'], $data['year'], $data['sector'], $data['category'],
            $data['services'], $data['summary'], $data['challenge'], $data['creative_direction'], $data['process'],
            $data['outcomes'], $data['cover_type'], $data['cover_path'], $data['status'], $data['sort_order'],
        ]);
        $id = (int) $pdo->lastInsertId();
        $this->syncGallery($pdo, $id, $data['gallery_lines']);
        Session::remove('_old_project');
        return $this->redirect(url('/admin/projects'));
    }

    public function edit(Request $request): Response
    {
        $id = (int) ($request->param('id') ?? 0);
        $project = Project::find($id);
        if ($project === null) {
            return $this->redirect(url('/admin/projects'));
        }
        $media = $this->app->pdo()->prepare('SELECT type, path FROM project_media WHERE project_id = ? ORDER BY sort_order');
        $media->execute([$id]);
        $lines = [];
        foreach ($media->fetchAll(\PDO::FETCH_ASSOC) ?: [] as $m) {
            $lines[] = ($m['type'] === 'video' ? 'video|' : '') . $m['path'];
        }
        $project['gallery_paths'] = implode("\n", $lines);
        $flash = Session::pullFlash();
        $errors = $flash['errors'] ?? [];
        $old = Session::get('_old_project');
        Session::remove('_old_project');
        if (is_array($old)) {
            $project = array_merge($project, $old);
        }
        $html = $this->adminView('admin/projects/form', ['project' => $project, 'errors' => $errors]);
        return Response::html($html);
    }

    public function update(Request $request): Response
    {
        if (! Csrf::verify($request->input('_csrf'))) {
            return $this->redirect(url('/admin/projects'));
        }
        $id = (int) ($request->param('id') ?? 0);
        $existing = Project::find($id);
        $data = $this->collect($request, is_array($existing) ? $existing : null);
        $errors = $this->validate($data, $id);
        if ($errors !== []) {
            Session::flash('errors', $errors);
            Session::set('_old_project', array_merge($data, ['id' => $id]));
            return $this->redirect(url('/admin/projects/edit/' . $id));
        }
        $pdo = $this->app->pdo();
        $pdo->prepare(
            'UPDATE projects SET title=?, slug=?, client=?, year=?, sector=?, category=?, services=?, summary=?, challenge=?, creative_direction=?, process=?, outcomes=?, cover_type=?, cover_path=?, status=?, sort_order=? WHERE id=?'
        )->execute([
            $data['title'], $data['slug'], $data['client'], $data['year'], $data['sector'], $data['category'],
            $data['services'], $data['summary'], $data['challenge'], $data['creative_direction'], $data['process'],
            $data['outcomes'], $data['cover_type'], $data['cover_path'], $data['status'], $data['sort_order'], $id,
        ]);
        $pdo->prepare('DELETE FROM project_media WHERE project_id = ?')->execute([$id]);
        $this->syncGallery($pdo, $id, $data['gallery_lines']);
        return $this->redirect(url('/admin/projects'));
    }

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

    /**
     * @param array<string, mixed>|null $existing Row from DB on edit; preserves long-form fields removed from the admin form.
     *
     * @return array<string, mixed>
     */
    private function collect(Request $request, ?array $existing): array
    {
        $category = $this->normalizeCategory((string) $request->input('category', ''));
        $summary = trim((string) $request->input('summary', ''));

        $fromExisting = static function (string $key) use ($existing): string {
            return $existing !== null ? trim((string) ($existing[$key] ?? '')) : '';
        };

        return [
            'title' => trim((string) $request->input('title', '')),
            'slug' => trim((string) $request->input('slug', '')),
            'client' => trim((string) $request->input('client', '')),
            'year' => (int) $request->input('year', (string) date('Y')),
            'sector' => trim((string) $request->input('sector', '')),
            'category' => $category,
            'services' => trim((string) $request->input('services', '')),
            'summary' => $summary,
            'challenge' => $fromExisting('challenge'),
            'creative_direction' => $fromExisting('creative_direction'),
            'process' => $fromExisting('process'),
            'outcomes' => $fromExisting('outcomes'),
            'cover_type' => $request->input('cover_type', 'image') === 'video' ? 'video' : 'image',
            'cover_path' => trim((string) $request->input('cover_path', '')),
            'status' => $request->input('status', 'published') === 'draft' ? 'draft' : 'published',
            'sort_order' => (int) $request->input('sort_order', '0'),
            'gallery_lines' => (string) $request->input('gallery_paths', ''),
        ];
    }

    private function normalizeCategory(string $raw): string
    {
        $raw = trim($raw);
        $allowed = Project::categorySlugs();
        if ($raw === '') {
            return $allowed[0];
        }
        if (in_array($raw, $allowed, true)) {
            return $raw;
        }

        return $raw;
    }

    /** @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 projects 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 already in use.';
        }
        return $errors;
    }

    private function syncGallery(\PDO $pdo, int $projectId, string $raw): void
    {
        $lines = array_filter(array_map('trim', explode("\n", $raw)));
        $order = 0;
        foreach ($lines as $line) {
            $type = 'image';
            $path = $line;
            if (str_contains($line, '|')) {
                [$t, $path] = explode('|', $line, 2);
                $t = trim($t);
                $path = trim($path);
                if ($t === 'video') {
                    $type = 'video';
                }
            }
            if ($path === '') {
                continue;
            }
            $pdo->prepare('INSERT INTO project_media (project_id, type, path, sort_order) VALUES (?,?,?,?)')
                ->execute([$projectId, $type, $path, $order++]);
        }
    }
}
