<?php

declare(strict_types=1);

/**
 * SuperAdminAuth
 * 
 * Handles authentication for super admin panel
 */
class SuperAdminAuth
{
    private const SESSION_KEY = 'super_admin_id';
    private const SESSION_TOKEN_KEY = 'super_admin_token';
    private const COOKIE_NAME = 'super_admin_session';
    private const SESSION_DURATION = 86400; // 24 hours

    /**
     * All available super admin permissions
     */
    public const PERMISSIONS = [
        'users_view' => 'View Users',
        'users_manage' => 'Manage Users',
        'users_ban' => 'Ban/Unban Users',
        'users_delete' => 'Delete Users',
        'workspaces_view' => 'View Workspaces',
        'workspaces_manage' => 'Manage Workspaces',
        'workspaces_ban' => 'Ban/Unban Workspaces',
        'workspaces_delete' => 'Delete Workspaces',
        'workspaces_login' => 'Login to Workspaces',
        'billing_view' => 'View Billing',
        'billing_manage' => 'Manage Billing',
        'plans_view' => 'View Plans',
        'plans_manage' => 'Manage Plans',
        'discounts_view' => 'View Discounts',
        'discounts_manage' => 'Manage Discounts',
        'settings_view' => 'View Settings',
        'settings_manage' => 'Manage Settings',
        'admins_view' => 'View Admins',
        'admins_manage' => 'Manage Admins',
        'analytics_view' => 'View Analytics',
        'activity_log_view' => 'View Activity Log',
    ];

    /**
     * Role-based default permissions
     */
    public const ROLE_PERMISSIONS = [
        'owner' => ['*'], // All permissions
        'admin' => [
            'users_view', 'users_manage', 'users_ban',
            'workspaces_view', 'workspaces_manage', 'workspaces_ban', 'workspaces_login',
            'billing_view', 'billing_manage',
            'plans_view', 'plans_manage',
            'discounts_view', 'discounts_manage',
            'settings_view',
            'analytics_view', 'activity_log_view',
        ],
        'support' => [
            'users_view',
            'workspaces_view', 'workspaces_login',
            'billing_view',
            'activity_log_view',
        ],
        'finance' => [
            'billing_view', 'billing_manage',
            'plans_view',
            'discounts_view', 'discounts_manage',
            'analytics_view',
        ],
    ];

    /**
     * Start session if not started
     */
    private static function ensureSession(): void
    {
        if (session_status() === PHP_SESSION_NONE) {
            session_start();
        }
    }

