<?php

namespace SSCI\Classes;

/**
 * Authentication Class
 * Handles user authentication and session management
 */
class Auth
{
    private Database $db;
    private array $config;

    public function __construct(Database $db, array $config)
    {
        $this->db = $db;
        $this->config = $config;
    }

    /**
     * Login user
     */
    public function login(string $email, string $password): bool
    {
        $user = $this->db->fetch(
            "SELECT * FROM users WHERE email = ? AND active = 1",
            [$email]
        );

        if (!$user) {
            return false;
        }

        if (!password_verify($password, $user['password'])) {
            return false;
        }

        $_SESSION['user_id'] = $user['id'];
        $_SESSION['email'] = $user['email'];
        $_SESSION['role'] = $user['role'];
        $_SESSION['name'] = $user['name'];
        $_SESSION['photo'] = $user['photo'];

        // Update last login
        $this->db->query(
            "UPDATE users SET last_login = NOW() WHERE id = ?",
            [$user['id']]
        );

        return true;
    }

    /**
     * Register user
     */
    public function register(array $data): bool
    {
        // Check if email already exists
        if ($this->db->fetch("SELECT id FROM users WHERE email = ?", [$data['email']])) {
            return false;
        }

        $password_hash = password_hash($data['password'], PASSWORD_BCRYPT);
        $verification_token = bin2hex(random_bytes(32));

        $this->db->query(
            "INSERT INTO users (name, email, password, role, phone, whatsapp, address, verification_token, created_at) 
             VALUES (?, ?, ?, ?, ?, ?, ?, ?, NOW())",
            [
                $data['name'],
                $data['email'],
                $password_hash,
                $data['role'] ?? 'guard',
                $data['phone'] ?? null,
                $data['whatsapp'] ?? null,
                $data['address'] ?? null,
                $verification_token,
            ]
        );

        return true;
    }

    /**
     * Check if user is authenticated
     */
    public function isAuthenticated(): bool
    {
        return isset($_SESSION['user_id']);
    }

    /**
     * Get current user
     */
    public function getCurrentUser(): ?array
    {
        if (!$this->isAuthenticated()) {
            return null;
        }

        return $this->db->fetch(
            "SELECT * FROM users WHERE id = ?",
            [$_SESSION['user_id']]
        );
    }

    /**
     * Check if user has permission
     */
    public function hasPermission(string $permission): bool
    {
        if (!$this->isAuthenticated()) {
            return false;
        }

        $roles = require __DIR__ . '/../../config/roles.php';
        $userRole = $_SESSION['role'] ?? null;

        if (!isset($roles[$userRole])) {
            return false;
        }

        $permissions = $roles[$userRole]['permissions'];

        return in_array('*', $permissions) || in_array($permission, $permissions);
    }

    /**
     * Check if user can access page
     */
    public function canAccessPage(string $page): bool
    {
        if (!$this->isAuthenticated()) {
            return false;
        }

        $roles = require __DIR__ . '/../../config/roles.php';
        $userRole = $_SESSION['role'] ?? null;

        if (!isset($roles[$userRole])) {
            return false;
        }

        return in_array($page, $roles[$userRole]['pages']);
    }

    /**
     * Logout user
     */
    public function logout(): void
    {
        session_destroy();
    }

    /**
     * Request password reset
     */
    public function requestPasswordReset(string $email): bool
    {
        $user = $this->db->fetch("SELECT id FROM users WHERE email = ?", [$email]);

        if (!$user) {
            return false;
        }

        $reset_token = bin2hex(random_bytes(32));
        $token_expiry = date('Y-m-d H:i:s', strtotime('+1 hour'));

        $this->db->query(
            "UPDATE users SET reset_token = ?, reset_token_expiry = ? WHERE id = ?",
            [$reset_token, $token_expiry, $user['id']]
        );

        // TODO: Send email with reset link

        return true;
    }

    /**
     * Reset password
     */
    public function resetPassword(string $token, string $password): bool
    {
        $user = $this->db->fetch(
            "SELECT id FROM users WHERE reset_token = ? AND reset_token_expiry > NOW()",
            [$token]
        );

        if (!$user) {
            return false;
        }

        $password_hash = password_hash($password, PASSWORD_BCRYPT);

        $this->db->query(
            "UPDATE users SET password = ?, reset_token = NULL, reset_token_expiry = NULL WHERE id = ?",
            [$password_hash, $user['id']]
        );

        return true;
    }

