<?php
require_once __DIR__ . '/Database.php';
require_once __DIR__ . '/../includes/JWTHelper.php';

/**
 * Authentication Class
 * Handles user authentication, JWT token generation, and password management
 */
class Auth {
    private $db;
    
    public function __construct() {
        $this->db = Database::getInstance();
    }
    
    /**
     * Register a new user
     */
    public function register($data) {
        // Validate required fields
        $required = ['first_name', 'last_name', 'email', 'phone', 'password', 'role_id'];
        foreach ($required as $field) {
            if (empty($data[$field])) {
                throw new Exception("Field {$field} is required");
            }
        }
        
        // Check if email or phone already exists
        $checkSql = "SELECT id FROM users WHERE email = ? OR phone = ?";
        $checkResult = $this->db->query($checkSql, [$data['email'], $data['phone']]);
        
        if ($checkResult->num_rows > 0) {
            throw new Exception("Email or phone number already registered");
        }
        
        // Hash password
        $passwordHash = password_hash($data['password'], PASSWORD_BCRYPT);
        
        // Prepare user data
        $userData = [
            'role_id' => $data['role_id'],
            'first_name' => $data['first_name'],
            'middle_name' => $data['middle_name'] ?? null,
            'last_name' => $data['last_name'],
            'email' => $data['email'],
            'phone' => $data['phone'],
            'phone_secondary' => $data['phone_secondary'] ?? null,
            'gender' => $data['gender'] ?? null,
            'dob' => $data['dob'] ?? null,
            'nationality' => $data['nationality'] ?? null,
            'id_type' => $data['id_type'] ?? 'National ID',
            'id_number' => $data['id_number'] ?? null,
            'password_hash' => $passwordHash,
            'address_postal' => $data['address_postal'] ?? null,
            'city' => $data['city'] ?? null,
            'country' => $data['country'] ?? 'Kenya',
            'status' => $data['status'] ?? 'pending_verification'
        ];
        
        // Insert user
        $columns = implode(', ', array_keys($userData));
        $placeholders = implode(', ', array_fill(0, count($userData), '?'));
        $values = array_values($userData);
        
        $sql = "INSERT INTO users ({$columns}) VALUES ({$placeholders})";
        $this->db->execute($sql, $values);
        
        $userId = $this->db->getLastInsertId();
        
        // Log activity
        $this->logActivity($userId, 'REGISTER', 'AUTH', $userId, null, ['email' => $data['email']]);
        
        return $userId;
    }
    
    /**
     * Login user and return JWT token
     */
    public function login($emailOrPhone, $password) {
        // Find user by email or phone
        $sql = "SELECT u.*, r.role_name FROM users u 
                LEFT JOIN roles r ON u.role_id = r.id 
                WHERE (u.email = ? OR u.phone = ?) AND u.status = 'active'";
        
        $result = $this->db->query($sql, [$emailOrPhone, $emailOrPhone]);
        $user = $result->fetch_assoc();
        
        if (!$user) {
            throw new Exception("Invalid credentials or account not active");
        }
        
        // Verify password
        if (!password_verify($password, $user['password_hash'])) {
            throw new Exception("Invalid credentials");
        }
        
        // Update last login
        $updateSql = "UPDATE users SET last_login = NOW() WHERE id = ?";
        $this->db->execute($updateSql, [$user['id']]);
        
        // Generate JWT token
        $payload = [
            'user_id' => $user['id'],
            'email' => $user['email'],
            'role_id' => $user['role_id'],
            'role_name' => $user['role_name']
        ];
        
        $token = JWTHelper::generate($payload, 86400); // 24 hours
        
        // Log activity
        $this->logActivity($user['id'], 'LOGIN', 'AUTH', $user['id'], null, ['ip' => $_SERVER['REMOTE_ADDR'] ?? '']);
        
        return [
            'token' => $token,
            'user' => [
                'id' => $user['id'],
                'first_name' => $user['first_name'],
                'last_name' => $user['last_name'],
                'email' => $user['email'],
                'phone' => $user['phone'],
                'role_id' => $user['role_id'],
                'role_name' => $user['role_name']
            ]
        ];
    }
    
    /**
     * Validate JWT token and return user data
     */
    public function validateToken($token) {
        $payload = JWTHelper::validate($token);
        
        if (!$payload) {
            throw new Exception("Invalid or expired token");
        }
        
        // Verify user still exists and is active
        $sql = "SELECT u.*, r.role_name FROM users u 
                LEFT JOIN roles r ON u.role_id = r.id 
                WHERE u.id = ? AND u.status = 'active'";
        
        $result = $this->db->query($sql, [$payload['user_id']]);
        $user = $result->fetch_assoc();
        
        if (!$user) {
            throw new Exception("User not found or inactive");
        }
        
        return [
            'user_id' => $user['id'],
            'email' => $user['email'],
            'role_id' => $user['role_id'],
            'role_name' => $user['role_name']
        ];
    }
    
    /**
     * Get user by ID
     */
    public function getUserById($userId) {
        $sql = "SELECT u.*, r.role_name FROM users u 
                LEFT JOIN roles r ON u.role_id = r.id 
                WHERE u.id = ?";
        
        $result = $this->db->query($sql, [$userId]);
        return $result->fetch_assoc();
    }
    
    /**
     * Change password
     */
    public function changePassword($userId, $oldPassword, $newPassword) {
        // Get current password hash
        $sql = "SELECT password_hash FROM users WHERE id = ?";
        $result = $this->db->query($sql, [$userId]);
        $user = $result->fetch_assoc();
        
        if (!$user || !password_verify($oldPassword, $user['password_hash'])) {
            throw new Exception("Current password is incorrect");
        }
        
        // Update password
        $newHash = password_hash($newPassword, PASSWORD_BCRYPT);
        $updateSql = "UPDATE users SET password_hash = ? WHERE id = ?";
        $this->db->execute($updateSql, [$newHash, $userId]);
        
        // Log activity
        $this->logActivity($userId, 'PASSWORD_CHANGE', 'AUTH', $userId);
        
        return true;
    }
    
    /**
     * Reset password (admin function)
     */
    public function resetPassword($userId, $newPassword) {
        $newHash = password_hash($newPassword, PASSWORD_BCRYPT);
        $sql = "UPDATE users SET password_hash = ? WHERE id = ?";
        $this->db->execute($sql, [$newHash, $userId]);
        
        $this->logActivity($userId, 'PASSWORD_RESET', 'AUTH', $userId);
        
        return true;
    }
    
    /**
     * Log activity
     */
    private function logActivity($userId, $actionType, $module, $referenceId, $oldValues = null, $newValues = null) {
        $sql = "INSERT INTO activity_logs (user_id, action_type, module, reference_id, old_values, new_values, ip_address, user_agent) 
                VALUES (?, ?, ?, ?, ?, ?, ?, ?)";
        
        $oldJson = $oldValues ? json_encode($oldValues) : null;
        $newJson = $newValues ? json_encode($newValues) : null;
        $ip = $_SERVER['REMOTE_ADDR'] ?? null;
        $userAgent = $_SERVER['HTTP_USER_AGENT'] ?? null;
        
        $this->db->execute($sql, [$userId, $actionType, $module, $referenceId, $oldJson, $newJson, $ip, $userAgent]);
    }
}
?>
