<?php
/**
 * Authentication Controller
 * Handle login, registration, and authentication
 */

namespace Controllers;

use Core\Auth;
use Core\Helpers;
use Models\User;
use Models\Pharmacy;
use Models\Courier;

class AuthController extends Controller {
    
    /**
     * Login user
     */
    public function login($params = []) {
        if ($_SERVER['REQUEST_METHOD'] === 'GET') {
            if (Auth::check()) {
                $this->redirectToDashboard();
            }
            
            $this->view('auth/login', [
                'title' => 'Connexion - ' . APP_NAME,
                'csrf_token' => Helpers::generateCsrfToken()
            ]);
            return;
        }
        
        $input = $this->getInput();
        
        $this->validateRequired($input, ['email', 'password']);
        $this->validateCsrfToken($input['csrf_token'] ?? '');
        
        try {
            $user = Auth::login($input['email'], $input['password']);
            
            if (!$user) {
                if (Helpers::isAjax()) {
                    $this->error('Email ou mot de passe incorrect', 401);
                } else {
                    $this->view('auth/login', [
                        'error' => 'Email ou mot de passe incorrect',
                        'title' => 'Connexion - ' . APP_NAME,
                        'csrf_token' => Helpers::generateCsrfToken()
                    ]);
                    return;
                }
            }
            
            if (Helpers::isAjax()) {
                $this->success([
                    'user' => [
                        'id' => $user['id'],
                        'name' => $user['name'],
                        'email' => $user['email'],
                        'role' => $user['role']
                    ],
                    'redirect_url' => $this->getDashboardUrl($user['role'])
                ], 'Connexion réussie');
            } else {
                $this->redirectToDashboard();
            }
            
        } catch (\Exception $e) {
            $this->log("Login failed: " . $e->getMessage(), 'error');
            
            if (Helpers::isAjax()) {
                $this->error('Erreur de connexion');
            } else {
                $this->view('auth/login', [
                    'error' => 'Erreur de connexion',
                    'title' => 'Connexion - ' . APP_NAME,
                    'csrf_token' => Helpers::generateCsrfToken()
                ]);
            }
        }
    }
    
    /**
     * Register new user
     */
    public function register($params = []) {
        if ($_SERVER['REQUEST_METHOD'] === 'GET') {
            if (Auth::check()) {
                $this->redirectToDashboard();
            }
            
            $this->view('auth/register', [
                'title' => 'Inscription - ' . APP_NAME,
                'csrf_token' => Helpers::generateCsrfToken()
            ]);
            return;
        }
        
        $input = $this->getInput();
        
        $this->validateRequired($input, [
            'name', 'email', 'phone', 'password', 'password_confirm', 'role'
        ]);
        $this->validateCsrfToken($input['csrf_token'] ?? '');
        
        // Validate passwords match
        if ($input['password'] !== $input['password_confirm']) {
            if (Helpers::isAjax()) {
                $this->error('Les mots de passe ne correspondent pas');
            } else {
                $this->view('auth/register', [
                    'error' => 'Les mots de passe ne correspondent pas',
                    'title' => 'Inscription - ' . APP_NAME,
                    'csrf_token' => Helpers::generateCsrfToken(),
                    'form_data' => $input
                ]);
                return;
            }
        }
        
        // Validate role
        $allowedRoles = ['client', 'pharmacy', 'courier'];
        if (!in_array($input['role'], $allowedRoles)) {
            $this->error('Rôle invalide');
        }
        
        // Validate phone number
        if (!Helpers::validatePhone($input['phone'])) {
            $this->error('Numéro de téléphone invalide');
        }
        
        // Additional validation for pharmacy and courier
        if (in_array($input['role'], ['pharmacy', 'courier'])) {
            $this->validateRequired($input, ['address', 'lat', 'lng']);
            
            if (!Helpers::validateCoordinates($input['lat'], $input['lng'])) {
                $this->error('Coordonnées géographiques invalides');
            }
        }
        
        try {
            $userModel = new User();
            
            // Check if email already exists
            if ($userModel->findByEmail($input['email'])) {
                if (Helpers::isAjax()) {
                    $this->error('Un compte avec cet email existe déjà');
                } else {
                    $this->view('auth/register', [
                        'error' => 'Un compte avec cet email existe déjà',
                        'title' => 'Inscription - ' . APP_NAME,
                        'csrf_token' => Helpers::generateCsrfToken(),
                        'form_data' => $input
                    ]);
                    return;
                }
            }
            
            // Create user account
            $userData = [
                'name' => $this->sanitize($input['name']),
                'email' => strtolower(trim($input['email'])),
                'phone' => Helpers::formatPhone($input['phone']),
                'password_hash' => password_hash($input['password'], PASSWORD_DEFAULT),
                'role' => $input['role'],
                'address' => isset($input['address']) ? $this->sanitize($input['address']) : null,
                'lat' => isset($input['lat']) ? (float)$input['lat'] : null,
                'lng' => isset($input['lng']) ? (float)$input['lng'] : null,
                'active' => true
            ];
            
            $this->db->beginTransaction();
            
            $userId = $userModel->create($userData);
            
            // Create role-specific profile
            if ($input['role'] === 'pharmacy') {
                $pharmacyModel = new Pharmacy();
                $pharmacyModel->create($userId, [
                    'name' => $userData['name'],
                    'address' => $userData['address'],
                    'lat' => $userData['lat'],
                    'lng' => $userData['lng']
                ]);
            } elseif ($input['role'] === 'courier') {
                $courierModel = new Courier();
                $courierModel->create($userId, [
                    'vehicle_type' => $input['vehicle_type'] ?? 'motorcycle',
                    'lat' => $userData['lat'],
                    'lng' => $userData['lng']
                ]);
            }
            
            $this->db->commit();
            
            $this->log("User registered: {$userData['email']} ({$input['role']})");
            
            if (Helpers::isAjax()) {
                $this->success([
                    'message' => 'Compte créé avec succès'
                ], 'Inscription réussie');
            } else {
                $this->view('auth/login', [
                    'success' => 'Compte créé avec succès. Vous pouvez maintenant vous connecter.',
                    'title' => 'Connexion - ' . APP_NAME,
                    'csrf_token' => Helpers::generateCsrfToken()
                ]);
            }
            
        } catch (\Exception $e) {
            $this->db->rollback();
            $this->log("Registration failed: " . $e->getMessage(), 'error');
            
            if (Helpers::isAjax()) {
                $this->error('Erreur lors de la création du compte');
            } else {
                $this->view('auth/register', [
                    'error' => 'Erreur lors de la création du compte',
                    'title' => 'Inscription - ' . APP_NAME,
                    'csrf_token' => Helpers::generateCsrfToken(),
                    'form_data' => $input
                ]);
            }
        }
    }
    
