<?php

declare(strict_types=1);

namespace App\Modules\Settings;

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

final class EmailTemplateController
{
    private const VARIABLE_GROUPS = [
        'zamowienie' => [
            'label' => 'Zamowienie',
            'vars' => [
                'numer' => 'Numer wewnetrzny (OP...)',
                'numer_zewnetrzny' => 'Numer z platformy',
                'zrodlo' => 'Zrodlo (Allegro/shopPRO/...)',
                'kwota' => 'Kwota brutto',
                'waluta' => 'Waluta (PLN/EUR/...)',
                'data' => 'Data zamowienia',
            ],
        ],
        'kupujacy' => [
            'label' => 'Kupujacy',
            'vars' => [
                'imie_nazwisko' => 'Imie i nazwisko',
                'email' => 'Adres e-mail',
                'telefon' => 'Telefon',
                'login' => 'Login platformy',
            ],
        ],
        'adres' => [
            'label' => 'Adres dostawy',
            'vars' => [
                'ulica' => 'Ulica z numerem',
                'miasto' => 'Miasto',
                'kod_pocztowy' => 'Kod pocztowy',
                'kraj' => 'Kraj',
            ],
        ],
        'firma' => [
            'label' => 'Firma',
            'vars' => [
                'nazwa' => 'Nazwa firmy',
                'nip' => 'NIP',
            ],
        ],
        'przesylka' => [
            'label' => 'Przesylka',
            'vars' => [
                'numer' => 'Numer przesylki (tracking)',
                'link_sledzenia' => 'Link sledzenia zalezny od kuriera',
            ],
        ],
    ];

    private const ATTACHMENT_TYPES = [
        'receipt' => 'Paragon',
    ];

    private const SAMPLE_DATA = [
        'zamowienie.numer' => 'OP000001234',
        'zamowienie.numer_zewnetrzny' => 'ALG-98765432',
        'zamowienie.zrodlo' => 'Allegro',
        'zamowienie.kwota' => '149,99',
        'zamowienie.waluta' => 'PLN',
        'zamowienie.data' => '2026-03-16',
        'kupujacy.imie_nazwisko' => 'Jan Kowalski',
        'kupujacy.email' => 'jan.kowalski@example.com',
        'kupujacy.telefon' => '+48 600 123 456',
        'kupujacy.login' => 'jankowalski82',
        'adres.ulica' => 'ul. Dluga 15/3',
        'adres.miasto' => 'Warszawa',
        'adres.kod_pocztowy' => '00-238',
        'adres.kraj' => 'PL',
        'firma.nazwa' => 'Przykladowa Firma Sp. z o.o.',
        'firma.nip' => '5271234567',
        'przesylka.numer' => '123456789012345678901234',
        'przesylka.link_sledzenia' => 'https://inpost.pl/sledzenie-przesylek?number=123456789012345678901234',
    ];

    public function __construct(
        private readonly Template $template,
        private readonly Translator $translator,
        private readonly AuthService $auth,
        private readonly EmailTemplateRepository $repository,
        private readonly EmailMailboxRepository $mailboxRepository
    ) {
    }

    public function index(Request $request): Response
    {
        $templates = $this->repository->listAll();

        $html = $this->template->render('settings/email-templates', [
            'title' => 'Szablony e-mail',
            'activeMenu' => 'settings',
            'activeSettings' => 'email-templates',
            'user' => $this->auth->user(),
            'csrfToken' => Csrf::token(),
            'templates' => $templates,
            'attachmentTypes' => self::ATTACHMENT_TYPES,
            'successMessage' => Flash::get('settings.email_templates.success', ''),
            'errorMessage' => Flash::get('settings.email_templates.error', ''),
        ], 'layouts/app');

        return Response::html($html);
    }

    public function create(Request $request): Response
    {
        return $this->renderForm(null);
    }

    public function edit(Request $request): Response
    {
        $id = (int) $request->input('id', '0');
        $template = $id > 0 ? $this->repository->findById($id) : null;

        if ($template === null) {
            Flash::set('settings.email_templates.error', 'Nie znaleziono szablonu');
            return Response::redirect('/settings/email-templates');
        }

        return $this->renderForm($template);
    }

    public function save(Request $request): Response
    {
        $templateId = (int) $request->input('id', '0');
        $formPath = $this->buildFormPath($templateId > 0 ? $templateId : null);

        if (!Csrf::validate((string) $request->input('_token', ''))) {
            Flash::set('settings.email_templates.error', 'Nieprawidlowy token CSRF');
            return Response::redirect($formPath);
        }

        $name = trim((string) $request->input('name', ''));
        $subject = trim((string) $request->input('subject', ''));
        $bodyHtml = (string) $request->input('body_html', '');

        if ($name === '' || $subject === '' || $bodyHtml === '') {
            Flash::set('settings.email_templates.error', 'Nazwa, temat i tresc sa wymagane');
            return Response::redirect($formPath);
        }

        $attachment1Raw = trim((string) $request->input('attachment_1', ''));
        $attachment1 = isset(self::ATTACHMENT_TYPES[$attachment1Raw]) ? $attachment1Raw : '';

        try {
            $this->repository->save([
                'id' => $request->input('id', ''),
                'name' => $name,
                'subject' => $subject,
                'body_html' => $bodyHtml,
                'mailbox_id' => $request->input('mailbox_id', ''),
                'attachment_1' => $attachment1,
                'is_active' => $request->input('is_active', null),
            ]);

            Flash::set('settings.email_templates.success', 'Szablon zostal zapisany');
        } catch (Throwable) {
            Flash::set('settings.email_templates.error', 'Blad zapisu szablonu');
            return Response::redirect($formPath);
        }

        return Response::redirect('/settings/email-templates');
    }

