<?php

class Auth {
    private $pdo;
    private $session;
    
    public function __construct($pdo) {
        $this->pdo = $pdo;
        $this->session = new Session();
    }
    
    public function login($email, $password) {
        try {
            // Find user by email with tenant information
            $stmt = $this->pdo->prepare("
                SELECT u.*, t.name as tenant_name, t.subdomain, t.slug as tenant_slug
                FROM users u 
                LEFT JOIN tenants t ON u.tenant_id = t.id 
                WHERE u.email = ? AND u.status = 'active'
            ");
            $stmt->execute([$email]);
            $user = $stmt->fetch(PDO::FETCH_ASSOC);
            
            if (!$user || !password_verify($password, $user['password'])) {
                return ['success' => false, 'message' => 'Invalid email or password'];
            }
            
            // Create session in sessions table
            $sessionToken = bin2hex(random_bytes(32));
            $expiresAt = date('Y-m-d H:i:s', strtotime('+30 days'));
            
            $stmt = $this->pdo->prepare("
                INSERT INTO sessions (user_id, tenant_id, team_id, token, ip_address, user_agent, last_activity, expires_at) 
                VALUES (?, ?, ?, ?, ?, ?, NOW(), ?)
            ");
            
            $stmt->execute([
                $user['id'],
                $user['tenant_id'],
                null, // team_id can be set later
                $sessionToken,
                $_SERVER['REMOTE_ADDR'] ?? '',
                $_SERVER['HTTP_USER_AGENT'] ?? '',
                $expiresAt
            ]);
            
            // Update last login and login count
            $stmt = $this->pdo->prepare("
                UPDATE users 
                SET last_login = NOW(), login_count = COALESCE(login_count, 0) + 1 
                WHERE id = ?
            ");
            $stmt->execute([$user['id']]);
            
            // Set session data
            $this->session->set('user_id', $user['id']);
            $this->session->set('session_token', $sessionToken);
            $this->session->set('tenant_id', $user['tenant_id']);
            $this->session->set('user_role', $user['role']);
            $this->session->set('user_email', $user['email']);
            $this->session->set('user_name', $user['first_name'] . ' ' . $user['last_name']);
            
            // Log the login in audit_logs
            $this->logAudit(
                $user['tenant_id'], 
                $user['id'], 
                'login', 
                'User logged in successfully',
                'user',
                $user['id']
            );
            
            return [
                'success' => true,
                'user' => [
                    'id' => $user['id'],
                    'name' => $user['first_name'] . ' ' . $user['last_name'],
                    'email' => $user['email'],
                    'role' => $user['role'],
                    'tenant_id' => $user['tenant_id'],
                    'tenant_name' => $user['tenant_name'],
                    'tenant_slug' => $user['tenant_slug']
                ]
            ];
            
        } catch (PDOException $e) {
            error_log("Login error: " . $e->getMessage());
            return ['success' => false, 'message' => 'Login failed. Please try again.'];
        }
    }
    
    public function logout() {
        $sessionToken = $this->session->get('session_token');
        $userId = $this->session->get('user_id');
        $tenantId = $this->session->get('tenant_id');
        
        if ($sessionToken) {
            try {
                $stmt = $this->pdo->prepare("DELETE FROM sessions WHERE token = ?");
                $stmt->execute([$sessionToken]);
                
                // Log logout in audit_logs
                if ($userId && $tenantId) {
                    $this->logAudit(
                        $tenantId, 
                        $userId, 
                        'logout', 
                        'User logged out',
                        'user',
                        $userId
                    );
                }
            } catch (PDOException $e) {
                error_log("Logout error: " . $e->getMessage());
            }
        }
        
        $this->session->destroy();
        return ['success' => true];
    }
    
    public function check() {
        $sessionToken = $this->session->get('session_token');
        $userId = $this->session->get('user_id');
        
        if (!$sessionToken || !$userId) {
            return false;
        }
        
        try {
            $stmt = $this->pdo->prepare("
                SELECT s.*, u.* 
                FROM sessions s 
                JOIN users u ON s.user_id = u.id 
                WHERE s.token = ? AND s.user_id = ? AND s.expires_at > NOW() AND u.status = 'active'
            ");
            $stmt->execute([$sessionToken, $userId]);
            $session = $stmt->fetch(PDO::FETCH_ASSOC);
            
            if ($session) {
                // Update last activity
                $stmt = $this->pdo->prepare("UPDATE sessions SET last_activity = NOW() WHERE id = ?");
                $stmt->execute([$session['id']]);
                return true;
            }
        } catch (PDOException $e) {
            error_log("Session check error: " . $e->getMessage());
        }
        
        return false;
    }
    
    public function user() {
        if (!$this->check()) {
            return null;
        }
        
        $userId = $this->session->get('user_id');
        
        try {
            $stmt = $this->pdo->prepare("
                SELECT 
                    u.id, u.first_name, u.last_name, u.email, u.role, u.tenant_id, 
                    u.timezone, u.preferences, u.avatar, u.job_title, u.department,
                    u.is_global_admin, u.account_type, u.employee_status,
                    t.name as tenant_name, t.subdomain, t.slug as tenant_slug
                FROM users u 
                LEFT JOIN tenants t ON u.tenant_id = t.id 
                WHERE u.id = ? AND u.status = 'active'
            ");
            $stmt->execute([$userId]);
            return $stmt->fetch(PDO::FETCH_ASSOC);
        } catch (PDOException $e) {
            error_log("Get user error: " . $e->getMessage());
            return null;
        }
    }
    
    public function tenant() {
        $user = $this->user();
        if (!$user || !$user['tenant_id']) {
            return null;
        }
        
        try {
            $stmt = $this->pdo->prepare("
                SELECT * FROM tenants WHERE id = ? AND is_active = 1
            ");
            $stmt->execute([$user['tenant_id']]);
            return $stmt->fetch(PDO::FETCH_ASSOC);
        } catch (PDOException $e) {
            error_log("Get tenant error: " . $e->getMessage());
            return null;
        }
    }
    
    public function hasRole($role) {
        $user = $this->user();
        return $user && $user['role'] === $role;
    }
    
    public function isGlobalAdmin() {
        $user = $this->user();
        return $user && $user['is_global_admin'] == 1;
    }
    
    public function can($permission) {
        $user = $this->user();
        if (!$user) return false;
        
        // Global admins have all permissions
        if ($user['is_global_admin'] == 1) {
            return true;
        }
        
        $permissions = $this->getRolePermissions($user['role']);
        return in_array($permission, $permissions);
    }
    
    private function getRolePermissions($role) {
        $permissions = [
            'admin' => [
                'view_dashboard', 'manage_users', 'manage_teams', 'view_reports', 
                'export_data', 'manage_settings', 'manage_forms', 'manage_leads',
                'view_analytics', 'manage_automations'
            ],
            'manager' => [
                'view_dashboard', 'manage_team_users', 'view_reports', 'export_data',
                'manage_forms', 'manage_leads', 'view_analytics'
            ],
            'user' => [
                'view_dashboard', 'view_own_data', 'create_leads', 'view_forms',
                'view_basic_analytics'
            ],
            'viewer' => [
                'view_dashboard', 'view_reports'
            ]
        ];
        
        return $permissions[$role] ?? [];
    }
    
    public function resetPassword($email) {
        try {
            // Check if user exists
            $stmt = $this->pdo->prepare("SELECT id FROM users WHERE email = ? AND status = 'active'");
            $stmt->execute([$email]);
            $user = $stmt->fetch(PDO::FETCH_ASSOC);
            
            if (!$user) {
                return ['success' => true]; // Don't reveal if email exists
            }
            
            // Generate reset token
            $token = bin2hex(random_bytes(32));
            $expiresAt = date('Y-m-d H:i:s', strtotime('+1 hour'));
            
            // Store in password_resets table
            $stmt = $this->pdo->prepare("
                INSERT INTO password_resets (user_id, token, expires_at) 
                VALUES (?, ?, ?)
            ");
            $stmt->execute([$user['id'], $token, $expiresAt]);
            
            // In a real application, you would send an email here
            // For now, we'll just return the token for testing
            return [
                'success' => true,
                'token' => $token, // Remove this in production
                'message' => 'Password reset instructions have been sent to your email.'
            ];
            
        } catch (PDOException $e) {
            error_log("Password reset error: " . $e->getMessage());
            return ['success' => false, 'message' => 'Failed to process password reset.'];
        }
    }
    
    public function validateResetToken($token) {
        try {
            $stmt = $this->pdo->prepare("
                SELECT pr.*, u.email 
                FROM password_resets pr 
                JOIN users u ON pr.user_id = u.id 
                WHERE pr.token = ? AND pr.expires_at > NOW() AND u.status = 'active'
            ");
            $stmt->execute([$token]);
            return $stmt->fetch(PDO::FETCH_ASSOC);
        } catch (PDOException $e) {
            error_log("Validate reset token error: " . $e->getMessage());
            return false;
        }
    }
    
    public function updatePasswordWithToken($token, $newPassword) {
        try {
            $resetRecord = $this->validateResetToken($token);
            if (!$resetRecord) {
                return ['success' => false, 'message' => 'Invalid or expired reset token.'];
            }
            
            // Update password
            $passwordHash = password_hash($newPassword, PASSWORD_DEFAULT);
            $stmt = $this->pdo->prepare("UPDATE users SET password = ? WHERE id = ?");
            $stmt->execute([$passwordHash, $resetRecord['user_id']]);
            
            // Delete used token
            $stmt = $this->pdo->prepare("DELETE FROM password_resets WHERE token = ?");
            $stmt->execute([$token]);
            
            // Log the action
            $this->logAudit(
                $this->getUserTenantId($resetRecord['user_id']),
                $resetRecord['user_id'],
                'password_reset',
                'Password reset via token',
                'user',
                $resetRecord['user_id']
            );
            
            return ['success' => true, 'message' => 'Password updated successfully.'];
            
        } catch (PDOException $e) {
            error_log("Update password error: " . $e->getMessage());
            return ['success' => false, 'message' => 'Failed to update password.'];
        }
    }
    
    private function getUserTenantId($userId) {
        try {
            $stmt = $this->pdo->prepare("SELECT tenant_id FROM users WHERE id = ?");
            $stmt->execute([$userId]);
            $user = $stmt->fetch(PDO::FETCH_ASSOC);
            return $user ? $user['tenant_id'] : null;
        } catch (PDOException $e) {
            error_log("Get user tenant error: " . $e->getMessage());
            return null;
        }
    }
    
    private function logAudit($tenantId, $userId, $action, $description, $resourceType = null, $resourceId = null) {
        try {
            $stmt = $this->pdo->prepare("
                INSERT INTO audit_logs (tenant_id, user_id, action, description, resource_type, resource_id, ip_address, user_agent) 
                VALUES (?, ?, ?, ?, ?, ?, ?, ?)
            ");
            $stmt->execute([
                $tenantId,
                $userId,
                $action,
                $description,
                $resourceType,
                $resourceId,
                $_SERVER['REMOTE_ADDR'] ?? '',
                $_SERVER['HTTP_USER_AGENT'] ?? ''
            ]);
        } catch (PDOException $e) {
            error_log("Audit log error: " . $e->getMessage());
        }
    }
}