<?php

require_once __DIR__ . '/../helpers/Response.php';

abstract class BaseController
{

    protected function __construct()
    {
        $this->setCorsHeaders();
        $this->handleOptionsRequest();
    }

    /**
     * Set CORS headers
     */
    protected function setCorsHeaders()
    {
        header('Access-Control-Allow-Origin: *');
        header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
        header('Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With');
        header('Access-Control-Max-Age: 3600');
    }

    /**
     * Handle OPTIONS preflight request
     */
    protected function handleOptionsRequest()
    {
        if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
            http_response_code(200);
            exit();
        }
    }

    /**
     * Get request method
     */
    protected function getRequestMethod()
    {
        return $_SERVER['REQUEST_METHOD'];
    }

    /**
     * Get POST data
     */
    protected function getPostData()
    {
        return $_POST;
    }

    /**
     * Get JSON input data
     */
    protected function getJsonInput()
    {
        $input = file_get_contents('php://input');
        return json_decode($input, true);
    }

    /**
     * Get input data (both POST and JSON)
     */
    protected function getInputData()
    {
        $jsonInput = $this->getJsonInput();
        $postData = $this->getPostData();

        // Merge both inputs, giving priority to JSON
        return array_merge($postData, $jsonInput ?: []);
    }

    /**
     * Get GET parameters
     */
    protected function getQueryParams()
    {
        return $_GET;
    }

    /**
     * Get uploaded files
     */
    protected function getFiles()
    {
        return $_FILES;
    }

    /**
     * Validate required fields
     */
    protected function validateRequired($data, $requiredFields)
    {
        $errors = [];

        foreach ($requiredFields as $field) {
            if (!isset($data[$field]) || empty($data[$field])) {
                $errors[] = "Field '$field' is required";
            }
        }

        if (!empty($errors)) {
            Response::validationError('Validation failed', $errors);
        }

        return true;
    }

    /**
     * Validate email format
     */
    protected function validateEmail($email)
    {
        return filter_var($email, FILTER_VALIDATE_EMAIL);
    }

    /**
     * Validate phone number
     */
    protected function validatePhone($phone)
    {
        return preg_match('/^[0-9]{10,15}$/', $phone);
    }

    /**
     * Sanitize input data
     */
    protected function sanitizeInput($data)
    {
        if (is_array($data)) {
            return array_map([$this, 'sanitizeInput'], $data);
        }

        return trim(htmlspecialchars($data, ENT_QUOTES, 'UTF-8'));
    }

    /**
     * Validate and sanitize input
     */
    protected function validateAndSanitize($data, $rules = [])
    {
        $sanitized = $this->sanitizeInput($data);

        foreach ($rules as $field => $rule) {
            if (isset($sanitized[$field])) {
                switch ($rule) {
                    case 'email':
                        if (!$this->validateEmail($sanitized[$field])) {
                            Response::validationError("Invalid email format for field '$field'");
                        }
                        break;
                    case 'phone':
                        if (!$this->validatePhone($sanitized[$field])) {
                            Response::validationError("Invalid phone format for field '$field'");
                        }
                        break;
                    case 'numeric':
                        if (!is_numeric($sanitized[$field])) {
                            Response::validationError("Field '$field' must be numeric");
                        }
                        break;
                }
            }
        }

        return $sanitized;
    }

    /**
     * Check if request method is allowed
     */
    protected function allowMethod($allowedMethods)
    {
        if (!in_array($_SERVER['REQUEST_METHOD'], $allowedMethods)) {
            Response::error('Method not allowed', 405);
        }
    }

    /**
     * Log error
     */
    protected function logError($message, $context = [])
    {
        $timestamp = date('Y-m-d H:i:s');
        $logMessage = "[$timestamp] $message";

        if (!empty($context)) {
            $logMessage .= " Context: " . json_encode($context);
        }

        error_log($logMessage);
    }

    /**
     * Handle exceptions
     */
    protected function handleException($e)
    {
        $this->logError($e->getMessage(), [
            'file' => $e->getFile(),
            'line' => $e->getLine(),
            'trace' => $e->getTraceAsString()
        ]);

        Response::serverError('Internal server error');
    }
}
