<?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 requireUserExists(int $userId): void
{
    if ($userId <= 0) {
        jsonResponse([
            'success' => false,
            'error' => 'Project owner must be valid.'
        ], 400);
    }

    $stmt = db()->prepare('SELECT id FROM users WHERE id = ? LIMIT 1');
    $stmt->execute([$userId]);

    if (!$stmt->fetch()) {
        jsonResponse([
            'success' => false,
            'error' => 'Project owner not found.'
        ], 400);
    }
}

$user = requireApiAuth();

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

switch ($api) {

    case 'ListProjects': {
        if (userIsAdmin((int)$user['id'])) {
            $stmt = db()->query(
                'SELECT id
                 FROM projects
                 ORDER BY id ASC'
            );
        } else {
            $stmt = db()->prepare(
                'SELECT DISTINCT projects.id
                 FROM projects
                 LEFT JOIN user_access
                    ON user_access.project_id = projects.id
                   AND user_access.user_id = ?
                 WHERE projects.owner = ?
                    OR user_access.id IS NOT NULL
                 ORDER BY projects.id ASC'
            );
            $stmt->execute([(int)$user['id'], (int)$user['id']]);
        }

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

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

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

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

        $stmt = db()->prepare(
            'SELECT id, name, owner, created_date
             FROM projects
             WHERE id = ?
             LIMIT 1'
        );

        $stmt->execute([$projectId]);
        $project = $stmt->fetch();

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

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

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

        requireUserRight((int)$user['id'], 'Create Projects');

        $data = getInputData();

        $projectId = strtoupper(trim($data['id'] ?? ''));
        $name = trim($data['name'] ?? '');
        $owner = isset($data['owner']) && $data['owner'] !== ''
            ? (int)$data['owner']
            : (int)$user['id'];

        if (!preg_match('/^[A-Z0-9]{2,12}$/', $projectId)) {
            jsonResponse([
                'success' => false,
                'error' => 'Project id must be 2-12 characters and contain only A-Z and 0-9.'
            ], 400);
        }

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

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

        requireUserExists($owner);

        $stmt = db()->prepare(
            'SELECT id FROM projects WHERE id = ? LIMIT 1'
        );

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

        if ($stmt->fetch()) {
            jsonResponse([
                'success' => false,
                'error' => 'Project id already exists.'
            ], 409);
        }

        $stmt = db()->prepare(
            'INSERT INTO projects (id, name, owner, created_date)
             VALUES (?, ?, ?, CURDATE())'
        );

        $stmt->execute([
            $projectId,
            $name,
            $owner
        ]);

        jsonResponse([
            'success' => true,
            'project_id' => $projectId
        ], 201);
    }

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

        $projectId = strtoupper(trim($_GET['project_id'] ?? ''));

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

        requireProjectRight((int)$user['id'], $projectId, 'Edit Projects');

        $data = getInputData();

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

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

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

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

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

        if (array_key_exists('owner', $data)) {
            $owner = (int)$data['owner'];
            requireUserExists($owner);

            $fields[] = 'owner = ?';
            $values[] = $owner;
        }

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

        $values[] = $projectId;

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

        $stmt->execute($values);

        if ($stmt->rowCount() === 0) {
            $existsStmt = db()->prepare('SELECT id FROM projects WHERE id = ? LIMIT 1');
            $existsStmt->execute([$projectId]);

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

            jsonResponse([
                'success' => false,
                'error' => 'Project not found or nothing changed.'
            ], 404);
        }

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

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