<?php
/**
 * Authentication Class
 * Handles user and admin authentication
 */

class Auth {
    private static $instance = null;
    private $user = null;
    private $admin = null;
    private $userType = null;
    
    private function __construct() {
        $this->loadFromSession();
    }
    
    public static function getInstance() {
        if (self::$instance === null) {
            self::$instance = new self();
        }
        return self::$instance;
    }
    
    /**
     * Load user/admin from session
     */
    private function loadFromSession() {
        if (isset($_SESSION['user_id']) && isset($_SESSION['user_type'])) {
            $this->userType = $_SESSION['user_type'];
            
            if ($this->userType === 'user') {
                $this->user = dbFetch(
                    "SELECT u.*, 
                            COALESCE(w.balance, 0) as balance, 
                            COALESCE(w.demo_balance, 10000) as demo_balance, 
                            COALESCE(w.bonus_balance, 0) as bonus_balance,
                            COALESCE(w.total_trades, 0) as total_trades
                     FROM users u 
                     LEFT JOIN user_wallets w ON u.id = w.user_id 
                     WHERE u.id = :id AND u.status = 'active'",
                    ['id' => $_SESSION['user_id']]
                );
                
                // Create wallet if doesn't exist
                if ($this->user && !dbExists('user_wallets', 'user_id = :uid', ['uid' => $this->user['id']])) {
                    dbInsert('user_wallets', [
                        'user_id' => $this->user['id'],
                        'balance' => 0,
                        'demo_balance' => defined('DEMO_BALANCE') ? DEMO_BALANCE : 10000
                    ]);
                }
            } elseif ($this->userType === 'admin') {
                $this->admin = dbFetch(
                    "SELECT * FROM admin_users WHERE id = :id AND status = 'active'",
                    ['id' => $_SESSION['user_id']]
                );
            }
        }
    }
    
    /**
     * User Login
     */
    public function loginUser($email, $password, $remember = false) {
        $user = dbFetch(
            "SELECT * FROM users WHERE email = :email",
            ['email' => $email]
        );
        
        if (!$user) {
            return ['success' => false, 'error' => 'Invalid email or password'];
        }
        
        if ($user['status'] === 'blocked') {
            return ['success' => false, 'error' => 'Your account has been blocked. Reason: ' . ($user['block_reason'] ?? 'Contact support')];
        }
        
        if ($user['status'] !== 'active') {
            return ['success' => false, 'error' => 'Your account is not active'];
        }
        
        if (!verifyPassword($password, $user['password'])) {
            return ['success' => false, 'error' => 'Invalid email or password'];
        }
        
        // Update last login
        dbUpdate('users', [
            'last_login' => date('Y-m-d H:i:s'),
            'last_ip' => getClientIp()
        ], 'id = :id', ['id' => $user['id']]);
        
        // Set session
        $_SESSION['user_id'] = $user['id'];
        $_SESSION['user_type'] = 'user';
        
        // Create session record
        $sessionToken = generateToken(64);
        dbInsert('user_sessions', [
            'user_id' => $user['id'],
            'session_token' => hash('sha256', $sessionToken),
            'ip_address' => getClientIp(),
            'user_agent' => getUserAgent(),
            'device_type' => getDeviceType(),
            'last_activity' => date('Y-m-d H:i:s'),
            'expires_at' => date('Y-m-d H:i:s', time() + ($remember ? REMEMBER_ME_LIFETIME : SESSION_LIFETIME))
        ]);
        
        if ($remember) {
            setcookie('remember_token', $sessionToken, time() + REMEMBER_ME_LIFETIME, '/', '', true, true);
        }
        
        // Log activity
        logActivity('user', $user['id'], 'login', 'User logged in');
        
        $this->user = $user;
        $this->userType = 'user';
        
        return ['success' => true, 'user' => $user];
    }
    
