<?php
namespace App\Core;

use App\Core\Database;

class BusinessPermission
{
    /*
    ---------------------------------------------------------
    Role Code
    ---------------------------------------------------------
    */

    public static function roleCode(): string
    {
        if (session_status() !== PHP_SESSION_ACTIVE) {
            session_start();
        }

        return (string)(
            $_SESSION['role']
            ?? $_SESSION['user_role']
            ?? ''
        );
    }

    /*
    ---------------------------------------------------------
    Resolve Role ID from roles table
    ---------------------------------------------------------
    */

    public static function roleId(): int
    {
        if (session_status() !== PHP_SESSION_ACTIVE) {
            session_start();
        }

        if (!empty($_SESSION['role_id'])) {
            return (int)$_SESSION['role_id'];
        }

        $roleCode = self::roleCode();

        if (!$roleCode) {
            return 0;
        }

        try {

            $db = Database::getInstance();

            $stmt = $db->prepare("
                SELECT id
                FROM roles
                WHERE code = ?
                LIMIT 1
            ");

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

            $roleId = (int)$stmt->fetchColumn();

            if ($roleId > 0) {

                $_SESSION['role_id'] = $roleId;

                error_log(
                    "ROLE RESOLVED: "
                    . $roleCode
                    . " => "
                    . $roleId
                );

                return $roleId;

            }

        } catch (\Throwable $e) {

            error_log(
                "ROLE RESOLVE ERROR: "
                . $e->getMessage()
            );

        }

        return 0;
    }

    /*
    ---------------------------------------------------------
    Permission Check
    ---------------------------------------------------------
    */

    public static function can(string $permissionKey): bool
    {
        $roleCode = self::roleCode();

        if ($roleCode === 'super_admin') {
            return true;
        }

        $roleId = self::roleId();

        if ($roleId <= 0) {
            return false;
        }

        try {

            $db = Database::getInstance();

            $stmt = $db->prepare("
                SELECT allowed
                FROM business_role_permissions
                WHERE role_id = ?
                AND permission_key = ?
                LIMIT 1
            ");

            $stmt->execute([
                $roleId,
                $permissionKey
            ]);

            return (int)$stmt->fetchColumn() === 1;

        } catch (\Throwable $e) {

            error_log(
                "PERMISSION ERROR: "
                . $e->getMessage()
            );

            return false;
        }
    }

    /*
    ---------------------------------------------------------
    CRUD Check
    ---------------------------------------------------------
    */

    public static function crud(string $entityKey, string $action): bool
    {
        $roleCode = self::roleCode();

        if ($roleCode === 'super_admin') {
            return true;
        }

        $roleId = self::roleId();

        $map = [
            'view' => 'can_view',
            'create' => 'can_create',
            'update' => 'can_update',
            'delete' => 'can_delete',
        ];

        $column = $map[$action] ?? null;

        if (!$column) {
            return false;
        }

        try {

            $db = Database::getInstance();

            $stmt = $db->prepare("
                SELECT {$column}
                FROM business_crud_policies
                WHERE role_id = ?
                AND entity_key = ?
                LIMIT 1
            ");

            $stmt->execute([
                $roleId,
                $entityKey
            ]);

            return (int)$stmt->fetchColumn() === 1;

        } catch (\Throwable $e) {

            error_log(
                "CRUD ERROR: "
                . $e->getMessage()
            );

            return false;
        }
    }

    /*
    ---------------------------------------------------------
    Require Permission
    ---------------------------------------------------------
    */

    public static function requirePermission(string $permissionKey): void
    {
        if (!self::can($permissionKey)) {

            http_response_code(403);

            exit(
                "Access denied by business permission: "
                . htmlspecialchars(
                    $permissionKey,
                    ENT_QUOTES,
                    'UTF-8'
                )
            );
        }
    }

    /*
    ---------------------------------------------------------
    Require CRUD
    ---------------------------------------------------------
    */

    public static function requireCrud(string $entityKey, string $action): void
    {
        if (!self::crud($entityKey, $action)) {

            http_response_code(403);

            exit(
                "Access denied by business CRUD policy: "
                . htmlspecialchars(
                    $entityKey . ':' . $action,
                    ENT_QUOTES,
                    'UTF-8'
                )
            );
        }
    }
}
