<?php
namespace admin\Controllers;

use Domain\Languages\LanguagesRepository;
use Domain\Settings\SettingsRepository;
use admin\ViewModels\Forms\FormEditViewModel;
use admin\ViewModels\Forms\FormField;
use admin\ViewModels\Forms\FormTab;
use admin\ViewModels\Forms\FormAction;
use admin\Support\Forms\FormRequestHandler;

/**
 * Kontroler ustawien w panelu administratora.
 */
class SettingsController
{
    private SettingsRepository $settingsRepository;
    private LanguagesRepository $languagesRepository;
    private FormRequestHandler $formHandler;

    public function __construct(SettingsRepository $settingsRepository, LanguagesRepository $languagesRepository)
    {
        $this->settingsRepository = $settingsRepository;
        $this->languagesRepository = $languagesRepository;
        $this->formHandler = new FormRequestHandler();
    }

    /**
     * Czyszczenie cache.
     */
    public function clearCache(): void
    {
        \Shared\Helpers\Helpers::delete_dir('../temp/');
        \Shared\Helpers\Helpers::delete_dir('../thumbs/');

        $redis = \Shared\Cache\RedisConnection::getInstance()->getConnection();
        if ($redis) {
            $redis->flushAll();
        }

        \Shared\Helpers\Helpers::alert('Cache został wyczyszczony.');
        \Shared\Helpers\Helpers::htacces();

        header('Location: /admin/dashboard/main_view/');
        exit;
    }

    /**
     * Czyszczenie cache (AJAX).
     */
    public function clearCacheAjax(): void
    {
        try {
            \Shared\Helpers\Helpers::delete_dir('../temp/');
            \Shared\Helpers\Helpers::delete_dir('../thumbs/');

            $redis = \Shared\Cache\RedisConnection::getInstance()->getConnection();
            if ($redis) {
                $redis->flushAll();
            }

            \Shared\Helpers\Helpers::htacces();

            echo json_encode(['status' => 'success', 'message' => 'Cache został wyczyszczony.']);
        } catch (\Exception $e) {
            echo json_encode(['status' => 'error', 'message' => 'Błąd podczas czyszczenia cache: ' . $e->getMessage()]);
        }
        exit;
    }

