<?php
declare(strict_types=1);

namespace App\Controllers;

use App\Core\Auth;
use App\Core\Csrf;
use App\Core\Request;
use App\Core\Validator;
use App\Models\Notification;
use App\Services\NotificationService;

abstract class BaseController
{
    protected function requireModule(string $module): void
    {
        if (!Auth::instance()->canSee($module)) {
            if (is_ajax()) {
                json_out(['ok' => false, 'error' => 'You cannot open this section.'], 403);
            }
            http_response_code(403);
            view('errors/403', ['title' => 'No access']);
            exit;
        }
        $method = strtoupper((string) ($_SERVER['REQUEST_METHOD'] ?? 'GET'));
        if ($method !== 'GET' && $method !== 'HEAD' && !Auth::instance()->canEdit($module)) {
            if (is_ajax()) {
                json_out(['ok' => false, 'error' => 'You can view this section but not change it.'], 403);
            }
            http_response_code(403);
            view('errors/403', ['title' => 'View only']);
            exit;
        }
    }

    protected function verifyCsrf(Request $request): void
    {
        if (!Csrf::verify(Csrf::fromRequest())) {
            if (is_ajax()) {
                json_out(['ok' => false, 'error' => 'Your session expired. Refresh and try again.'], 419);
            }
            flash('error', 'Your session expired. Please try again.');
            redirect($request->path());
        }
    }

    protected function page(): int
    {
        $p = (int) ($_GET['page'] ?? 1);
        return max(1, $p);
    }

    protected function q(): string
    {
        return trim((string) ($_GET['q'] ?? ''));
    }

    protected function ownerScope(): ?int
    {
        if (has_role('manager', 'admin')) {
            return null;
        }
        return Auth::instance()->id();
    }

    protected function notifications(): array
    {
        $uid = Auth::instance()->id();
        if (!$uid || !Auth::instance()->tenantId()) {
            return ['items' => [], 'count' => 0];
        }
        try {
            NotificationService::syncDealNextSteps();
            \App\Services\AutomationService::syncOverdueTasks();
        } catch (\Throwable $e) {
            // Keep the page up if a due-date check fails.
        }
        return [
            'items' => Notification::unread($uid),
            'count' => Notification::unreadCount($uid),
        ];
    }

    protected function fail(Validator $v): void
    {
        json_out(['ok' => false, 'error' => $v->first(), 'errors' => $v->errors()], 422);
    }
}
