<?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\Constants\RedirectPaths;
use App\Core\Security\Csrf;
use App\Core\Support\Flash;
use Throwable;

final class AllegroStatusMappingController
{
    public function __construct(
        private readonly Translator $translator,
        private readonly AllegroStatusMappingRepository $statusMappings,
        private readonly OrderStatusRepository $orderStatuses,
        private readonly AllegroStatusDiscoveryService $statusDiscoveryService
    ) {
    }

    public function saveStatusMapping(Request $request): Response
    {
        $csrfError = $this->validateCsrf((string) $request->input('_token', ''));
        if ($csrfError !== null) {
            return $csrfError;
        }

        $allegroStatusCode = strtolower(trim((string) $request->input('allegro_status_code', '')));
        $orderproStatusCode = strtolower(trim((string) $request->input('orderpro_status_code', '')));
        $allegroStatusName = trim((string) $request->input('allegro_status_name', ''));

        if ($allegroStatusCode === '') {
            Flash::set('settings_error', $this->translator->get('settings.allegro.statuses.flash.allegro_status_required'));
            return Response::redirect(RedirectPaths::ALLEGRO_STATUSES_TAB);
        }

        if ($orderproStatusCode === '') {
            Flash::set('settings_error', $this->translator->get('settings.allegro.statuses.flash.orderpro_status_required'));
            return Response::redirect(RedirectPaths::ALLEGRO_STATUSES_TAB);
        }

        if (!$this->orderStatusCodeExists($orderproStatusCode)) {
            Flash::set('settings_error', $this->translator->get('settings.allegro.statuses.flash.orderpro_status_not_found'));
            return Response::redirect(RedirectPaths::ALLEGRO_STATUSES_TAB);
        }

        try {
            $this->statusMappings->upsertMapping($allegroStatusCode, $allegroStatusName !== '' ? $allegroStatusName : null, $orderproStatusCode);
            Flash::set('settings_success', $this->translator->get('settings.allegro.statuses.flash.saved'));
        } catch (Throwable $exception) {
            Flash::set('settings_error', $this->translator->get('settings.allegro.statuses.flash.save_failed') . ' ' . $exception->getMessage());
        }

        return Response::redirect(RedirectPaths::ALLEGRO_STATUSES_TAB);
    }

    public function saveStatusMappingsBulk(Request $request): Response
    {
        $csrfError = $this->validateCsrf((string) $request->input('_token', ''));
        if ($csrfError !== null) {
            return $csrfError;
        }

        $codes = $request->input('allegro_status_code', []);
        $names = $request->input('allegro_status_name', []);
        $selectedOrderproCodes = $request->input('orderpro_status_code', []);
        if (!is_array($codes) || !is_array($names) || !is_array($selectedOrderproCodes)) {
            Flash::set('settings_error', $this->translator->get('settings.allegro.statuses.flash.save_failed'));
            return Response::redirect(RedirectPaths::ALLEGRO_STATUSES_TAB);
        }

        try {
            foreach ($codes as $index => $rawCode) {
                $allegroStatusCode = strtolower(trim((string) $rawCode));
                if ($allegroStatusCode === '') {
                    continue;
                }

                $allegroStatusName = trim((string) ($names[$index] ?? ''));
                $orderproStatusCodeRaw = strtolower(trim((string) ($selectedOrderproCodes[$index] ?? '')));
                $orderproStatusCode = $orderproStatusCodeRaw !== '' ? $orderproStatusCodeRaw : null;

                if ($orderproStatusCode !== null && !$this->orderStatusCodeExists($orderproStatusCode)) {
                    Flash::set('settings_error', $this->translator->get('settings.allegro.statuses.flash.orderpro_status_not_found'));
                    return Response::redirect(RedirectPaths::ALLEGRO_STATUSES_TAB);
                }

                $this->statusMappings->upsertMapping(
                    $allegroStatusCode,
                    $allegroStatusName !== '' ? $allegroStatusName : null,
                    $orderproStatusCode
                );
            }

            Flash::set('settings_success', $this->translator->get('settings.allegro.statuses.flash.saved_bulk'));
        } catch (Throwable $exception) {
            Flash::set('settings_error', $this->translator->get('settings.allegro.statuses.flash.save_failed') . ' ' . $exception->getMessage());
        }

        return Response::redirect(RedirectPaths::ALLEGRO_STATUSES_TAB);
    }

    public function deleteStatusMapping(Request $request): Response
    {
        $csrfError = $this->validateCsrf((string) $request->input('_token', ''));
        if ($csrfError !== null) {
            return $csrfError;
        }

        $mappingId = max(0, (int) $request->input('mapping_id', 0));
        if ($mappingId <= 0) {
            Flash::set('settings_error', $this->translator->get('settings.allegro.statuses.flash.mapping_not_found'));
            return Response::redirect(RedirectPaths::ALLEGRO_STATUSES_TAB);
        }

        try {
            $this->statusMappings->deleteMappingById($mappingId);
            Flash::set('settings_success', $this->translator->get('settings.allegro.statuses.flash.deleted'));
        } catch (Throwable $exception) {
            Flash::set('settings_error', $this->translator->get('settings.allegro.statuses.flash.delete_failed') . ' ' . $exception->getMessage());
        }

        return Response::redirect(RedirectPaths::ALLEGRO_STATUSES_TAB);
    }

    public function syncStatusesFromAllegro(Request $request): Response
    {
        $csrfError = $this->validateCsrf((string) $request->input('_token', ''));
        if ($csrfError !== null) {
            return $csrfError;
        }

        try {
            $result = $this->statusDiscoveryService->discoverAndStoreStatuses(5, 100);
            Flash::set(
                'settings_success',
                $this->translator->get('settings.allegro.statuses.flash.sync_ok', [
                    'discovered' => (string) ((int) ($result['discovered'] ?? 0)),
                    'samples' => (string) ((int) ($result['samples'] ?? 0)),
                ])
            );
        } catch (Throwable $exception) {
            Flash::set('settings_error', $this->translator->get('settings.allegro.statuses.flash.sync_failed') . ' ' . $exception->getMessage());
        }

        return Response::redirect(RedirectPaths::ALLEGRO_STATUSES_TAB);
    }

    private function orderStatusCodeExists(string $code): bool
    {
        $needle = strtolower(trim($code));
        if ($needle === '') {
            return false;
        }

        foreach ($this->orderStatuses->listStatuses() as $row) {
            $statusCode = strtolower(trim((string) ($row['code'] ?? '')));
            if ($statusCode === $needle) {
                return true;
            }
        }

        return false;
    }

    private function validateCsrf(string $token): ?Response
    {
        if (Csrf::validate($token)) {
            return null;
        }

        Flash::set('settings_error', $this->translator->get('auth.errors.csrf_expired'));
        return Response::redirect(RedirectPaths::ALLEGRO_INTEGRATION);
    }
}