    /**
     * Globalna wyszukiwarka admin (produkty + zamowienia) - AJAX.
     */
    public function globalSearchAjax(): void
    {
        global $mdb;

        $phrase = trim((string)\Shared\Helpers\Helpers::get('q'));
        if ($phrase === '' || mb_strlen($phrase) < 2) {
            echo json_encode([
                'status' => 'ok',
                'items' => [],
            ]);
            exit;
        }

        $phrase = mb_substr($phrase, 0, 120);
        $phraseNormalized = preg_replace('/\s+/', ' ', $phrase);
        $phraseNormalized = trim((string)$phraseNormalized);
        $like = '%' . $phrase . '%';
        $likeNormalized = '%' . $phraseNormalized . '%';

        $items = [];
        $defaultLang = (string)$this->languagesRepository->defaultLanguage();

        try {
            $productStmt = $mdb->query(
                'SELECT '
                . 'p.id, p.ean, p.sku, p.parent_id, psl.name '
                . 'FROM pp_shop_products AS p '
                . 'LEFT JOIN pp_shop_products_langs AS psl ON psl.product_id = p.id AND psl.lang_id = :lang_id '
                . 'WHERE '
                . '(p.ean LIKE :q1 OR p.sku LIKE :q2 OR psl.name LIKE :q3) '
                . 'AND p.archive != 1 '
                . 'ORDER BY p.id DESC '
                . 'LIMIT 15',
                [
                    ':lang_id' => $defaultLang,
                    ':q1' => $like,
                    ':q2' => $like,
                    ':q3' => $like,
                ]
            );
        } catch (\Throwable $e) {
            $productStmt = false;
        }

        $productRows = $productStmt ? $productStmt->fetchAll() : [];
        if (is_array($productRows)) {
            foreach ($productRows as $row) {
                $productId = (int)($row['id'] ?? 0);
                if ($productId <= 0) {
                    continue;
                }

                $name = trim((string)($row['name'] ?? ''));
                if ($name === '') {
                    $name = 'Produkt #' . $productId;
                }

                $meta = [];
                $sku = trim((string)($row['sku'] ?? ''));
                $ean = trim((string)($row['ean'] ?? ''));
                if ($sku !== '') {
                    $meta[] = 'SKU: ' . $sku;
                }
                if ($ean !== '') {
                    $meta[] = 'EAN: ' . $ean;
                }

                $items[] = [
                    'type' => 'product',
                    'title' => $name,
                    'subtitle' => implode(' | ', $meta),
                    'url' => '/admin/shop_product/product_edit/id=' . $productId,
                ];
            }
        }

        try {
            $orderStmt = $mdb->query(
                'SELECT '
                . 'id, number, client_name, client_surname, client_email, client_phone '
                . 'FROM pp_shop_orders '
                . 'WHERE '
                . '('
                . 'number LIKE :q1 '
                . 'OR client_email LIKE :q2 '
                . 'OR client_name LIKE :q3 '
                . 'OR client_surname LIKE :q4 '
                . 'OR client_phone LIKE :q5 '
                . "OR CONCAT_WS(' ', TRIM(client_name), TRIM(client_surname)) LIKE :q6 "
                . "OR CONCAT_WS(' ', TRIM(client_surname), TRIM(client_name)) LIKE :q7 "
                . ') '
                . 'ORDER BY id DESC '
                . 'LIMIT 15',
                [
                    ':q1' => $like,
                    ':q2' => $like,
                    ':q3' => $like,
                    ':q4' => $like,
                    ':q5' => $like,
                    ':q6' => $likeNormalized,
                    ':q7' => $likeNormalized,
                ]
            );
        } catch (\Throwable $e) {
            $orderStmt = false;
        }

        $orderRows = $orderStmt ? $orderStmt->fetchAll() : [];
        if (is_array($orderRows)) {
            foreach ($orderRows as $row) {
                $orderId = (int)($row['id'] ?? 0);
                if ($orderId <= 0) {
                    continue;
                }

                $orderNumber = trim((string)($row['number'] ?? ''));
                $clientName = trim((string)($row['client_name'] ?? ''));
                $clientSurname = trim((string)($row['client_surname'] ?? ''));
                $clientEmail = trim((string)($row['client_email'] ?? ''));
                $clientPhone = trim((string)($row['client_phone'] ?? ''));

                $title = $orderNumber !== '' ? 'Zamówienie ' . $orderNumber : 'Zamówienie #' . $orderId;
                $subtitleParts = [];
                $fullName = trim($clientName . ' ' . $clientSurname);
                if ($fullName !== '') {
                    $subtitleParts[] = $fullName;
                }
                if ($clientEmail !== '') {
                    $subtitleParts[] = $clientEmail;
                }
                if ($clientPhone !== '') {
                    $subtitleParts[] = $clientPhone;
                }

                $items[] = [
                    'type' => 'order',
                    'title' => $title,
                    'subtitle' => implode(' | ', $subtitleParts),
                    'url' => '/admin/shop_order/order_details/order_id=' . $orderId,
                ];
            }
        }

        echo json_encode([
            'status' => 'ok',
            'items' => array_slice($items, 0, 20),
        ]);
        exit;
    }

    /**
     * Zapis ustawien (AJAX).
     */
    public function save(): void
    {
        // Kompatybilnosc wsteczna dla legacy gridEdit (values jako JSON).
        $legacyValues = \Shared\Helpers\Helpers::get('values');
        if ($legacyValues) {
            $values = json_decode($legacyValues, true);
            $result = $this->settingsRepository->saveSettings(is_array($values) ? $values : []);

            \Shared\Helpers\Helpers::delete_dir('../temp/');
            \Shared\Helpers\Helpers::htacces();

            echo json_encode($result);
            exit;
        }

        $languages = $this->languagesRepository->languagesList();
        $settings = $this->settingsRepository->getSettings();
        $viewModel = $this->buildFormViewModel($settings, $languages);

        $result = $this->formHandler->handleSubmit($viewModel, $_POST);
        if (!$result['success']) {
            $_SESSION['form_errors'][$this->getFormId()] = $result['errors'];
            echo json_encode(['success' => false, 'errors' => $result['errors']]);
            exit;
        }

        $values = $this->transformFormDataToSettings($result['data']);
        $saveResult = $this->settingsRepository->saveSettings($values);

        \Shared\Helpers\Helpers::delete_dir('../temp/');
        \Shared\Helpers\Helpers::htacces();

        echo json_encode([
            'success' => ($saveResult['status'] ?? '') === 'ok',
            'message' => $saveResult['msg'] ?? 'Ustawienia zostały zapisane.',
            'errors' => (($saveResult['status'] ?? '') === 'ok') ? [] : ['general' => ($saveResult['msg'] ?? 'Błąd zapisu.')],
        ]);
        exit;
    }

