<?php
/**
 * Base Controller Class
 * Common functionality for all controllers
 */

namespace Controllers;

abstract class Controller {
    protected $db;
    
    public function __construct() {
        $this->db = \Core\DB::getInstance();
    }
    
    /**
     * Return JSON response
     */
    protected function json($data, $code = 200) {
        http_response_code($code);
        header('Content-Type: application/json');
        echo json_encode($data);
        exit();
    }
    
    /**
     * Return success JSON response
     */
    protected function success($data = [], $message = 'Success') {
        $this->json([
            'success' => true,
            'message' => $message,
            'data' => $data
        ]);
    }
    
    /**
     * Return error JSON response
     */
    protected function error($message, $code = 400, $data = []) {
        $this->json([
            'success' => false,
            'message' => $message,
            'data' => $data
        ], $code);
    }
    
    /**
     * Get request input as array
     */
    protected function getInput() {
        $input = file_get_contents('php://input');
        
        // Try to decode JSON
        $json = json_decode($input, true);
        if (json_last_error() === JSON_ERROR_NONE) {
            return $json;
        }
        
        // Fallback to POST data
        return $_POST;
    }
    
    /**
     * Validate required fields
     */
    protected function validateRequired($data, $required) {
        $missing = [];
        
        foreach ($required as $field) {
            if (!isset($data[$field]) || empty($data[$field])) {
                $missing[] = $field;
            }
        }
        
        if (!empty($missing)) {
            $this->error('Champs requis manquants: ' . implode(', ', $missing), 400);
        }
        
        return true;
    }
    
    /**
     * Sanitize input data
     */
    protected function sanitize($data) {
        if (is_array($data)) {
            return array_map([$this, 'sanitize'], $data);
        }
        
        return htmlspecialchars(trim($data), ENT_QUOTES, 'UTF-8');
    }
    
    /**
     * Check if user is authenticated
     */
    protected function requireAuth() {
        if (!isset($_SESSION['user_id'])) {
            $this->error('Authentication required', 401);
        }
        
        return $_SESSION['user_id'];
    }
    
    /**
     * Check if user has specific role
     */
    protected function requireRole($role) {
        $userId = $this->requireAuth();
        
        if (!isset($_SESSION['user_role']) || $_SESSION['user_role'] !== $role) {
            $this->error('Insufficient permissions', 403);
        }
        
        return $userId;
    }
    
    /**
     * Generate CSRF token
     */
    protected function generateCsrfToken() {
        if (!isset($_SESSION['csrf_token'])) {
            $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
        }
        
        return $_SESSION['csrf_token'];
    }
    
    /**
     * Validate CSRF token
     */
    protected function validateCsrfToken($token) {
        if (!isset($_SESSION['csrf_token']) || !hash_equals($_SESSION['csrf_token'], $token)) {
            $this->error('CSRF token validation failed', 403);
        }
        
        return true;
    }
    
    /**
     * Log activity
     */
    protected function log($message, $level = 'info') {
        $logFile = LOG_PATH . 'app.log';
        $timestamp = date('Y-m-d H:i:s');
        $userId = $_SESSION['user_id'] ?? 'anonymous';
        $ip = $_SERVER['REMOTE_ADDR'] ?? 'unknown';
        
        $logMessage = "[{$timestamp}] {$level}: {$message} | User: {$userId} | IP: {$ip}" . PHP_EOL;
        
        file_put_contents($logFile, $logMessage, FILE_APPEND | LOCK_EX);
    }
    
    /**
     * Handle file upload
     */
    protected function handleFileUpload($field, $allowedTypes = null) {
        if (!isset($_FILES[$field])) {
            return null;
        }
        
        $file = $_FILES[$field];
        
        if ($file['error'] !== UPLOAD_ERR_OK) {
            $this->error('File upload error: ' . $this->getUploadErrorMessage($file['error']));
        }
        
        // Check file size
        if ($file['size'] > UPLOAD_MAX_SIZE) {
            $this->error('File size exceeds maximum allowed size');
        }
        
        // Check file type
        $allowedTypes = $allowedTypes ?? UPLOAD_ALLOWED_TYPES;
        if (!in_array($file['type'], $allowedTypes)) {
            $this->error('File type not allowed');
        }
        
        // Generate unique filename
        $extension = pathinfo($file['name'], PATHINFO_EXTENSION);
        $filename = uniqid() . '_' . time() . '.' . $extension;
        $destination = UPLOAD_PATH . $filename;
        
        if (!move_uploaded_file($file['tmp_name'], $destination)) {
            $this->error('Failed to save file');
        }
        
        return $filename;
    }
    
    /**
     * Get upload error message
     */
    private function getUploadErrorMessage($error) {
        switch ($error) {
            case UPLOAD_ERR_INI_SIZE:
                return 'File size exceeds upload_max_filesize directive';
            case UPLOAD_ERR_FORM_SIZE:
                return 'File size exceeds MAX_FILE_SIZE directive';
            case UPLOAD_ERR_PARTIAL:
                return 'File was only partially uploaded';
            case UPLOAD_ERR_NO_FILE:
                return 'No file was uploaded';
            case UPLOAD_ERR_NO_TMP_DIR:
                return 'Missing temporary folder';
            case UPLOAD_ERR_CANT_WRITE:
                return 'Failed to write file to disk';
            case UPLOAD_ERR_EXTENSION:
                return 'File upload stopped by extension';
            default:
                return 'Unknown upload error';
        }
    }
    
    /**
     * Render view (for web pages)
     */
    protected function view($template, $data = []) {
        // Extract data for use in template
        extract($data);
        
        // Start output buffering
        ob_start();
        
        // Include the template
        $templatePath = __DIR__ . '/../Views/' . $template . '.php';
        if (file_exists($templatePath)) {
            include $templatePath;
        } else {
            throw new \Exception("View template not found: {$template}");
        }
        
        // Get the buffered content
        $content = ob_get_clean();
        
        // Output the content
        echo $content;
        exit();
    }
}
?>
