<?php
require_once 'config/database.php';
require_once 'utils/JWT.php';
require_once 'utils/Response.php';

/**
 * Authentication Controller for Zen Zone Spa API
 * Handles login, logout, and user management
 */
class AuthController {
    
    private $db;
    
    public function __construct() {
        $this->db = DatabaseConfig::getConnection();
    }
    
    /**
     * Handle login request
     * POST /auth/login
     */
    public function login() {
        $data = Response::getRequestBody();
        
        // Validate required fields
        $errors = Response::validateRequired($data, ['username', 'password']);
        if ($errors) {
            Response::validationError($errors);
        }
        
        $username = trim($data['username']);
        $password = $data['password'];
        
        try {
            // Get user from database
            $stmt = $this->db->prepare("
                SELECT id, username, password_hash, email, name, role, is_active 
                FROM users 
                WHERE username = ? AND is_active = 1
            ");
            $stmt->execute([$username]);
            $user = $stmt->fetch();
            
            if (!$user || !password_verify($password, $user['password_hash'])) {
                Response::error('Invalid username or password', 401);
            }
            
            // Update last login
            $this->updateLastLogin($user['id']);
            
            // Generate JWT token
            $token_payload = [
                'user_id' => $user['id'],
                'username' => $user['username'],
                'role' => $user['role']
            ];
            
            $token = JWT::encode($token_payload, 24); // 24 hours expiry
            
            // Store token in database for tracking
            $this->storeToken($user['id'], $token);
            
            // Prepare user data (exclude password)
            $user_data = [
                'id' => $user['id'],
                'username' => $user['username'],
                'email' => $user['email'],
                'name' => $user['name'],
                'role' => $user['role']
            ];
            
            Response::success([
                'token' => $token,
                'user' => $user_data,
                'expires_in' => 24 * 3600 // seconds
            ], 'Login successful');
            
        } catch (Exception $e) {
            error_log("Login error: " . $e->getMessage());
            Response::serverError('Login failed. Please try again.');
        }
    }
    
    /**
     * Handle user registration
     * POST /auth/register
     */
    public function register() {
        $data = Response::getRequestBody();
        
        // Validate required fields
        $errors = Response::validateRequired($data, ['username', 'email', 'password', 'name']);
        if ($errors) {
            Response::validationError($errors);
        }
        
        // Validate email format
        if (!filter_var($data['email'], FILTER_VALIDATE_EMAIL)) {
            Response::error('Invalid email format', 400);
        }
        
        // Validate password strength (minimum 6 characters)
        if (strlen($data['password']) < 6) {
            Response::error('Password must be at least 6 characters', 400);
        }
        
        $username = trim($data['username']);
        $email = trim($data['email']);
        $password = $data['password'];
        $name = trim($data['name']);
        $phone = isset($data['phone']) ? trim($data['phone']) : null;
        $role = isset($data['role']) ? $data['role'] : 'staff'; // Default role
        
        try {
            // Check if username already exists
            $stmt = $this->db->prepare("SELECT id FROM users WHERE username = ?");
            $stmt->execute([$username]);
            if ($stmt->fetch()) {
                Response::error('Username already exists', 400);
            }
            
            // Check if email already exists
            $stmt = $this->db->prepare("SELECT id FROM users WHERE email = ?");
            $stmt->execute([$email]);
            if ($stmt->fetch()) {
                Response::error('Email already exists', 400);
            }
            
            // Hash password
            $password_hash = password_hash($password, PASSWORD_DEFAULT);
            
            // Insert new user
            $stmt = $this->db->prepare("
                INSERT INTO users (username, email, password_hash, name, phone, role, is_active) 
                VALUES (?, ?, ?, ?, ?, ?, 1)
            ");
            $stmt->execute([$username, $email, $password_hash, $name, $phone, $role]);
            
            // Get the newly created user
            $user_id = $this->db->lastInsertId();
            
            // Return user data (without password)
            Response::success([
                'id' => $user_id,
                'username' => $username,
                'email' => $email,
                'name' => $name,
                'phone' => $phone,
                'role' => $role
            ], 'User registered successfully', 201);
            
        } catch (Exception $e) {
            error_log("Registration error: " . $e->getMessage());
            Response::serverError('Registration failed. Please try again.');
        }
    }
    
    /**
     * Handle logout request
     * POST /auth/logout
     */
    public function logout() {
        $token = $this->getAuthToken();
        
        if (!$token) {
            Response::unauthorized('No token provided');
        }
        
        try {
            // Revoke token
            $this->revokeToken($token);
            Response::success(null, 'Logged out successfully');
            
        } catch (Exception $e) {
            error_log("Logout error: " . $e->getMessage());
            Response::success(null, 'Logged out successfully'); // Always success for logout
        }
    }
    
    /**
     * Get current user profile
     * GET /auth/profile
     */
    public function profile() {
        $user = $this->getAuthenticatedUser();
        
        try {
            $stmt = $this->db->prepare("
                SELECT id, username, email, name, role, phone, created_at, last_login
                FROM users 
                WHERE id = ? AND is_active = 1
            ");
            $stmt->execute([$user['user_id']]);
            $user_data = $stmt->fetch();
            
            if (!$user_data) {
                Response::notFound('User not found');
            }
            
            Response::success($user_data, 'Profile retrieved successfully');
            
        } catch (Exception $e) {
            error_log("Profile error: " . $e->getMessage());
            Response::serverError('Failed to retrieve profile');
        }
    }
    
    /**
     * Validate token endpoint
     * POST /auth/validate
     */
    public function validateToken() {
        $user = $this->getAuthenticatedUser();
        Response::success([
            'valid' => true,
            'user_id' => $user['user_id'],
            'username' => $user['username'],
            'role' => $user['role']
        ], 'Token is valid');
    }
    
    /**
     * Change password
     * POST /auth/change-password
     */
    public function changePassword() {
        $user = $this->getAuthenticatedUser();
        $data = Response::getRequestBody();
        
        $errors = Response::validateRequired($data, ['current_password', 'new_password']);
        if ($errors) {
            Response::validationError($errors);
        }
        
        try {
            // Verify current password
            $stmt = $this->db->prepare("SELECT password_hash FROM users WHERE id = ?");
            $stmt->execute([$user['user_id']]);
            $current_hash = $stmt->fetchColumn();
            
            if (!password_verify($data['current_password'], $current_hash)) {
                Response::error('Current password is incorrect', 400);
            }
            
            // Update password
            $new_hash = password_hash($data['new_password'], PASSWORD_DEFAULT);
            $stmt = $this->db->prepare("UPDATE users SET password_hash = ? WHERE id = ?");
            $stmt->execute([$new_hash, $user['user_id']]);
            
            Response::success(null, 'Password changed successfully');
            
        } catch (Exception $e) {
            error_log("Change password error: " . $e->getMessage());
            Response::serverError('Failed to change password');
        }
    }
    
    /**
     * Get authenticated user from token
     */
    private function getAuthenticatedUser() {
        $token = $this->getAuthToken();
        
        if (!$token) {
            Response::unauthorized('No token provided');
        }
        
        $payload = JWT::validateToken($token);
        if (!$payload) {
            Response::unauthorized('Invalid or expired token');
        }
        
        return $payload;
    }
    
    /**
     * Static method to require authentication for protected endpoints
     * This method can be called from route handlers
     */
    public static function requireAuth() {
        $auth = new self();
        return $auth->getAuthenticatedUser();
    }
    
    /**
     * Get authorization token from request (cPanel compatible)
     */
    private function getAuthToken() {
        // Try multiple methods to get the Authorization header (cPanel compatible)
        $auth_header = null;
        
        // Method 1: Apache header (most common)
        if (isset($_SERVER['HTTP_AUTHORIZATION'])) {
            $auth_header = $_SERVER['HTTP_AUTHORIZATION'];
        }
        // Method 2: Redirect from .htaccess
        elseif (isset($_SERVER['REDIRECT_HTTP_AUTHORIZATION'])) {
            $auth_header = $_SERVER['REDIRECT_HTTP_AUTHORIZATION'];
        }
        // Method 3: getallheaders() if available
        elseif (function_exists('getallheaders')) {
            $headers = getallheaders();
            $auth_header = $headers['Authorization'] ?? $headers['authorization'] ?? null;
        }
        // Method 4: apache_request_headers() fallback
        elseif (function_exists('apache_request_headers')) {
            $headers = apache_request_headers();
            $auth_header = $headers['Authorization'] ?? $headers['authorization'] ?? null;
        }
        
        if ($auth_header && strpos($auth_header, 'Bearer ') === 0) {
            return substr($auth_header, 7);
        }
        
        return null;
    }
    
    /**
     * Update user's last login time
     */
    private function updateLastLogin($user_id) {
        $stmt = $this->db->prepare("UPDATE users SET last_login = NOW() WHERE id = ?");
        $stmt->execute([$user_id]);
    }
    
    /**
     * Store token in database for tracking
     */
    private function storeToken($user_id, $token) {
        $token_hash = hash('sha256', $token);
        $expires_at = date('Y-m-d H:i:s', time() + (24 * 3600));
        
        $stmt = $this->db->prepare("
            INSERT INTO api_tokens (user_id, token_hash, expires_at) 
            VALUES (?, ?, ?)
        ");
        $stmt->execute([$user_id, $token_hash, $expires_at]);
    }
    
    /**
     * Revoke token
     */
    private function revokeToken($token) {
        $token_hash = hash('sha256', $token);
        $stmt = $this->db->prepare("UPDATE api_tokens SET is_revoked = 1 WHERE token_hash = ?");
        $stmt->execute([$token_hash]);
    }
    
    /**
     * Clean expired tokens (call this periodically)
     */
    public function cleanExpiredTokens() {
        $stmt = $this->db->prepare("DELETE FROM api_tokens WHERE expires_at < NOW() OR is_revoked = 1");
        $stmt->execute();
    }
} 