    /**
     * Widok ustawien.
     */
    public function view(): string
    {
        $languages = $this->languagesRepository->languagesList();
        $settings = $this->settingsRepository->getSettings();

        $validationErrors = $_SESSION['form_errors'][$this->getFormId()] ?? null;
        if ($validationErrors) {
            unset($_SESSION['form_errors'][$this->getFormId()]);
        }

        $viewModel = $this->buildFormViewModel($settings, $languages, $validationErrors);

        return \Shared\Tpl\Tpl::view('components/form-edit', ['form' => $viewModel]);
    }

    private function buildFormViewModel(array $settings, array $languages, ?array $errors = null): FormEditViewModel
    {
        $data = $this->transformSettingsToFormData($settings, $languages);

        $tabs = [
            new FormTab('contact', 'Dane kontaktowe', 'fa-paper-plane'),
            new FormTab('shop', 'Sklep', 'fa-dollar'),
            new FormTab('products', 'Produkty', 'fa-shopping-cart'),
            new FormTab('mail', 'Poczta', 'fa-envelope'),
            new FormTab('other', 'Pozostałe', 'fa-bars'),
            new FormTab('system', 'System', 'fa-cog'),
            new FormTab('conversions', 'Konwersje', 'fa-line-chart'),
        ];

        $fields = [
            FormField::text('firm_name', [
                'label' => 'Nazwa firmy',
                'tab' => 'contact',
            ]),
            FormField::editor('additional_info', [
                'label' => 'Dodatkowe informacje',
                'tab' => 'contact',
                'height' => 150,
            ]),
            FormField::switch('google_maps', [
                'label' => 'Mapa',
                'tab' => 'contact',
            ]),
            FormField::textarea('firm_adress', [
                'label' => 'Mapa - adres',
                'tab' => 'contact',
            ]),

            FormField::editor('shop_bank_account_info', [
                'label' => 'Dane do przelewu',
                'tab' => 'shop',
                'height' => 200,
            ]),
            FormField::text('hotpay_api', [
                'label' => 'Klucz API HotPay',
                'tab' => 'shop',
            ]),
            FormField::switch('tpay_sandbox', [
                'label' => 'Tpay.com - tryb sandbox',
                'tab' => 'shop',
            ]),
            FormField::text('tpay_id', [
                'label' => 'Tpay.com ID',
                'tab' => 'shop',
            ]),
            FormField::text('tpay_security_code', [
                'label' => 'Tpay.com - kod bezpieczeństwa',
                'tab' => 'shop',
            ]),
            FormField::switch('przelewy24_sandbox', [
                'label' => 'Przelewy24.pl - tryb sandbox',
                'tab' => 'shop',
            ]),
            FormField::text('przelewy24_merchant_id', [
                'label' => 'Przelewy24.pl - merchant ID',
                'tab' => 'shop',
            ]),
            FormField::text('przelewy24_crc_key', [
                'label' => 'Przelewy24.pl - klucz CRC',
                'tab' => 'shop',
            ]),
            FormField::text('free_delivery', [
                'label' => 'Darmowa dostawa od',
                'tab' => 'shop',
                'attributes' => ['class' => 'number-format'],
            ]),
            FormField::text('orlen_paczka_map_token', [
                'label' => 'Orlen Paczka map token',
                'tab' => 'shop',
            ]),

            FormField::langSection('warehouse_messages', 'products', [
                FormField::text('warehouse_message_zero', [
                    'label' => 'Komunikat gdy stan magazynowy równy 0',
                ]),
                FormField::text('warehouse_message_nonzero', [
                    'label' => 'Komunikat gdy stan magazynowy większy niż 0',
                ]),
            ]),

            FormField::switch('contact_form', [
                'label' => 'Formularz kontaktowy',
                'tab' => 'mail',
            ]),
            FormField::text('contact_email', [
                'label' => 'Email kontaktowy',
                'tab' => 'mail',
            ]),
            FormField::text('email_host', [
                'label' => 'Email - host',
                'tab' => 'mail',
            ]),
            FormField::text('email_port', [
                'label' => 'Email - port',
                'tab' => 'mail',
            ]),
            FormField::text('email_login', [
                'label' => 'Email - login',
                'tab' => 'mail',
            ]),
            FormField::text('email_password', [
                'label' => 'Email - hasło',
                'tab' => 'mail',
            ]),

            FormField::text('facebook_link', [
                'label' => 'Facebook link',
                'tab' => 'other',
            ]),
            FormField::text('piksel', [
                'label' => 'Piksel Facebook',
                'tab' => 'other',
            ]),
            FormField::textarea('statistic_code', [
                'label' => 'Kod statystyk',
                'tab' => 'other',
                'rows' => 10,
            ]),
            FormField::textarea('htaccess', [
                'label' => 'Własne reguły htacess',
                'tab' => 'other',
                'rows' => 10,
            ]),
            FormField::textarea('robots', [
                'label' => 'Własne reguły robots.txt',
                'tab' => 'other',
                'rows' => 10,
            ]),

            FormField::switch('update', [
                'label' => 'Aktualizacja',
                'tab' => 'system',
            ]),
            FormField::text('update_key', [
                'label' => 'Numer licencji',
                'tab' => 'system',
            ]),
            FormField::switch('devel', [
                'label' => 'Strona konstrukcyjna',
                'tab' => 'system',
            ]),
            FormField::switch('lazy_loading', [
                'label' => 'Lazy loading obrazów',
                'tab' => 'system',
            ]),
            FormField::switch('generate_webp', [
                'label' => 'Generowanie obrazków WEBP',
                'tab' => 'system',
            ]),
            FormField::switch('infinitescroll', [
                'label' => 'Infinitescroll',
                'tab' => 'system',
            ]),
            FormField::switch('htaccess_cache', [
                'label' => 'Htaccess cache',
                'tab' => 'system',
            ]),

            FormField::text('google_tag_manager_id', [
                'label' => 'Google Tag Manager - ID',
                'tab' => 'conversions',
            ]),
            FormField::textarea('own_gtm_js', [
                'label' => 'Własny kod GTM JS (bez tagu script)',
                'tab' => 'conversions',
                'rows' => 10,
            ]),
            FormField::textarea('own_gtm_html', [
                'label' => 'Własny kod GTM HTML',
                'tab' => 'conversions',
                'rows' => 10,
            ]),
        ];

        $actions = [
            FormAction::save('/admin/settings/save/', ''),
        ];

        return new FormEditViewModel(
            $this->getFormId(),
            'Edycja ustawień',
            $data,
            $fields,
            $tabs,
            $actions,
            'POST',
            '/admin/settings/save/',
            null,
            false,
            [],
            $languages,
            $errors
        );
    }

