<?php

declare(strict_types=1);

require_once __DIR__ . '/../db.php';
require_once __DIR__ . '/../auth.php';

header('Content-Type: application/json; charset=utf-8');

function jsonResponse(array $data, int $status = 200): void
{
    http_response_code($status);
    echo json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
    exit;
}

function getInputData(): array
{
    $contentType = $_SERVER['CONTENT_TYPE'] ?? '';

    if (str_contains($contentType, 'application/json')) {
        $raw = file_get_contents('php://input');
        $data = json_decode($raw, true);

        return is_array($data) ? $data : [];
    }

    return $_POST;
}

function normalizeDateValue(mixed $value, string $fieldName): ?string
{
    $value = trim((string)$value);

    if ($value === '') {
        return null;
    }

    if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $value)) {
        jsonResponse([
            'success' => false,
            'error' => "Invalid {$fieldName}. Use YYYY-MM-DD."
        ], 400);
    }

    return $value;
}

function requireProjectAccess(string $projectId, int $userId): void
{
    requireProjectAccessForUser($userId, $projectId);
}

$user = requireApiAuth();

$api = $_GET['api'] ?? '';

switch ($api) {

    case 'ListVersions': {
        $projectId = strtoupper(trim($_GET['project_id'] ?? ''));

        if ($projectId === '') {
            jsonResponse([
                'success' => false,
                'error' => 'Missing project_id.'
            ], 400);
        }

        requireProjectAccess($projectId, (int)$user['id']);

        $stmt = db()->prepare(
            'SELECT id
             FROM versions
             WHERE project = ?
             ORDER BY created_date DESC, id DESC'
        );

        $stmt->execute([$projectId]);

        jsonResponse([
            'success' => true,
            'versions' => array_map('intval', $stmt->fetchAll(PDO::FETCH_COLUMN))
        ]);
    }

    case 'VersionInfo': {
        $versionId = (int)($_GET['version_id'] ?? 0);

        if ($versionId <= 0) {
            jsonResponse([
                'success' => false,
                'error' => 'Missing or invalid version_id.'
            ], 400);
        }

        $stmt = db()->prepare(
            'SELECT
                versions.id,
                versions.name,
                versions.description,
                versions.created_date,
                versions.due_date,
                versions.released_date,
                versions.project
             FROM versions
             INNER JOIN projects ON projects.id = versions.project
             WHERE versions.id = ?
             LIMIT 1'
        );

        $stmt->execute([$versionId]);

        $version = $stmt->fetch();

        if (!$version) {
            jsonResponse([
                'success' => false,
                'error' => 'Version not found.'
            ], 404);
        }

        requireProjectAccessForUser((int)$user['id'], (string)$version['project']);

        jsonResponse([
            'success' => true,
            'version' => $version
        ]);
    }

    case 'Create': {
        if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
            jsonResponse([
                'success' => false,
                'error' => 'Create requires POST.'
            ], 405);
        }

        $data = getInputData();

        $projectId = strtoupper(trim($data['project_id'] ?? $data['project'] ?? ''));
        $name = trim($data['name'] ?? '');
        $description = array_key_exists('description', $data) ? trim((string)$data['description']) : null;
        $dueDate = array_key_exists('due_date', $data) ? normalizeDateValue($data['due_date'], 'due_date') : null;
        $releasedDate = array_key_exists('released_date', $data) ? normalizeDateValue($data['released_date'], 'released_date') : null;

        if ($projectId === '') {
            jsonResponse([
                'success' => false,
                'error' => 'Project id is required.'
            ], 400);
        }

        requireProjectRight((int)$user['id'], $projectId, 'Create Versions');

        if ($name === '') {
            jsonResponse([
                'success' => false,
                'error' => 'Version name is required.'
            ], 400);
        }

        if (strlen($name) > 128) {
            jsonResponse([
                'success' => false,
                'error' => 'Version name is too long.'
            ], 400);
        }

        $stmt = db()->prepare(
            'INSERT INTO versions
             (name, description, created_date, due_date, released_date, project)
             VALUES (?, ?, CURDATE(), ?, ?, ?)'
        );

        $stmt->execute([
            $name,
            $description,
            $dueDate,
            $releasedDate,
            $projectId
        ]);

        jsonResponse([
            'success' => true,
            'version_id' => (int)db()->lastInsertId()
        ], 201);
    }

    case 'Edit': {
        if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
            jsonResponse([
                'success' => false,
                'error' => 'Edit requires POST.'
            ], 405);
        }

        $versionId = (int)($_GET['version_id'] ?? 0);

        if ($versionId <= 0) {
            jsonResponse([
                'success' => false,
                'error' => 'Missing or invalid version_id.'
            ], 400);
        }

        $data = getInputData();
        $projectStmt = db()->prepare(
            'SELECT project
             FROM versions
             WHERE id = ?
             LIMIT 1'
        );
        $projectStmt->execute([$versionId]);
        $versionProject = $projectStmt->fetchColumn();

        if (!$versionProject) {
            jsonResponse([
                'success' => false,
                'error' => 'Version not found.'
            ], 404);
        }

        requireProjectRight((int)$user['id'], (string)$versionProject, 'Edit Versions');

        $fields = [];
        $values = [];

        if (array_key_exists('name', $data)) {
            $name = trim((string)$data['name']);

            if ($name === '') {
                jsonResponse([
                    'success' => false,
                    'error' => 'Version name cannot be empty.'
                ], 400);
            }

            if (strlen($name) > 128) {
                jsonResponse([
                    'success' => false,
                    'error' => 'Version name is too long.'
                ], 400);
            }

            $fields[] = 'versions.name = ?';
            $values[] = $name;
        }

        if (array_key_exists('description', $data)) {
            $description = trim((string)$data['description']);

            $fields[] = 'versions.description = ?';
            $values[] = $description !== '' ? $description : null;
        }

        if (array_key_exists('due_date', $data)) {
            $fields[] = 'versions.due_date = ?';
            $values[] = normalizeDateValue($data['due_date'], 'due_date');
        }

        if (array_key_exists('released_date', $data)) {
            $fields[] = 'versions.released_date = ?';
            $values[] = normalizeDateValue($data['released_date'], 'released_date');
        }

        if (empty($fields)) {
            jsonResponse([
                'success' => false,
                'error' => 'No editable fields provided.'
            ], 400);
        }

        $values[] = $versionId;

        $stmt = db()->prepare(
            'UPDATE versions
             INNER JOIN projects ON projects.id = versions.project
             SET ' . implode(', ', $fields) . '
             WHERE versions.id = ?'
        );

        $stmt->execute($values);

        if ($stmt->rowCount() === 0) {
            $existsStmt = db()->prepare(
                'SELECT versions.id
                 FROM versions
                 INNER JOIN projects ON projects.id = versions.project
                 WHERE versions.id = ?
                 LIMIT 1'
            );

            $existsStmt->execute([$versionId]);

            if ($existsStmt->fetch()) {
                jsonResponse([
                    'success' => true,
                    'version_id' => $versionId
                ]);
            }

            jsonResponse([
                'success' => false,
                'error' => 'Version not found.'
            ], 404);
        }

        jsonResponse([
            'success' => true,
            'version_id' => $versionId
        ]);
    }

    default: {
        jsonResponse([
            'success' => false,
            'error' => 'Unknown API action.'
        ], 404);
    }
}
