<?php

class ProjectAccess {

    // Список всех доступных прав
    const PERMISSIONS = [
        'create_task',          // создание задач
        'edit_task',            // редактирование любых задач
        'edit_own_task_only',   // редактирование только назначенных на себя
        'delete_task',          // удаление задач
        'move_task',            // перемещение любых задач между колонками
        'move_own_task_only',   // перемещение только назначенных на себя
        'archive_task',         // архивирование задач
        'create_column',        // создание колонок
        'edit_column',          // редактирование колонок
        'delete_column',        // удаление колонок
        'manage_departments',   // управление отделами
        'remove_members',       // удаление участников (приглашать/редактировать могут только админы)
        'create_comment',              // создание комментариев в любых задачах
        'create_comment_own_task_only', // создание комментариев только в назначенных на себя
        'delete_own_comments',  // удаление своих комментариев
        'delete_all_comments',  // удаление любых комментариев в проекте
        'upload_files',         // загрузка файлов
        'upload_images'         // загрузка картинок
    ];

    // Права по умолчанию для нового участника
    const DEFAULT_PERMISSIONS = [
        'create_task' => true,          // создание задач
        'edit_task' => false,           // редактирование любых задач
        'edit_own_task_only' => true,   // редактирование только назначенных на себя
        'delete_task' => false,         // удаление задач
        'move_task' => false,           // перемещение любых задач между колонками
        'move_own_task_only' => true,   // перемещение только назначенных на себя
        'archive_task' => true,         // архивирование задач
        'create_column' => false,       // создание колонок
        'edit_column' => false,         // редактирование колонок
        'delete_column' => false,       // удаление колонок
        'manage_departments' => false,  // управление отделами
        'remove_members' => false,      // удаление участников
        'create_comment' => false,              // создание комментариев в любых задачах
        'create_comment_own_task_only' => true, // создание комментариев только в назначенных на себя
        'delete_own_comments' => true,  // удаление своих комментариев
        'delete_all_comments' => false, // удаление любых комментариев
        'upload_files' => true,         // загрузка файлов
        'upload_images' => true         // загрузка картинок
    ];

    // ==================== ПРОВЕРКИ ДОСТУПА ====================

    // Проверить, является ли пользователь владельцем проекта (в id_admin таблицы projects)
    public static function isOwner(int $project_id, int $user_id): bool {
        $project = Database::get('project', ['id_admin'], ['id' => $project_id]);
        if (!$project || !$project['id_admin']) {
            return false;
        }
        $owners = json_decode($project['id_admin'], true);
        return is_array($owners) && in_array($user_id, $owners);
    }

    // Проверить, является ли пользователь участником проекта
    public static function isMember(int $project_id, int $user_id): bool {
        // Владелец всегда имеет доступ
        if (self::isOwner($project_id, $user_id)) {
            return true;
        }
        return Database::has('project_members', [
            'id_project' => $project_id,
            'id_user' => $user_id
        ]);
    }

    // Проверить, является ли пользователь админом проекта
    public static function isAdmin(int $project_id, int $user_id): bool {
        // Владелец = безоговорочный админ
        if (self::isOwner($project_id, $user_id)) {
            return true;
        }
        return Database::has('project_members', [
            'id_project' => $project_id,
            'id_user' => $user_id,
            'is_admin' => 1
        ]);
    }

    // Проверить конкретное право (владелец/админ имеет все права)
    public static function can(int $project_id, int $user_id, string $permission): bool {
        // Владелец может всё
        if (self::isOwner($project_id, $user_id)) {
            return true;
        }

        $member = Database::get('project_members', ['is_admin', 'permissions'], [
            'id_project' => $project_id,
            'id_user' => $user_id
        ]);

        if (!$member) {
            return false;
        }

        // Админ может всё
        if ((int)$member['is_admin'] === 1) {
            return true;
        }

        $permissions = $member['permissions'] ? json_decode($member['permissions'], true) : [];
        return isset($permissions[$permission]) && $permissions[$permission] === true;
    }

    // Проверить право на редактирование задачи (с учётом edit_own_task_only)
    // "Своя задача" = назначен на пользователя ИЛИ создана пользователем
    public static function canEditTask(int $project_id, int $user_id, ?int $task_assignee_id, ?int $task_creator_id = null): bool {
        if (self::isAdmin($project_id, $user_id)) {
            return true;
        }

        if (self::can($project_id, $user_id, 'edit_task')) {
            return true;
        }

        // Создатель + право создания → может редактировать свои созданные
        if ($task_creator_id === $user_id && self::can($project_id, $user_id, 'create_task')) {
            return true;
        }

        // Назначена на себя + право edit_own_task_only
        if ($task_assignee_id === $user_id && self::can($project_id, $user_id, 'edit_own_task_only')) {
            return true;
        }

        return false;
    }

