<?php
declare(strict_types=1);

namespace App\Modules\Settings;

use App\Core\Exceptions\IntegrationConfigException;
use App\Core\Http\RedirectPathResolver;
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 Throwable;

final class HostedSmsIntegrationController
{
    public function __construct(
        private readonly Template $template,
        private readonly Translator $translator,
        private readonly AuthService $auth,
        private readonly HostedSmsIntegrationRepository $repository,
        private readonly HostedSmsApiClient $apiClient,
        private readonly IntegrationsRepository $integrations
    ) {
    }

    public function index(Request $request): Response
    {
        $html = $this->template->render('settings/hostedsms', [
            'title' => $this->translator->get('settings.hostedsms.title'),
            'activeMenu' => 'settings',
            'activeSettings' => 'integrations',
            'user' => $this->auth->user(),
            'csrfToken' => Csrf::token(),
            'settings' => $this->repository->getSettings(),
            'errorMessage' => (string) Flash::get('settings_error', ''),
            'successMessage' => (string) Flash::get('settings_success', ''),
            'testMessage' => (string) Flash::get('hostedsms_test', ''),
        ], 'layouts/app');

        return Response::html($html);
    }

    public function save(Request $request): Response
    {
        $redirectTo = $this->resolveRedirect($request);

        if (!Csrf::validate((string) $request->input('_token', ''))) {
            Flash::set('settings_error', $this->translator->get('auth.errors.csrf_expired'));
            return Response::redirect($redirectTo);
        }

        try {
            $this->repository->saveSettings([
                'user_email' => (string) $request->input('user_email', ''),
                'password' => (string) $request->input('password', ''),
                'sender' => (string) $request->input('sender', ''),
                'convert_message_to_gsm7' => $request->input('convert_message_to_gsm7', ''),
                'is_active' => $request->input('is_active', ''),
            ]);
            Flash::set('settings_success', $this->translator->get('settings.hostedsms.flash.saved'));
        } catch (Throwable $exception) {
            Flash::set(
                'settings_error',
                $this->translator->get('settings.hostedsms.flash.save_failed') . ' ' . $exception->getMessage()
            );
        }

        return Response::redirect($redirectTo);
    }

    public function test(Request $request): Response
    {
        $redirectTo = $this->resolveRedirect($request);

        if (!Csrf::validate((string) $request->input('_token', ''))) {
            Flash::set('settings_error', $this->translator->get('auth.errors.csrf_expired'));
            return Response::redirect($redirectTo);
        }

        try {
            $phone = $this->validatePhone((string) $request->input('phone', ''));
            $message = $this->validateMessage((string) $request->input('message', ''));
            $credentials = $this->repository->getCredentials();

            if ($credentials === null) {
                throw new IntegrationConfigException('Najpierw zapisz kompletna konfiguracje HostedSMS.');
            }

            $result = $this->apiClient->sendSms(
                $credentials['user_email'],
                $credentials['password'],
                $credentials['sender'],
                $phone,
                $message,
                $credentials['convert_message_to_gsm7']
            );

            $status = $result['ok'] ? 'ok' : 'fail';
            $this->integrations->updateTestResult(
                $credentials['integration_id'],
                $status,
                (int) $result['http_code'],
                (string) $result['message']
            );

            if ($result['ok']) {
                Flash::set('hostedsms_test', $this->translator->get('settings.hostedsms.flash.test_success', [
                    'message_id' => (string) $result['message_id'],
                ]));
            } else {
                Flash::set('settings_error', $this->translator->get('settings.hostedsms.flash.test_failed') . ' ' . $result['message']);
            }
        } catch (Throwable $exception) {
            Flash::set('settings_error', $this->translator->get('settings.hostedsms.flash.test_failed') . ' ' . $exception->getMessage());
        }

        return Response::redirect($redirectTo);
    }

    private function resolveRedirect(Request $request): string
    {
        return RedirectPathResolver::resolve(
            (string) $request->input('return_to', '/settings/integrations/hostedsms'),
            ['/settings/integrations'],
            '/settings/integrations/hostedsms'
        );
    }

    private function validatePhone(string $value): string
    {
        $phone = preg_replace('/[\s+\-()]/', '', trim($value)) ?? '';
        if (preg_match('/^\d{8,15}$/', $phone) !== 1) {
            throw new IntegrationConfigException('Podaj numer telefonu w formacie miedzynarodowym, np. 48xxxxxxxxx.');
        }

        return $phone;
    }

    private function validateMessage(string $value): string
    {
        $message = trim($value);
        if ($message === '') {
            throw new IntegrationConfigException('Podaj tresc testowego SMS.');
        }
        if (strlen($message) > 4000) {
            throw new IntegrationConfigException('Tresc SMS nie moze przekraczac 4000 znakow.');
        }

        return $message;
    }
}
