<?php
declare(strict_types=1);

namespace App\Modules\Settings;

use App\Core\Http\Request;
use App\Core\Http\Response;
use App\Core\I18n\Translator;
use App\Core\Security\Csrf;
use App\Core\Support\Flash;
use App\Core\View\Template;
use App\Modules\Auth\AuthService;
use App\Modules\Cron\CronRepository;
use Throwable;

final class CronSettingsController
{
    private const PAST_JOBS_PER_PAGE = 25;

    public function __construct(
        private readonly Template $template,
        private readonly Translator $translator,
        private readonly AuthService $auth,
        private readonly CronRepository $cronRepository,
        private readonly bool $runOnWebDefault,
        private readonly int $webLimitDefault
    ) {
    }

    public function index(Request $request): Response
    {
        $pastPage = max(1, (int) $request->input('past_page', 1));

        try {
            $runOnWeb = $this->cronRepository->getBoolSetting('cron_run_on_web', $this->runOnWebDefault);
            $webLimit = $this->cronRepository->getIntSetting('cron_web_limit', $this->webLimitDefault, 1, 100);
            $schedules = $this->cronRepository->listSchedules();
            $futureJobs = $this->cronRepository->listFutureJobs(60);
            $pastJobsTotal = $this->cronRepository->countPastJobs();
            $pastTotalPages = max(1, (int) ceil($pastJobsTotal / self::PAST_JOBS_PER_PAGE));
            if ($pastPage > $pastTotalPages) {
                $pastPage = $pastTotalPages;
            }
            $pastOffset = ($pastPage - 1) * self::PAST_JOBS_PER_PAGE;
            $pastJobs = $this->cronRepository->listPastJobs(self::PAST_JOBS_PER_PAGE, $pastOffset);
        } catch (Throwable $exception) {
            Flash::set('settings_error', $this->translator->get('settings.cron.flash.load_failed') . ' ' . $exception->getMessage());
            $runOnWeb = $this->runOnWebDefault;
            $webLimit = $this->webLimitDefault;
            $schedules = [];
            $futureJobs = [];
            $pastJobs = [];
            $pastJobsTotal = 0;
            $pastTotalPages = 1;
            $pastPage = 1;
        }

        $trackingIntervalSeconds = $this->cronRepository->getScheduleInterval('shipment_tracking_sync');
        $trackingIntervalMinutes = $trackingIntervalSeconds !== null ? (int) ($trackingIntervalSeconds / 60) : 15;

        $html = $this->template->render('settings/cron', [
            'title' => $this->translator->get('settings.cron.title'),
            'activeMenu' => 'settings',
            'activeSettings' => 'cron',
            'user' => $this->auth->user(),
            'csrfToken' => Csrf::token(),
            'runOnWeb' => $runOnWeb,
            'webLimit' => $webLimit,
            'trackingIntervalMinutes' => $trackingIntervalMinutes,
            'schedules' => $schedules,
            'futureJobs' => $futureJobs,
            'pastJobs' => $pastJobs,
            'pastJobsPagination' => [
                'page' => $pastPage,
                'per_page' => self::PAST_JOBS_PER_PAGE,
                'total' => $pastJobsTotal,
                'total_pages' => $pastTotalPages,
            ],
            'errorMessage' => (string) Flash::get('settings_error', ''),
            'successMessage' => (string) Flash::get('settings_success', ''),
        ], 'layouts/app');

        return Response::html($html);
    }

    public function save(Request $request): Response
    {
        $csrfToken = (string) $request->input('_token', '');
        if (!Csrf::validate($csrfToken)) {
            Flash::set('settings_error', $this->translator->get('auth.errors.csrf_expired'));
            return Response::redirect('/settings/cron');
        }

        $runOnWeb = (string) $request->input('cron_run_on_web', '0') === '1';
        $webLimitRaw = (int) $request->input('cron_web_limit', $this->webLimitDefault);
        $webLimit = max(1, min(100, $webLimitRaw));

        $trackingMinutesRaw = (int) $request->input('tracking_interval_minutes', 15);
        $trackingMinutes = max(5, min(120, $trackingMinutesRaw));

        try {
            $this->cronRepository->upsertSetting('cron_run_on_web', $runOnWeb ? '1' : '0');
            $this->cronRepository->upsertSetting('cron_web_limit', (string) $webLimit);
            $this->cronRepository->updateScheduleInterval('shipment_tracking_sync', $trackingMinutes * 60);
            Flash::set('settings_success', $this->translator->get('settings.cron.flash.saved'));
        } catch (Throwable $exception) {
            Flash::set('settings_error', $this->translator->get('settings.cron.flash.save_failed') . ' ' . $exception->getMessage());
        }

        return Response::redirect('/settings/cron');
    }
}
