<?php
/**
 * Unified 5-Layer Authorization & Ownership Guard
 * Defense-in-Depth: Authentication -> Role -> Permission -> Ownership/Scope -> Validation
 * Eliminates IDOR and unauthorized horizontal privilege escalations
 */

require_once __DIR__ . '/Auth.php';
require_once __DIR__ . '/../Core/Exceptions/AuthenticationException.php';
require_once __DIR__ . '/../Core/Exceptions/AuthorizationException.php';
require_once __DIR__ . '/../Core/Exceptions/NotFoundException.php';
require_once __DIR__ . '/../Models/Store.php';
require_once __DIR__ . '/../Models/Order.php';
require_once __DIR__ . '/../Models/Review.php';

class AuthGuard {
    /**
     * Layer 1: Require Authenticated User
     */
    public static function requireAuth(): int {
        if (!Auth::check()) {
            throw new AuthenticationException('กรุณาเข้าสู่ระบบก่อนดำเนินการ');
        }
        return (int)Auth::id();
    }

    /**
     * Layer 2: Require User to have specific Role(s)
     */
    public static function requireRole($roles): void {
        self::requireAuth();
        $userRoles = Auth::roles();
        $rolesList = (array)$roles;

        foreach ($rolesList as $role) {
            if (in_array($role, $userRoles, true)) {
                return;
            }
        }

        throw new AuthorizationException('คุณไม่มีบทบาทที่ได้รับอนุญาตให้เข้าถึงส่วนนี้');
    }

    /**
     * Layer 3: Require Admin Permission
     */
    public static function requirePermission(string $permission): void {
        self::requireAuth();
        
        if (!Auth::isAdmin()) {
            throw new AuthorizationException('ส่วนนี้สงวนไว้สำหรับผู้ดูแลระบบเท่านั้น');
        }

        require_once __DIR__ . '/../Middleware/AdminMiddleware.php';
        if (!AdminMiddleware::can($permission)) {
            throw new AuthorizationException("คุณไม่มีสิทธิ์ [{$permission}] ในการดำเนินการนี้");
        }
    }

    /**
     * Layer 4.1: Require Resource Ownership (e.g. Address, Notification, Account Settings)
     */
    public static function requireOwnership(int $resourceOwnerId, ?string $errorMessage = null): void {
        $currentUserId = self::requireAuth();

        // Admins can bypass standard user ownership if permitted
        if (Auth::isAdmin()) {
            return;
        }

        if ($currentUserId !== $resourceOwnerId) {
            throw new AuthorizationException($errorMessage ?? 'คุณไม่มีสิทธิ์เข้าถึงหรือจัดการข้อมูลของผู้ใช้อื่น');
        }
    }

    /**
     * Layer 4.2: Require Store Ownership for Seller Actions
     */
    public static function requireStoreOwnership(int $storeId, ?string $errorMessage = null): array {
        $userId = self::requireAuth();
        $store = (new Store())->findById($storeId);

        if (!$store) {
            throw new NotFoundException('ไม่พบร้านค้าที่ระบุในระบบ');
        }

        if (Auth::isAdmin()) {
            return $store;
        }

        if ((int)$store['user_id'] !== $userId) {
            throw new AuthorizationException($errorMessage ?? 'คุณไม่ใช่เจ้าของร้านค้านี้ จึงไม่สามารถจัดการข้อมูลได้');
        }

        return $store;
    }

    /**
     * Layer 4.3: Require Order Access (Buyer, Store Owner, or Admin)
     */
    public static function requireOrderAccess(int $orderId): array {
        $userId = self::requireAuth();
        $order = (new Order())->findById($orderId);

        if (!$order) {
            throw new NotFoundException('ไม่พบข้อมูลคำสั่งซื้อในระบบ');
        }

        if (Auth::isAdmin()) {
            return $order;
        }

        // Buyer access
        if ((int)$order['customer_id'] === $userId) {
            return $order;
        }

        // Seller access
        $store = (new Store())->findById((int)$order['store_id']);
        if ($store && (int)$store['user_id'] === $userId) {
            return $order;
        }

        throw new AuthorizationException('คุณไม่มีสิทธิ์เข้าถึงข้อมูลคำสั่งซื้อนี้');
    }
}