    // Проверить право на перемещение задачи (с учётом move_own_task_only)
    // "Своя задача" = назначен на пользователя ИЛИ создана пользователем
    public static function canMoveTask(int $project_id, int $user_id, ?int $task_assignee_id, ?int $task_creator_id = null): bool {
        if (self::isAdmin($project_id, $user_id)) {
            return true;
        }

        if (self::can($project_id, $user_id, 'move_task')) {
            return true;
        }

        // Создатель + право создания → может перемещать свои созданные
        if ($task_creator_id === $user_id && self::can($project_id, $user_id, 'create_task')) {
            return true;
        }

        // Назначена на себя + право move_own_task_only
        if ($task_assignee_id === $user_id && self::can($project_id, $user_id, 'move_own_task_only')) {
            return true;
        }

        return false;
    }

    // Проверить право на создание комментария в задаче
    public static function canCreateComment(int $project_id, int $user_id, ?int $task_assignee_id, ?int $task_creator_id = null): bool {
        if (self::isAdmin($project_id, $user_id)) {
            return true;
        }

        // Полное право — комментировать любые задачи
        if (self::can($project_id, $user_id, 'create_comment')) {
            return true;
        }

        // Создатель + право создания → может комментировать свои созданные
        if ($task_creator_id === $user_id && self::can($project_id, $user_id, 'create_task')) {
            return true;
        }

        // Назначена на себя + право create_comment_own_task_only
        if ($task_assignee_id === $user_id && self::can($project_id, $user_id, 'create_comment_own_task_only')) {
            return true;
        }

        return false;
    }

    // ==================== ПРОВЕРКИ С EXIT ====================

    // Требовать доступ к проекту (при отказе — 403 и exit)
    public static function requireAccess(int $project_id, ?int $user_id): void {
        if (!$user_id) {
            RestApi::response(['success' => false, 'errors' => ['auth' => 'Требуется авторизация']], 401);
        }

        if (!self::isMember($project_id, $user_id)) {
            RestApi::response(['success' => false, 'errors' => ['access' => 'Нет доступа к проекту']], 403);
        }
    }

    // Требовать права админа
    public static function requireAdmin(int $project_id, ?int $user_id): void {
        if (!$user_id) {
            RestApi::response(['success' => false, 'errors' => ['auth' => 'Требуется авторизация']], 401);
        }

        if (!self::isAdmin($project_id, $user_id)) {
            RestApi::response(['success' => false, 'errors' => ['access' => 'Требуются права администратора']], 403);
        }
    }

    // Требовать конкретное право
    public static function requirePermission(int $project_id, ?int $user_id, string $permission): void {
        if (!$user_id) {
            RestApi::response(['success' => false, 'errors' => ['auth' => 'Требуется авторизация']], 401);
        }

        if (!self::can($project_id, $user_id, $permission)) {
            RestApi::response(['success' => false, 'errors' => ['access' => 'Недостаточно прав']], 403);
        }
    }

    // Требовать право на редактирование задачи
    public static function requireEditTask(int $project_id, ?int $user_id, ?int $task_assignee_id, ?int $task_creator_id = null): void {
        if (!$user_id) {
            RestApi::response(['success' => false, 'errors' => ['auth' => 'Требуется авторизация']], 401);
        }

        if (!self::canEditTask($project_id, $user_id, $task_assignee_id, $task_creator_id)) {
            RestApi::response(['success' => false, 'errors' => ['access' => 'Нет прав на редактирование задачи']], 403);
        }
    }

    // Требовать право на перемещение задачи
    public static function requireMoveTask(int $project_id, ?int $user_id, ?int $task_assignee_id, ?int $task_creator_id = null): void {
        if (!$user_id) {
            RestApi::response(['success' => false, 'errors' => ['auth' => 'Требуется авторизация']], 401);
        }

        if (!self::canMoveTask($project_id, $user_id, $task_assignee_id, $task_creator_id)) {
            RestApi::response(['success' => false, 'errors' => ['access' => 'Нет прав на перемещение задачи']], 403);
        }
    }

    // ==================== УПРАВЛЕНИЕ УЧАСТНИКАМИ ====================