    /**
     * Login a super admin
     */
    public static function login(string $email, string $password): array
    {
        $pdo = getPDO();
        
        $stmt = $pdo->prepare('SELECT * FROM super_admins WHERE email = ? AND is_active = 1');
        $stmt->execute([$email]);
        $admin = $stmt->fetch();

        if (!$admin || !password_verify($password, $admin['password_hash'])) {
            return ['success' => false, 'error' => 'Invalid email or password'];
        }

        // Create session token
        $token = bin2hex(random_bytes(32));
        $expiresAt = date('Y-m-d H:i:s', time() + self::SESSION_DURATION);

        $stmt = $pdo->prepare('
            INSERT INTO super_admin_sessions (admin_id, session_token, ip_address, user_agent, expires_at)
            VALUES (?, ?, ?, ?, ?)
        ');
        $stmt->execute([
            $admin['id'],
            $token,
            $_SERVER['REMOTE_ADDR'] ?? null,
            $_SERVER['HTTP_USER_AGENT'] ?? null,
            $expiresAt
        ]);

        // Update last login
        $stmt = $pdo->prepare('UPDATE super_admins SET last_login_at = NOW() WHERE id = ?');
        $stmt->execute([$admin['id']]);

        // Set session
        self::ensureSession();
        $_SESSION[self::SESSION_KEY] = $admin['id'];
        $_SESSION[self::SESSION_TOKEN_KEY] = $token;

        // Set cookie
        setcookie(self::COOKIE_NAME, $token, time() + self::SESSION_DURATION, '/', '', true, true);

        // Log activity
        self::logActivity($admin['id'], 'login', null, null, ['ip' => $_SERVER['REMOTE_ADDR'] ?? null]);

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

    /**
     * Logout current super admin
     */
    public static function logout(): void
    {
        self::ensureSession();

        $adminId = $_SESSION[self::SESSION_KEY] ?? null;
        $token = $_SESSION[self::SESSION_TOKEN_KEY] ?? null;

        if ($token) {
            $pdo = getPDO();
            $stmt = $pdo->prepare('DELETE FROM super_admin_sessions WHERE session_token = ?');
            $stmt->execute([$token]);
        }

        if ($adminId) {
            self::logActivity($adminId, 'logout');
        }

        unset($_SESSION[self::SESSION_KEY], $_SESSION[self::SESSION_TOKEN_KEY]);
        setcookie(self::COOKIE_NAME, '', time() - 3600, '/', '', true, true);
    }

    /**
     * Get current logged in super admin
     */
    public static function getCurrentAdmin(): ?array
    {
        self::ensureSession();

        $adminId = $_SESSION[self::SESSION_KEY] ?? null;
        $token = $_SESSION[self::SESSION_TOKEN_KEY] ?? ($_COOKIE[self::COOKIE_NAME] ?? null);

        if (!$adminId || !$token) {
            return null;
        }

        $pdo = getPDO();

        // Verify session is valid
        $stmt = $pdo->prepare('
            SELECT sa.* FROM super_admins sa
            JOIN super_admin_sessions sas ON sa.id = sas.admin_id
            WHERE sas.session_token = ? AND sas.expires_at > NOW() AND sa.is_active = 1
        ');
        $stmt->execute([$token]);
        $admin = $stmt->fetch();

        if (!$admin) {
            self::logout();
            return null;
        }

        return $admin;
    }

    /**
     * Check if current admin has permission
     */
    public static function hasPermission(string $permission): bool
    {
        $admin = self::getCurrentAdmin();
        if (!$admin) {
            return false;
        }

        // Owner has all permissions
        if ($admin['role'] === 'owner') {
            return true;
        }

        $pdo = getPDO();
        $stmt = $pdo->prepare('
            SELECT allowed FROM super_admin_permissions 
            WHERE admin_id = ? AND permission_key = ?
        ');
        $stmt->execute([$admin['id'], $permission]);
        $result = $stmt->fetch();

        return $result && $result['allowed'];
    }

    /**
     * Require authentication - redirect if not logged in
     */
    public static function requireAuth(): void
    {
        if (!self::getCurrentAdmin()) {
            header('Location: /admin/login.php');
            exit;
        }
    }

    /**
     * Require specific permission
     */
    public static function requirePermission(string $permission): void
    {
        self::requireAuth();
        
        if (!self::hasPermission($permission)) {
            http_response_code(403);
            include __DIR__ . '/../../public/admin/403.php';
            exit;
        }
    }

    /**
     * Get admin permissions
     */
    public static function getAdminPermissions(int $adminId): array
    {
        $pdo = getPDO();
        
        // Get admin role
        $stmt = $pdo->prepare('SELECT role FROM super_admins WHERE id = ?');
        $stmt->execute([$adminId]);
        $admin = $stmt->fetch();

        if (!$admin) {
            return [];
        }

        // Owner has all permissions
        if ($admin['role'] === 'owner') {
            return array_keys(self::PERMISSIONS);
        }

        $stmt = $pdo->prepare('
            SELECT permission_key FROM super_admin_permissions 
            WHERE admin_id = ? AND allowed = 1
        ');
        $stmt->execute([$adminId]);
        
        return array_column($stmt->fetchAll(), 'permission_key');
    }

    /**
     * Log admin activity
     */
    public static function logActivity(int $adminId, string $action, ?string $entityType = null, ?int $entityId = null, ?array $details = null): void
    {
        $pdo = getPDO();
        $stmt = $pdo->prepare('
            INSERT INTO super_admin_activity_log (admin_id, action, entity_type, entity_id, details, ip_address)
            VALUES (?, ?, ?, ?, ?, ?)
        ');
        $stmt->execute([
            $adminId,
            $action,
            $entityType,
            $entityId,
            $details ? json_encode($details) : null,
            $_SERVER['REMOTE_ADDR'] ?? null
        ]);
    }

    /**
     * Create a new super admin
     */
    public static function createAdmin(string $name, string $email, string $password, string $role, array $permissions = [], ?int $createdBy = null): ?int
    {
        $pdo = getPDO();

        try {
            $pdo->beginTransaction();

            $stmt = $pdo->prepare('
                INSERT INTO super_admins (name, email, password_hash, role, created_by)
                VALUES (?, ?, ?, ?, ?)
            ');
            $stmt->execute([
                $name,
                $email,
                password_hash($password, PASSWORD_DEFAULT),
                $role,
                $createdBy
            ]);
            $adminId = (int)$pdo->lastInsertId();

            // Add permissions
            if (!empty($permissions)) {
                $stmt = $pdo->prepare('
                    INSERT INTO super_admin_permissions (admin_id, permission_key, allowed)
                    VALUES (?, ?, 1)
                ');
                foreach ($permissions as $permission) {
                    if (array_key_exists($permission, self::PERMISSIONS)) {
                        $stmt->execute([$adminId, $permission]);
                    }
                }
            }

            $pdo->commit();

            if ($createdBy) {
                self::logActivity($createdBy, 'create_admin', 'super_admin', $adminId, ['email' => $email, 'role' => $role]);
            }

            return $adminId;
        } catch (Exception $e) {
            $pdo->rollBack();
            return null;
        }
    }

    /**
     * Update admin permissions
     */
    public static function updatePermissions(int $adminId, array $permissions): bool
    {
        $pdo = getPDO();

        try {
            $pdo->beginTransaction();

            // Remove existing permissions
            $stmt = $pdo->prepare('DELETE FROM super_admin_permissions WHERE admin_id = ?');
            $stmt->execute([$adminId]);

            // Add new permissions
            $stmt = $pdo->prepare('
                INSERT INTO super_admin_permissions (admin_id, permission_key, allowed)
                VALUES (?, ?, 1)
            ');
            foreach ($permissions as $permission) {
                if (array_key_exists($permission, self::PERMISSIONS)) {
                    $stmt->execute([$adminId, $permission]);
                }
            }

            $pdo->commit();
            return true;
        } catch (Exception $e) {
            $pdo->rollBack();
            return false;
        }
    }
}
