<?php
/**
 * BOAFO BaseController
 * Shared controller functionality: views, redirects, JSON responses, validation
 */
abstract class BaseController {

    protected function view(string $viewPath, array $data = [], ?string $layout = 'main'): void {
        // Make data available as variables
        extract($data, EXTR_SKIP);

        $viewFile = APP_PATH . '/Views/' . str_replace('.', '/', $viewPath) . '.php';
        if (!file_exists($viewFile)) {
            die("View not found: {$viewPath}");
        }

        if ($layout) {
            $layoutFile = APP_PATH . '/Views/layouts/' . $layout . '.php';
            if (!file_exists($layoutFile)) {
                die("Layout not found: {$layout}");
            }
            // Buffer the view
            ob_start();
            require $viewFile;
            $content = ob_get_clean();

            // Render layout
            require $layoutFile;
        } else {
            require $viewFile;
        }
    }

    protected function json(array $data, int $code = 200): never {
        http_response_code($code);
        header('Content-Type: application/json; charset=utf-8');
        echo json_encode($data, JSON_UNESCAPED_UNICODE);
        exit;
    }

    protected function redirect(string $url): never {
        header('Location: ' . $url);
        exit;
    }

    protected function back(): never {
        $this->redirect($_SERVER['HTTP_REFERER'] ?? APP_URL . '/dashboard');
    }

    protected function input(string $key, mixed $default = null): mixed {
        return $_POST[$key] ?? $_GET[$key] ?? $default;
    }

    protected function sanitize(string $value): string {
        return htmlspecialchars(trim($value), ENT_QUOTES, 'UTF-8');
    }

    protected function validate(array $rules): array {
        $errors = [];
        foreach ($rules as $field => $rule_string) {
            $rules_list = explode('|', $rule_string);
            $value = $this->input($field);

            foreach ($rules_list as $rule) {
                if ($rule === 'required' && empty(trim((string)$value))) {
                    $errors[$field] = ucfirst(str_replace('_', ' ', $field)) . ' is required.';
                    break;
                }
                if ($rule === 'email' && !filter_var($value, FILTER_VALIDATE_EMAIL)) {
                    $errors[$field] = 'Invalid email address.';
                    break;
                }
                if (str_starts_with($rule, 'min:')) {
                    $min = (int) substr($rule, 4);
                    if (strlen((string)$value) < $min) {
                        $errors[$field] = ucfirst(str_replace('_', ' ', $field)) . " must be at least {$min} characters.";
                        break;
                    }
                }
                if (str_starts_with($rule, 'max:')) {
                    $max = (int) substr($rule, 4);
                    if (strlen((string)$value) > $max) {
                        $errors[$field] = ucfirst(str_replace('_', ' ', $field)) . " must not exceed {$max} characters.";
                        break;
                    }
                }
                if (str_starts_with($rule, 'in:')) {
                    $allowed = explode(',', substr($rule, 3));
                    if (!in_array($value, $allowed)) {
                        $errors[$field] = ucfirst(str_replace('_', ' ', $field)) . ' contains an invalid value.';
                        break;
                    }
                }
            }
        }
        return $errors;
    }

    protected function flash(string $key, mixed $value): void {
        $_SESSION['flash'][$key] = $value;
    }

    protected function getFlash(string $key): mixed {
        $val = $_SESSION['flash'][$key] ?? null;
        unset($_SESSION['flash'][$key]);
        return $val;
    }

    protected function isPost(): bool {
        return $_SERVER['REQUEST_METHOD'] === 'POST';
    }

    protected function isAjax(): bool {
        return !empty($_SERVER['HTTP_X_REQUESTED_WITH']) &&
            strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest';
    }

    protected function currentUser(): ?array {
        return Auth::user();
    }

    protected function requireAuth(): void {
        if (!Auth::check()) {
            $this->redirect(APP_URL . '/login');
        }
    }
}