    // Добавить участника в проект
    public static function addMember(int $project_id, int $user_id, int $current_user_id, bool $is_admin = false, ?array $permissions = null): array {
        // Нельзя пригласить себя
        if ($user_id === $current_user_id) {
            return ['success' => false, 'errors' => ['member' => 'Нельзя пригласить себя в проект']];
        }

        if (self::isMember($project_id, $user_id)) {
            return ['success' => false, 'errors' => ['member' => 'Пользователь уже участник проекта']];
        }

        $perms = $permissions ?? self::DEFAULT_PERMISSIONS;

        Database::insert('project_members', [
            'id_project' => $project_id,
            'id_user' => $user_id,
            'is_admin' => $is_admin ? 1 : 0,
            'permissions' => json_encode($perms),
            'created_at' => date('Y-m-d H:i:s')
        ]);

        return ['success' => true, 'id' => Database::id()];
    }

    // Удалить участника из проекта (владельца удалить нельзя, админ не может удалить себя)
    public static function removeMember(int $project_id, int $user_id, int $current_user_id): array {
        // Владельца удалить нельзя
        if (self::isOwner($project_id, $user_id)) {
            return ['success' => false, 'errors' => ['member' => 'Нельзя удалить владельца проекта']];
        }

        $member = Database::get('project_members', ['is_admin'], [
            'id_project' => $project_id,
            'id_user' => $user_id
        ]);

        if (!$member) {
            return ['success' => false, 'errors' => ['member' => 'Участник не найден']];
        }

        // Админ может выйти сам, если есть другие админы или владелец
        // (владелец всегда есть в id_admin проекта, так что это безопасно)

        Database::delete('project_members', [
            'id_project' => $project_id,
            'id_user' => $user_id
        ]);

        return ['success' => true];
    }

    // Получить всех участников проекта (включая владельцев из id_admin)
    public static function getMembers(int $project_id): array {
        $result = [];
        $addedUserIds = [];

        // Получаем владельцев из id_admin проекта
        $project = Database::get('project', ['id_admin'], ['id' => $project_id]);
        if ($project && $project['id_admin']) {
            $ownerIds = json_decode($project['id_admin'], true);
            if (is_array($ownerIds) && count($ownerIds) > 0) {
                $owners = Database::select('accounts', ['id', 'name', 'username', 'avatar_url', 'telegram'], ['id' => $ownerIds]);
                foreach ($owners as $owner) {
                    $result[] = [
                        'id' => null,
                        'id_user' => (int)$owner['id'],
                        'is_admin' => true,
                        'is_owner' => true,
                        'permissions' => [],
                        'created_at' => null,
                        'name' => $owner['name'],
                        'username' => $owner['username'],
                        'avatar_url' => $owner['avatar_url'],
                        'telegram' => $owner['telegram']
                    ];
                    $addedUserIds[] = (int)$owner['id'];
                }
            }
        }

        // Получаем участников из project_members
        $members = Database::select('project_members', [
            '[>]accounts' => ['id_user' => 'id']
        ], [
            'project_members.id',
            'project_members.id_user',
            'project_members.is_admin',
            'project_members.permissions',
            'project_members.created_at',
            'accounts.name',
            'accounts.username',
            'accounts.avatar_url',
            'accounts.telegram'
        ], [
            'project_members.id_project' => $project_id
        ]);

        foreach ($members as $member) {
            $userId = (int)$member['id_user'];
            // Пропускаем если уже добавлен как владелец
            if (in_array($userId, $addedUserIds)) {
                continue;
            }
            $result[] = [
                'id' => $member['id'],
                'id_user' => $userId,
                'is_admin' => (int)$member['is_admin'] === 1,
                'is_owner' => false,
                'permissions' => $member['permissions'] ? json_decode($member['permissions'], true) : [],
                'created_at' => $member['created_at'],
                'name' => $member['name'],
                'username' => $member['username'],
                'avatar_url' => $member['avatar_url'],
                'telegram' => $member['telegram']
            ];
        }

        return $result;
    }

    // Получить ID всех проектов пользователя (включая где он владелец)
    public static function getUserProjectIds(int $user_id): array {
        $projectIds = [];

        // Проекты из project_members
        $rows = Database::select('project_members', ['id_project'], [
            'id_user' => $user_id
        ]);
        foreach ($rows as $row) {
            $projectIds[] = (int)$row['id_project'];
        }

        // Проекты где пользователь в id_admin
        $allProjects = Database::select('project', ['id', 'id_admin']);
        foreach ($allProjects as $project) {
            if ($project['id_admin']) {
                $owners = json_decode($project['id_admin'], true);
                if (is_array($owners) && in_array($user_id, $owners)) {
                    $pid = (int)$project['id'];
                    if (!in_array($pid, $projectIds)) {
                        $projectIds[] = $pid;
                    }
                }
            }
        }

        return $projectIds;
    }

