<?php

class Permissions {
    const VIEW_CHANNEL = 1;
    const SEND_MESSAGES = 2;
    const MANAGE_MESSAGES = 4;
    const MANAGE_CHANNELS = 8;
    const MANAGE_SERVER = 16;
    const ADMINISTRATOR = 32;
    const CREATE_THREAD = 64;
    const MANAGE_TAGS = 128;
    const PIN_THREADS = 256;
    const LOCK_THREADS = 512;
    const SEND_MESSAGES_IN_THREADS = 1024;
    const SPEAK = 2048;
    const CREATE_EVENT = 4096;
    const EDIT_EVENT = 8192;
    const DELETE_EVENT = 16384;
    const CREATE_ANNOUNCEMENT = 32768;
    const CREATE_POLL = 65536;

    public static function hasPermission($user_id, $server_id, $permission) {
        $stmt = db()->prepare("SELECT is_admin FROM users WHERE id = ?");
        $stmt->execute([$user_id]);
        $user = $stmt->fetch();
        if ($user && $user['is_admin']) return true;

        $stmt = db()->prepare("SELECT owner_id FROM servers WHERE id = ?");
        $stmt->execute([$server_id]);
        $server = $stmt->fetch();
        if ($server && $server['owner_id'] == $user_id) return true;

        // Aggregate permissions from user's roles AND the @everyone role
        $stmt = db()->prepare("
            SELECT BIT_OR(r.permissions) as total_perms 
            FROM roles r
            LEFT JOIN user_roles ur ON r.id = ur.role_id AND ur.user_id = ?
            WHERE r.server_id = ? AND (ur.user_id IS NOT NULL OR r.name = '@everyone' OR r.name = 'Everyone')
        ");
        $stmt->execute([$user_id, $server_id]);
        $row = $stmt->fetch();
        $perms = (int)($row['total_perms'] ?? 0);

        if ($perms & self::ADMINISTRATOR) return true;
        return ($perms & $permission) === $permission;
    }

    public static function canViewChannel($user_id, $channel_id) {
        return self::canDoInChannel($user_id, $channel_id, self::VIEW_CHANNEL);
    }

    public static function canSendInChannel($user_id, $channel_id) {
        return self::canDoInChannel($user_id, $channel_id, self::SEND_MESSAGES);
    }

    public static function canDoInChannel($user_id, $channel_id, $permission) {
        $stmt = db()->prepare("SELECT server_id FROM channels WHERE id = ?");
        $stmt->execute([$channel_id]);
        $c = $stmt->fetch();
        if (!$c) return false;
        $server_id = $c['server_id'];

        // Check if owner or admin
        if (self::hasPermission($user_id, $server_id, self::ADMINISTRATOR)) return true;

        // Fetch all relevant overrides
        // 1. @everyone role
        // 2. User's roles
        // 3. User specifically
        
        // Use a single query to get all relevant overrides
        $stmt = db()->prepare("
            SELECT cp.user_id, cp.role_id, cp.allow_permissions, cp.deny_permissions, r.name as role_name
            FROM channel_permissions cp
            LEFT JOIN roles r ON cp.role_id = r.id
            LEFT JOIN user_roles ur ON cp.role_id = ur.role_id AND ur.user_id = ?
            WHERE cp.channel_id = ? AND (
                cp.user_id = ? OR 
                ur.user_id IS NOT NULL OR 
                r.name = '@everyone' OR 
                r.name = 'Everyone'
            )
        ");
        $stmt->execute([$user_id, $channel_id, $user_id]);
        $overrides = $stmt->fetchAll();

        if (empty($overrides)) {
            // No overrides, fallback to global permissions
            return self::hasPermission($user_id, $server_id, $permission);
        }

        // Resolution order (simplified but effective):
        // User overrides > Role overrides > @everyone
        
        $user_override = null;
        $role_allow = 0;
        $role_deny = 0;
        $everyone_override = null;

        foreach($overrides as $o) {
            if ($o['user_id'] == $user_id) {
                $user_override = $o;
            } elseif ($o['role_name'] === '@everyone' || $o['role_name'] === 'Everyone') {
                $everyone_override = $o;
            } else {
                $role_allow |= (int)$o['allow_permissions'];
                $role_deny |= (int)$o['deny_permissions'];
            }
        }

        // 1. User specifically
        if ($user_override) {
            if ($user_override['allow_permissions'] & $permission) return true;
            if ($user_override['deny_permissions'] & $permission) return false;
        }

        // 2. Roles
        if ($role_allow & $permission) return true;
        if ($role_deny & $permission) return false;

        // 3. @everyone
        if ($everyone_override) {
            if ($everyone_override['allow_permissions'] & $permission) return true;
            if ($everyone_override['deny_permissions'] & $permission) return false;
        }

        // Fallback to base permissions
        return self::hasPermission($user_id, $server_id, $permission);
    }
}