    public function delete(Request $request): Response
    {
        if (!Csrf::validate((string) $request->input('_token', ''))) {
            Flash::set('settings.email_templates.error', 'Nieprawidlowy token CSRF');
            return Response::redirect('/settings/email-templates');
        }

        $id = (int) $request->input('id', '0');
        if ($id <= 0) {
            Flash::set('settings.email_templates.error', 'Nieprawidlowy identyfikator szablonu');
            return Response::redirect('/settings/email-templates');
        }

        try {
            $this->repository->delete($id);
            Flash::set('settings.email_templates.success', 'Szablon zostal usuniety');
        } catch (Throwable) {
            Flash::set('settings.email_templates.error', 'Blad usuwania szablonu');
        }

        return Response::redirect('/settings/email-templates');
    }

    public function toggleStatus(Request $request): Response
    {
        if (!Csrf::validate((string) $request->input('_token', ''))) {
            return Response::json(['success' => false, 'message' => 'Nieprawidlowy token CSRF'], 403);
        }

        $id = (int) $request->input('id', '0');
        if ($id <= 0) {
            return Response::json(['success' => false, 'message' => 'Nieprawidlowy identyfikator'], 400);
        }

        try {
            $this->repository->toggleStatus($id);
            return Response::json(['success' => true]);
        } catch (Throwable) {
            return Response::json(['success' => false, 'message' => 'Blad zmiany statusu'], 500);
        }
    }

    public function duplicate(Request $request): Response
    {
        if (!Csrf::validate((string) $request->input('_token', ''))) {
            Flash::set('settings.email_templates.error', 'Nieprawidlowy token CSRF');
            return Response::redirect('/settings/email-templates');
        }

        $id = (int) $request->input('id', '0');
        if ($id <= 0) {
            Flash::set('settings.email_templates.error', 'Nieprawidlowy identyfikator szablonu');
            return Response::redirect('/settings/email-templates');
        }

        try {
            $this->repository->duplicate($id);
            Flash::set('settings.email_templates.success', 'Szablon zostal zduplikowany');
        } catch (Throwable) {
            Flash::set('settings.email_templates.error', 'Blad duplikowania szablonu');
        }

        return Response::redirect('/settings/email-templates');
    }

    public function preview(Request $request): Response
    {
        if (!Csrf::validate((string) $request->input('_token', ''))) {
            return Response::json(['success' => false, 'message' => 'Nieprawidlowy token CSRF'], 403);
        }

        $subject = (string) $request->input('subject', '');
        $bodyHtml = (string) $request->input('body_html', '');

        return Response::json([
            'success' => true,
            'subject' => self::resolveVariables($subject, self::SAMPLE_DATA),
            'body_html' => self::resolveVariables($bodyHtml, self::SAMPLE_DATA),
        ]);
    }

    public function getVariables(Request $request): Response
    {
        return Response::json([
            'success' => true,
            'groups' => self::VARIABLE_GROUPS,
        ]);
    }

    /**
     * @param array<string, string> $data
     */
    public static function resolveVariables(string $text, array $data): string
    {
        return (string) preg_replace_callback(
            '/\{\{([a-z_]+)\.([a-z_]+)\}\}/',
            static function (array $matches) use ($data): string {
                $key = $matches[1] . '.' . $matches[2];
                return $data[$key] ?? $matches[0];
            },
            $text
        );
    }

    private function renderForm(?array $template): Response
    {
        $html = $this->template->render('settings/email-templates-form', [
            'title' => $template !== null ? 'Edytuj szablon e-mail' : 'Nowy szablon e-mail',
            'activeMenu' => 'settings',
            'activeSettings' => 'email-templates',
            'user' => $this->auth->user(),
            'csrfToken' => Csrf::token(),
            'mailboxes' => $this->mailboxRepository->listActive(),
            'template' => $template,
            'variableGroups' => self::VARIABLE_GROUPS,
            'attachmentTypes' => self::ATTACHMENT_TYPES,
            'successMessage' => Flash::get('settings.email_templates.success', ''),
            'errorMessage' => Flash::get('settings.email_templates.error', ''),
        ], 'layouts/app');

        return Response::html($html);
    }

    private function buildFormPath(?int $templateId): string
    {
        if ($templateId !== null && $templateId > 0) {
            return '/settings/email-templates/edit?id=' . $templateId;
        }

        return '/settings/email-templates/create';
    }
}
