<?php
declare(strict_types=1);

namespace Infolab\Controllers;

use Infolab\ActivityLogger;
use Infolab\Database;
use Infolab\Request;
use Infolab\Response;
use Infolab\Validator;

/**
 * Ressources d'un projet (liens, docs, datasets, vidéos).
 */
final class ResourcesController
{
    private const KINDS = ['link', 'document', 'dataset', 'video', 'other'];

    public function index(Request $req, array $params): void
    {
        $p = ProjectsController::findOr404($params['slug']);
        $rows = Database::fetchAll(
            'SELECT id, project_id, title, description, url, kind, sort_order, created_at, updated_at
             FROM resources WHERE project_id = :pid ORDER BY sort_order ASC, id ASC',
            [':pid' => (int) $p['id']],
        );
        Response::json(['data' => array_map([self::class, 'present'], $rows)]);
    }

    public function store(Request $req, array $params): void
    {
        $p = ProjectsController::findOr404($params['slug']);
        $body = $req->json();
        $v = new Validator($body);
        $v->required('title')->string('title', 200);
        $v->required('url')->url('url', 1024);
        $v->string('description', 5000);
        $v->in('kind', self::KINDS);
        $v->integer('sort_order', 0);
        $v->check();

        $sortOrder = isset($body['sort_order'])
            ? (int) $body['sort_order']
            : self::nextSortOrder((int) $p['id']);

        $id = Database::insert('resources', [
            'project_id'  => (int) $p['id'],
            'title'       => (string) $body['title'],
            'description' => $body['description'] ?? null,
            'url'         => (string) $body['url'],
            'kind'        => $body['kind'] ?? 'link',
            'sort_order'  => $sortOrder,
        ]);

        ActivityLogger::log(
            'added_resource',
            sprintf('a ajouté la ressource « %s » au projet « %s »', (string) $body['title'], $p['title']),
            (int) $p['id'],
        );

        $row = Database::fetchOne('SELECT * FROM resources WHERE id = :id', [':id' => $id]);
        Response::json(self::present($row), 201);
    }

    public function update(Request $req, array $params): void
    {
        $p = ProjectsController::findOr404($params['slug']);
        $r = self::findOr404((int) $params['id'], (int) $p['id']);

        $body = $req->json();
        $v = new Validator($body);
        $v->string('title', 200);
        $v->string('description', 5000);
        $v->url('url', 1024);
        $v->in('kind', self::KINDS);
        $v->integer('sort_order', 0);
        $v->check();

        $update = [];
        foreach (['title', 'description', 'url', 'kind', 'sort_order'] as $f) {
            if (array_key_exists($f, $body)) {
                $update[$f] = $body[$f];
            }
        }
        if (isset($update['sort_order'])) {
            $update['sort_order'] = (int) $update['sort_order'];
        }
        if ($update !== []) {
            Database::update('resources', $update, 'id = :id', [':id' => (int) $r['id']]);
        }
        $fresh = Database::fetchOne('SELECT * FROM resources WHERE id = :id', [':id' => (int) $r['id']]);
        Response::json(self::present($fresh));
    }

    public function destroy(Request $req, array $params): void
    {
        $p = ProjectsController::findOr404($params['slug']);
        $r = self::findOr404((int) $params['id'], (int) $p['id']);
        Database::delete('resources', 'id = :id', [':id' => (int) $r['id']]);
        Response::noContent();
    }

    private static function findOr404(int $id, int $projectId): array
    {
        $row = Database::fetchOne(
            'SELECT * FROM resources WHERE id = :id AND project_id = :pid',
            [':id' => $id, ':pid' => $projectId],
        );
        if ($row === null) {
            throw new \ApiException(404, ['error' => 'not_found']);
        }
        return $row;
    }

    private static function nextSortOrder(int $projectId): int
    {
        return (int) Database::fetchValue(
            'SELECT COALESCE(MAX(sort_order), 0) + 10 FROM resources WHERE project_id = :pid',
            [':pid' => $projectId],
        );
    }

    private static function present(array $row): array
    {
        return [
            'id'          => (int) $row['id'],
            'project_id'  => (int) $row['project_id'],
            'title'       => $row['title'],
            'description' => $row['description'],
            'url'         => $row['url'],
            'kind'        => $row['kind'],
            'sort_order'  => (int) $row['sort_order'],
            'created_at'  => $row['created_at'],
            'updated_at'  => $row['updated_at'],
        ];
    }
}