    private function getFormId(): string
    {
        return 'settings-edit';
    }

    private function transformSettingsToFormData(array $settings, array $languages): array
    {
        $data = $settings;
        $data['languages'] = [];

        foreach ($languages as $lang) {
            if (!($lang['status'] ?? false)) {
                continue;
            }

            $langId = (string)$lang['id'];
            $data['languages'][$langId] = [
                'warehouse_message_zero' => $settings['warehouse_message_zero_' . $langId] ?? '',
                'warehouse_message_nonzero' => $settings['warehouse_message_nonzero_' . $langId] ?? '',
            ];
        }

        return $data;
    }

    private function transformFormDataToSettings(array $data): array
    {
        if (!isset($data['warehouse_messages']) || !is_array($data['warehouse_messages'])) {
            return $data;
        }

        $data['warehouse_message_zero'] = [];
        $data['warehouse_message_nonzero'] = [];

        foreach ($data['warehouse_messages'] as $langId => $langValues) {
            if (!is_array($langValues)) {
                continue;
            }

            $data['warehouse_message_zero'][$langId] = $langValues['warehouse_message_zero'] ?? '';
            $data['warehouse_message_nonzero'][$langId] = $langValues['warehouse_message_nonzero'] ?? '';
        }

        unset($data['warehouse_messages']);

        return $data;
    }
}