    /**
     * Admin Login
     */
    public function loginAdmin($username, $password) {
        $admin = dbFetch(
            "SELECT * FROM admin_users WHERE (username = :username OR email = :username)",
            ['username' => $username]
        );
        
        if (!$admin) {
            return ['success' => false, 'error' => 'Invalid credentials'];
        }
        
        if ($admin['status'] !== 'active') {
            return ['success' => false, 'error' => 'Your account is not active'];
        }
        
        if (!verifyPassword($password, $admin['password'])) {
            return ['success' => false, 'error' => 'Invalid credentials'];
        }
        
        // Check IP whitelist
        if (!empty($admin['ip_whitelist'])) {
            $allowedIps = explode(',', $admin['ip_whitelist']);
            $clientIp = getClientIp();
            if (!in_array($clientIp, array_map('trim', $allowedIps))) {
                return ['success' => false, 'error' => 'Access denied from this IP address'];
            }
        }
        
        // Update last login
        dbUpdate('admin_users', [
            'last_login' => date('Y-m-d H:i:s'),
            'last_ip' => getClientIp()
        ], 'id = :id', ['id' => $admin['id']]);
        
        // Set session
        $_SESSION['user_id'] = $admin['id'];
        $_SESSION['user_type'] = 'admin';
        $_SESSION['admin_role'] = $admin['role'];
        
        // Log activity
        logActivity('admin', $admin['id'], 'login', 'Admin logged in');
        
        $this->admin = $admin;
        $this->userType = 'admin';
        
        return ['success' => true, 'admin' => $admin];
    }
    
    /**
     * User Registration
     */
    public function registerUser($data) {
        // Validate email
        if (!isValidEmail($data['email'])) {
            return ['success' => false, 'error' => 'Invalid email address'];
        }
        
        // Check if email exists
        if (dbExists('users', 'email = :email', ['email' => $data['email']])) {
            return ['success' => false, 'error' => 'Email already registered'];
        }
        
        // Validate password
        if (!isStrongPassword($data['password'])) {
            return ['success' => false, 'error' => 'Password must be at least 8 characters with uppercase, lowercase, and numbers'];
        }
        
        // Validate phone if provided
        if (!empty($data['phone']) && !isValidPhone($data['phone'])) {
            return ['success' => false, 'error' => 'Invalid phone number'];
        }
        
        // Check referral code
        $referredBy = null;
        if (!empty($data['referral_code'])) {
            $referrer = dbFetch(
                "SELECT id FROM users WHERE referral_code = :code AND status = 'active'",
                ['code' => $data['referral_code']]
            );
            if ($referrer) {
                $referredBy = $referrer['id'];
            }
        }
        
        try {
            dbBeginTransaction();
            
            // Create user
            $userId = dbInsert('users', [
                'user_id' => generateUserId(),
                'email' => $data['email'],
                'phone' => $data['phone'] ?? null,
                'password' => hashPassword($data['password']),
                'first_name' => $data['first_name'] ?? null,
                'last_name' => $data['last_name'] ?? null,
                'referral_code' => generateReferralCode(),
                'referred_by' => $referredBy,
                'status' => 'active'
            ]);
            
            if (!$userId) {
                throw new Exception('Failed to create user');
            }
            
            // Create wallet
            dbInsert('user_wallets', [
                'user_id' => $userId,
                'balance' => 0,
                'demo_balance' => defined('DEMO_BALANCE') ? DEMO_BALANCE : 10000
            ]);
            
            // Create referral record
            if ($referredBy) {
                dbInsert('referrals', [
                    'referrer_id' => $referredBy,
                    'referred_id' => $userId
                ]);
            }
            
            // Add welcome bonus
            $welcomeBonus = getSetting('welcome_bonus', WELCOME_BONUS_PERCENT);
            if ($welcomeBonus > 0) {
                // Welcome bonus will be applied on first deposit
            }
            
            dbCommit();
            
            // Log activity
            logActivity('user', $userId, 'registration', 'New user registered');
            
            return ['success' => true, 'user_id' => $userId];
            
        } catch (Exception $e) {
            dbRollback();
            error_log("Registration Error: " . $e->getMessage());
            return ['success' => false, 'error' => 'Registration failed. Please try again.'];
        }
    }
    