    // ==================== УПРАВЛЕНИЕ ПРАВАМИ ====================

    // Установить конкретное право
    public static function setPermission(int $project_id, int $user_id, string $permission, bool $value, int $current_user_id): array {
        // Нельзя редактировать свои права
        if ($user_id === $current_user_id) {
            return ['success' => false, 'errors' => ['member' => 'Нельзя изменять свои права']];
        }

        if (!in_array($permission, self::PERMISSIONS)) {
            return ['success' => false, 'errors' => ['permission' => 'Неизвестное право: ' . $permission]];
        }

        $member = Database::get('project_members', ['permissions'], [
            'id_project' => $project_id,
            'id_user' => $user_id
        ]);

        if (!$member) {
            return ['success' => false, 'errors' => ['member' => 'Участник не найден']];
        }

        $permissions = $member['permissions'] ? json_decode($member['permissions'], true) : [];
        $permissions[$permission] = $value;

        Database::update('project_members', [
            'permissions' => json_encode($permissions)
        ], [
            'id_project' => $project_id,
            'id_user' => $user_id
        ]);

        return ['success' => true, 'permissions' => $permissions];
    }

    // Установить несколько прав сразу
    public static function setPermissions(int $project_id, int $user_id, array $permissions, int $current_user_id): array {
        // Нельзя редактировать свои права
        if ($user_id === $current_user_id) {
            return ['success' => false, 'errors' => ['member' => 'Нельзя изменять свои права']];
        }

        // Нельзя редактировать права владельца
        if (self::isOwner($project_id, $user_id)) {
            return ['success' => false, 'errors' => ['member' => 'Нельзя изменять права владельца проекта']];
        }

        foreach (array_keys($permissions) as $perm) {
            if (!in_array($perm, self::PERMISSIONS)) {
                return ['success' => false, 'errors' => ['permission' => 'Неизвестное право: ' . $perm]];
            }
        }

        $member = Database::get('project_members', ['permissions'], [
            'id_project' => $project_id,
            'id_user' => $user_id
        ]);

        if (!$member) {
            return ['success' => false, 'errors' => ['member' => 'Участник не найден']];
        }

        $currentPerms = $member['permissions'] ? json_decode($member['permissions'], true) : [];
        $mergedPerms = array_merge($currentPerms, $permissions);

        Database::update('project_members', [
            'permissions' => json_encode($mergedPerms)
        ], [
            'id_project' => $project_id,
            'id_user' => $user_id
        ]);

        return ['success' => true, 'permissions' => $mergedPerms];
    }

    // Получить права участника
    public static function getPermissions(int $project_id, int $user_id): ?array {
        // Владелец имеет все права
        if (self::isOwner($project_id, $user_id)) {
            $allPerms = [];
            foreach (self::PERMISSIONS as $perm) {
                $allPerms[$perm] = true;
            }
            return $allPerms;
        }

        $member = Database::get('project_members', ['is_admin', 'permissions'], [
            'id_project' => $project_id,
            'id_user' => $user_id
        ]);

        if (!$member) {
            return null;
        }

        // Админ имеет все права
        if ((int)$member['is_admin'] === 1) {
            $allPerms = [];
            foreach (self::PERMISSIONS as $perm) {
                $allPerms[$perm] = true;
            }
            return $allPerms;
        }

        return $member['permissions'] ? json_decode($member['permissions'], true) : [];
    }

    // Назначить/снять админа
    public static function setAdmin(int $project_id, int $user_id, bool $is_admin, int $current_user_id): array {
        // Нельзя редактировать свои права
        if ($user_id === $current_user_id) {
            return ['success' => false, 'errors' => ['member' => 'Нельзя изменять свои права']];
        }

        // Нельзя изменять статус владельца
        if (self::isOwner($project_id, $user_id)) {
            return ['success' => false, 'errors' => ['member' => 'Нельзя изменять статус владельца проекта']];
        }

        $member = Database::get('project_members', ['id'], [
            'id_project' => $project_id,
            'id_user' => $user_id
        ]);

        if (!$member) {
            return ['success' => false, 'errors' => ['member' => 'Участник не найден']];
        }

        Database::update('project_members', [
            'is_admin' => $is_admin ? 1 : 0
        ], [
            'id_project' => $project_id,
            'id_user' => $user_id
        ]);

        return ['success' => true];
    }

    // Получить список всех доступных прав (для UI)
    public static function getAvailablePermissions(): array {
        return self::PERMISSIONS;
    }

    // Получить дефолтные права (для UI)
    public static function getDefaultPermissions(): array {
        return self::DEFAULT_PERMISSIONS;
    }
}

?>