    /**
     * Invite user with activation token
     * Creates a new user account that requires email verification
     */
    public function inviteUser(array $data): ?string
    {
        // Check if email already exists
        if ($this->db->fetch("SELECT id FROM users WHERE email = ?", [$data['email']])) {
            return null;
        }

        // Generate activation token
        $verification_token = bin2hex(random_bytes(32));
        $token_expiry = date('Y-m-d H:i:s', strtotime('+7 days'));

        // Create user with inactive status and temporary password
        $temp_password = bin2hex(random_bytes(8));
        $password_hash = password_hash($temp_password, PASSWORD_BCRYPT);

        $this->db->query(
            "INSERT INTO users (name, email, password, role, phone, address, verification_token, verified_at, active, created_at) 
             VALUES (?, ?, ?, ?, ?, ?, ?, NULL, ?, NOW())",
            [
                $data['name'],
                $data['email'],
                $password_hash,
                $data['role'] ?? 'guard',
                $data['phone'] ?? null,
                $data['address'] ?? null,
                $verification_token,
                0  // Set as inactive until verified
            ]
        );

        return $verification_token;
    }

    /**
     * Verify user email with token
     */
    public function verifyEmail(string $token): bool
    {
        $user = $this->db->fetch(
            "SELECT id FROM users WHERE verification_token = ?",
            [$token]
        );

        if (!$user) {
            return false;
        }

        $this->db->query(
            "UPDATE users SET verified_at = NOW(), verification_token = NULL, active = 1 WHERE id = ?",
            [$user['id']]
        );

        return true;
    }

    /**
     * Check if email is verified
     */
    public function isEmailVerified(int $userId): bool
    {
        $user = $this->db->fetch(
            "SELECT verified_at FROM users WHERE id = ?",
            [$userId]
        );

        return $user && !empty($user['verified_at']);
    }

    /**
     * Resend verification email
     */
    public function resendVerificationToken(string $email): ?string
    {
        $user = $this->db->fetch(
            "SELECT id, verified_at FROM users WHERE email = ?",
            [$email]
        );

        if (!$user || !empty($user['verified_at'])) {
            return null; // User doesn't exist or already verified
        }

        $verification_token = bin2hex(random_bytes(32));

        $this->db->query(
            "UPDATE users SET verification_token = ? WHERE id = ?",
            [$verification_token, $user['id']]
        );

        return $verification_token;
    }

    /**
     * Get user by verification token
     */
    public function getUserByVerificationToken(string $token): ?array
    {
        return $this->db->fetch(
            "SELECT id, name, email, role FROM users WHERE verification_token = ?",
            [$token]
        );
    }

    /**
     * Audit log - track user actions
     */
    public function logAuditEntry(int $userId, string $action, string $description, ?array $metadata = null): bool
    {
        // Check if audit_logs table exists
        $tables = $this->db->fetchAll("SHOW TABLES LIKE 'audit_logs'");
        if (empty($tables)) {
            return false; // Table doesn't exist yet
        }

        return (bool)$this->db->query(
            "INSERT INTO audit_logs (user_id, action, description, metadata, created_at) VALUES (?, ?, ?, ?, NOW())",
            [
                $userId,
                $action,
                $description,
                $metadata ? json_encode($metadata) : null
            ]
        );
    }

    /**
     * Track login attempt
     */
    public function logLoginAttempt(string $email, bool $success): void
    {
        // Check if login_attempts table exists
        $tables = $this->db->fetchAll("SHOW TABLES LIKE 'login_attempts'");
        if (empty($tables)) {
            return;
        }

        $this->db->query(
            "INSERT INTO login_attempts (email, success, ip_address, user_agent, created_at) VALUES (?, ?, ?, ?, NOW())",
            [
                $email,
                $success ? 1 : 0,
                $_SERVER['REMOTE_ADDR'] ?? 'unknown',
                $_SERVER['HTTP_USER_AGENT'] ?? 'unknown'
            ]
        );
    }

    /**
     * Check for suspicious login attempts
     */
    public function checkSuspiciousActivity(string $email): bool
    {
        // Check if login_attempts table exists
        $tables = $this->db->fetchAll("SHOW TABLES LIKE 'login_attempts'");
        if (empty($tables)) {
            return false;
        }

        // Get failed login attempts in last 15 minutes
        $attempts = $this->db->fetch(
            "SELECT COUNT(*) as count FROM login_attempts WHERE email = ? AND success = 0 AND created_at > DATE_SUB(NOW(), INTERVAL 15 MINUTE)",
            [$email]
        );

        // Flag as suspicious if more than 5 failed attempts
        return ($attempts['count'] ?? 0) > 5;
    }
}