    /**
     * Logout
     */
    public function logout() {
        if ($this->userType === 'user' && $this->user) {
            logActivity('user', $this->user['id'], 'logout', 'User logged out');
            
            // Delete session records
            dbDelete('user_sessions', 'user_id = :id', ['id' => $this->user['id']]);
        } elseif ($this->userType === 'admin' && $this->admin) {
            logActivity('admin', $this->admin['id'], 'logout', 'Admin logged out');
        }
        
        // Clear session
        $_SESSION = [];
        session_destroy();
        
        // Clear remember cookie
        if (isset($_COOKIE['remember_token'])) {
            setcookie('remember_token', '', time() - 3600, '/', '', true, true);
        }
        
        $this->user = null;
        $this->admin = null;
        $this->userType = null;
    }
    
    /**
     * Check if user is logged in
     */
    public function isUserLoggedIn() {
        return $this->userType === 'user' && $this->user !== null;
    }
    
    /**
     * Check if admin is logged in
     */
    public function isAdminLoggedIn() {
        return $this->userType === 'admin' && $this->admin !== null;
    }
    
    /**
     * Alias for isAdminLoggedIn (shorthand)
     */
    public function isAdmin() {
        return $this->isAdminLoggedIn();
    }
    
    /**
     * Get current user
     */
    public function getUser() {
        return $this->user;
    }
    
    /**
     * Get current admin
     */
    public function getAdmin() {
        return $this->admin;
    }
    
    /**
     * Get user ID
     */
    public function getUserId() {
        return $this->user['id'] ?? null;
    }
    
    /**
     * Get admin ID
     */
    public function getAdminId() {
        return $this->admin['id'] ?? null;
    }
    
    /**
     * Check admin role
     */
    public function hasRole($roles) {
        if (!$this->admin) return false;
        
        if (!is_array($roles)) {
            $roles = [$roles];
        }
        
        return in_array($this->admin['role'], $roles);
    }
    
    /**
     * Require user login
     */
    public function requireUser() {
        if (!$this->isUserLoggedIn()) {
            if (isAjax()) {
                jsonError('Please login to continue', 401);
            }
            redirect(USER_URL . '/login.php', 'Please login to continue', 'warning');
        }
    }
    
    /**
     * Require admin login
     */
    public function requireAdmin($roles = null) {
        if (!$this->isAdminLoggedIn()) {
            if (isAjax()) {
                jsonError('Unauthorized access', 401);
            }
            redirect(ADMIN_URL . '/login.php', 'Please login to continue', 'warning');
        }
        
        if ($roles !== null && !$this->hasRole($roles)) {
            if (isAjax()) {
                jsonError('Access denied', 403);
            }
            redirect(ADMIN_URL . '/dashboard.php', 'Access denied', 'error');
        }
    }
    
    /**
     * Update user password
     */
    public function updatePassword($currentPassword, $newPassword) {
        if (!$this->user) {
            return ['success' => false, 'error' => 'Not logged in'];
        }
        
        if (!verifyPassword($currentPassword, $this->user['password'])) {
            return ['success' => false, 'error' => 'Current password is incorrect'];
        }
        
        if (!isStrongPassword($newPassword)) {
            return ['success' => false, 'error' => 'New password must be at least 8 characters with uppercase, lowercase, and numbers'];
        }
        
        dbUpdate('users', [
            'password' => hashPassword($newPassword)
        ], 'id = :id', ['id' => $this->user['id']]);
        
        logActivity('user', $this->user['id'], 'password_change', 'Password changed');
        
        return ['success' => true, 'message' => 'Password updated successfully'];
    }
    
    /**
     * Refresh user data
     */
    public function refreshUser() {
        if ($this->user) {
            $this->user = dbFetch(
                "SELECT u.*, 
                        COALESCE(w.balance, 0) as balance, 
                        COALESCE(w.demo_balance, 10000) as demo_balance, 
                        COALESCE(w.bonus_balance, 0) as bonus_balance,
                        COALESCE(w.total_trades, 0) as total_trades
                 FROM users u 
                 LEFT JOIN user_wallets w ON u.id = w.user_id 
                 WHERE u.id = :id",
                ['id' => $this->user['id']]
            );
        }
        return $this->user ?: [];
    }
}

// Helper function
function auth() {
    return Auth::getInstance();
}