    /**
     * Logout user
     */
    public function logout($params = []) {
        Auth::logout();
        
        if (Helpers::isAjax()) {
            $this->success([], 'Déconnexion réussie');
        } else {
            Helpers::redirect('/');
        }
    }
    
    /**
     * Get current authenticated user
     */
    public function me($params = []) {
        if (!Auth::check()) {
            $this->error('Non authentifié', 401);
        }
        
        $user = Auth::user();
        $userModel = new User();
        $userWithProfile = $userModel->getWithProfile($user['id']);
        
        $this->success($userWithProfile);
    }
    
    /**
     * Update user profile
     */
    public function updateProfile($params = []) {
        $userId = $this->requireAuth();
        $input = $this->getInput();
        
        $allowedFields = ['name', 'phone', 'address', 'lat', 'lng'];
        $updateData = [];
        
        foreach ($allowedFields as $field) {
            if (isset($input[$field])) {
                $updateData[$field] = $field === 'phone' ? 
                    Helpers::formatPhone($input[$field]) : 
                    $this->sanitize($input[$field]);
            }
        }
        
        // Validate coordinates if provided
        if (isset($updateData['lat']) && isset($updateData['lng'])) {
            if (!Helpers::validateCoordinates($updateData['lat'], $updateData['lng'])) {
                $this->error('Coordonnées géographiques invalides');
            }
        }
        
        try {
            $userModel = new User();
            $userModel->update($userId, $updateData);
            
            // Update role-specific profile
            $user = Auth::user();
            if ($user['role'] === 'pharmacy' && (isset($updateData['lat']) || isset($updateData['lng']))) {
                $pharmacyModel = new Pharmacy();
                $pharmacy = $pharmacyModel->findByUserId($userId);
                if ($pharmacy) {
                    $this->db->update('pharmacies', [
                        'lat' => $updateData['lat'] ?? $pharmacy['lat'],
                        'lng' => $updateData['lng'] ?? $pharmacy['lng'],
                        'address' => $updateData['address'] ?? $pharmacy['address']
                    ], 'id = ?', [$pharmacy['id']]);
                }
            } elseif ($user['role'] === 'courier' && (isset($updateData['lat']) || isset($updateData['lng']))) {
                $courierModel = new Courier();
                $courier = $courierModel->findByUserId($userId);
                if ($courier) {
                    $courierModel->updateLocation($courier['id'], 
                        $updateData['lat'] ?? $courier['lat'],
                        $updateData['lng'] ?? $courier['lng']
                    );
                }
            }
            
            $this->log("Profile updated: {$userId}");
            
            $this->success([], 'Profil mis à jour avec succès');
            
        } catch (\Exception $e) {
            $this->log("Profile update failed: " . $e->getMessage(), 'error');
            $this->error('Erreur lors de la mise à jour du profil');
        }
    }
    
    /**
     * Change password
     */
    public function changePassword($params = []) {
        $userId = $this->requireAuth();
        $input = $this->getInput();
        
        $this->validateRequired($input, ['current_password', 'new_password', 'new_password_confirm']);
        
        if ($input['new_password'] !== $input['new_password_confirm']) {
            $this->error('Les nouveaux mots de passe ne correspondent pas');
        }
        
        if (strlen($input['new_password']) < 6) {
            $this->error('Le nouveau mot de passe doit contenir au moins 6 caractères');
        }
        
        try {
            $userModel = new User();
            $user = $userModel->findById($userId);
            
            if (!$user || !password_verify($input['current_password'], $user['password_hash'])) {
                $this->error('Mot de passe actuel incorrect');
            }
            
            $newHash = password_hash($input['new_password'], PASSWORD_DEFAULT);
            $userModel->update($userId, ['password_hash' => $newHash]);
            
            $this->log("Password changed: {$userId}");
            
            $this->success([], 'Mot de passe modifié avec succès');
            
        } catch (\Exception $e) {
            $this->log("Password change failed: " . $e->getMessage(), 'error');
            $this->error('Erreur lors du changement de mot de passe');
        }
    }
    
    /**
     * Redirect to appropriate dashboard based on role
     */
    private function redirectToDashboard() {
        $user = Auth::user();
        $url = $this->getDashboardUrl($user['role']);
        Helpers::redirect($url);
    }
    
    /**
     * Get dashboard URL for role
     */
    private function getDashboardUrl($role) {
        switch ($role) {
            case 'admin':
                return '/admin';
            case 'pharmacy':
                return '/pharmacy';
            case 'courier':
                return '/courier';
            case 'client':
            default:
                return '/client';
        }
    }
}
?>
