<?php
/**
 * SalonPro X - Base Controller
 * All controllers should extend this class
 */

namespace core;

class Controller
{
    protected Request $request;
    protected Response $response;
    protected View $view;
    protected ?object $user = null;
    protected array $middleware = [];

    public function __construct()
    {
        $this->request = new Request();
        $this->response = new Response();
        $this->user = Auth::user();
        $this->registerMiddleware();
    }

    /**
     * Register middleware for this controller
     */
    protected function registerMiddleware(): void
    {
        // Override in child controllers
    }

    /**
     * Add middleware to a specific action or all actions
     */
    protected function addMiddleware(string $middlewareClass, array $actions = []): void
    {
        $this->middleware[] = [
            'class' => $middlewareClass,
            'actions' => $actions,
        ];
    }

    /**
     * Run middleware for the given action
     */
    public function runMiddleware(string $action): void
    {
        foreach ($this->middleware as $mw) {
            if (empty($mw['actions']) || in_array($action, $mw['actions'])) {
                $instance = new $mw['class']();
                $instance->handle($this->request);
            }
        }
    }

    /**
     * Render a view
     */
    protected function view(string $view, array $data = [], string $layout = 'main'): void
    {
        $data = array_merge($this->getSharedData(), $data);
        View::render($view, $data, $layout);
    }

    /**
     * Get shared data for all views
     */
    protected function getSharedData(): array
    {
        return [
            'auth' => $this->user,
            'request' => $this->request,
            'csrf_field' => Security::csrfField(),
            'settings' => $this->getSettings(),
            'current_url' => $this->request->url(),
        ];
    }

    /**
     * Get system settings
     */
    protected function getSettings(): array
    {
        $cacheFile = PATH_STORAGE . DS . 'cache' . DS . 'settings.cache';
        
        if (file_exists($cacheFile) && (time() - filemtime($cacheFile)) < 3600) {
            return unserialize(file_get_contents($cacheFile)) ?: [];
        }

        try {
            $db = Database::getInstance();
            $settings = $db->table('settings')->get();
            $result = [];
            foreach ($settings as $setting) {
                $result[$setting->key] = $setting->value;
            }
            file_put_contents($cacheFile, serialize($result));
            return $result;
        } catch (\Throwable $e) {
            return [];
        }
    }

    /**
     * Return JSON response
     */
    protected function json(mixed $data, int $statusCode = 200): void
    {
        $this->response->json($data, $statusCode);
    }

    /**
     * Return success JSON response
     */
    protected function success(mixed $data = null, string $message = 'Success'): void
    {
        $this->response->success($data, $message);
    }

    /**
     * Return error JSON response
     */
    protected function error(string $message = 'Error', int $statusCode = 400, mixed $errors = null): void
    {
        $this->response->error($message, $statusCode, $errors);
    }

    /**
     * Redirect to a URL
     */
    protected function redirect(string $url): void
    {
        $this->response->redirect($url);
    }

    /**
     * Redirect back
     */
    protected function back(): void
    {
        $this->response->back();
    }

    /**
     * Redirect with alert message
     */
    protected function redirectWith(string $url, string $type, string $message): void
    {
        Session::setAlert($type, $message);
        $this->redirect($url);
    }

    /**
     * Validate request data
     */
    protected function validate(array $rules, array $messages = []): array
    {
        $validator = Validator::make($this->request->all(), $rules, $messages);
        if ($validator->fails()) {
            if ($this->request->isAjax()) {
                $this->error('Validation failed', 422, $validator->errors());
            }
            Session::flash('_errors', $validator->errors());
            Session::flash('_old_input', $this->request->all());
            $this->back();
            exit;
        }
        return $validator->validated();
    }

    /**
     * Check if user has permission
     */
    protected function requirePermission(string $permission): void
    {
        Auth::requirePermission($permission);
    }

    /**
     * Check if request is AJAX
     */
    protected function isAjax(): bool
    {
        return $this->request->isAjax();
    }

    /**
     * Log activity
     */
    protected function logActivity(string $action, string $description): void
    {
        Auth::logActivity($action, $description);
    }

    /**
     * Log audit
     */
    protected function logAudit(string $action, string $table, mixed $recordId, ?array $oldValues = null, ?array $newValues = null): void
    {
        Auth::logAudit($action, $table, $recordId, $oldValues, $newValues);
    }
}
