<?php
require_once __DIR__ . '/../classes/SystemSettings.php';

/**
 * Auth Class for handling user authentication and authorization.
 */
class Auth {
    private $conn;

    public function __construct($conn) {
        $this->conn = $conn;
    }

    public function requireLogin() {
        if (!isset($_SESSION['user_id'])) {
            header('Location: /IMS/login.php');
            exit();
        }
        $user = $this->loadUserSessionRow((int)$_SESSION['user_id']);
        if (!$user) {
            $this->clearInvalidSession();
            header('Location: /IMS/login.php?session_expired=1');
            exit();
        }
        $_SESSION['role'] = $user['role'];
        $_SESSION['branch_id'] = $user['branch_id'];
        $_SESSION['terminal_id'] = $user['terminal_id'] ?? null;

        $settings = new SystemSettings();
        if (!$settings->maintenanceAccessAllowed($user['role'], $user['branch_id'])) {
            $this->clearInvalidSession();
            header('Location: /IMS/login.php?maintenance=1');
            exit();
        }
    }

    private function loadUserSessionRow($userId) {
        $this->requireConnection();
        try {
            $stmt = $this->conn->prepare('SELECT role, branch_id, terminal_id FROM users WHERE user_id = ?');
            $stmt->execute([$userId]);
            return $stmt->fetch(PDO::FETCH_ASSOC) ?: null;
        } catch (Throwable $e) {
            if (stripos($e->getMessage(), 'terminal_id') === false) {
                error_log('Auth user lookup failed: ' . $e->getMessage());
                return null;
            }
            try {
                $stmt = $this->conn->prepare('SELECT role, branch_id FROM users WHERE user_id = ?');
                $stmt->execute([$userId]);
                $user = $stmt->fetch(PDO::FETCH_ASSOC) ?: null;
                if ($user) {
                    $user['terminal_id'] = null;
                }
                return $user;
            } catch (Throwable $fallbackError) {
                error_log('Auth fallback user lookup failed: ' . $fallbackError->getMessage());
                return null;
            }
        }
    }

    private function clearInvalidSession() {
        $_SESSION = [];
        if (ini_get('session.use_cookies')) {
            $params = session_get_cookie_params();
            setcookie(session_name(), '', time() - 42000, $params['path'], $params['domain'], $params['secure'], $params['httponly']);
        }
        session_destroy();
    }

    private function requireConnection() {
        if (!$this->conn instanceof PDO) {
            error_log('Auth attempted to use an unavailable database connection.');
            http_response_code(503);
            echo 'Database connection is unavailable. Please try again shortly.';
            exit();
        }
    }

    private function fetchRole($userId) {
        $this->requireConnection();
        try {
            $stmt = $this->conn->prepare('SELECT role FROM users WHERE user_id = ?');
            $stmt->execute([$userId]);
            return strtolower(trim((string)$stmt->fetchColumn()));
        } catch (Throwable $e) {
            error_log('Error fetching user role: ' . $e->getMessage());
            return '';
        }
    }

    public function isSuperAdmin($userId) {
        $role = $this->fetchRole($userId);
        return $role === 'super_admin' || $role === 'admin';
    }

    public function isWarehousePersonnel($userId) {
        return $this->fetchRole($userId) === 'warehouse';
    }

    public function isController($userId) {
        return $this->fetchRole($userId) === 'controller';
    }

    public function isBranchManager($userId) {
        $role = $this->fetchRole($userId);
        return $role === 'branch_manager' || $role === 'branch';
    }

    public function isSalesAssistant($userId) {
        $role = $this->fetchRole($userId);
        return $role === 'sales_assistant' || $role === 'sales';
    }

    public function getUserBranch($userId) {
        $this->requireConnection();
        try {
            $stmt = $this->conn->prepare('SELECT branch_id FROM users WHERE user_id = ?');
            $stmt->execute([$userId]);
            return $stmt->fetchColumn();
        } catch (Throwable $e) {
            error_log('Error fetching user branch: ' . $e->getMessage());
            return null;
        }
    }

    public function getDashboardUrl() {
        $basePath = '/IMS/';
        if (!isset($_SESSION['user_id'])) {
            return $basePath . 'login.php';
        }
        if ($this->isSuperAdmin($_SESSION['user_id'])) {
            return $basePath . 'views/dashboard/admin.php';
        }
        if ($this->isController($_SESSION['user_id'])) {
            return $basePath . 'views/dashboard/controller.php';
        }
        if ($this->isWarehousePersonnel($_SESSION['user_id'])) {
            return $basePath . 'views/dashboard/warehouse.php';
        }
        if ($this->isBranchManager($_SESSION['user_id'])) {
            return $basePath . 'views/dashboard/branch.php';
        }
        if ($this->isSalesAssistant($_SESSION['user_id'])) {
            return $basePath . 'views/dashboard/assistant.php';
        }
        return $basePath . 'index.php';
    }

    public function enforceSuperAdminPrivileges($userId) {
        if (!$this->isSuperAdmin($userId)) {
            header('Location: /IMS/unauthorized.php');
            exit();
        }
    }

    public function enforceSuperAdminOrWarehousePrivileges($userId) {
        if (!$this->isSuperAdmin($userId) && !$this->isWarehousePersonnel($userId)) {
            header('Location: /IMS/unauthorized.php');
            exit();
        }
    }

    public function getUserRole($userId) {
        $role = $this->fetchRole($userId);
        return $role !== '' ? $role : null;
    }

    public function getUserName($userId) {
        $this->requireConnection();
        try {
            $stmt = $this->conn->prepare('SELECT username FROM users WHERE user_id = :user_id');
            $stmt->bindParam(':user_id', $userId, PDO::PARAM_INT);
            $stmt->execute();
            $result = $stmt->fetch(PDO::FETCH_ASSOC);
            return $result ? $result['username'] : null;
        } catch (Throwable $e) {
            error_log('Error getting username: ' . $e->getMessage());
            return null;
        }
    }
}
?>