<?php

namespace Bot;

use Bot\IppanelSmsHandler;
use Payment\ZarinpalPaymentHandler;

class FormManager
{
    private $bot;
    private $stateManager;
    private $forms;

    private static $fileCache = [];

    public function __construct(BotHandler $bot, StateManager $stateManager, array $formsConfig)
    {
        $this->bot = $bot;
        $this->stateManager = $stateManager;
        $this->forms = $formsConfig;
    }

    public function start(string $chatId, string $formKey, ?string $callbackQueryId = null, ?int $messageId = null): void
    {
        if (!isset($this->forms[$formKey])) {
            error_log("[Form Start Failed] Form key '{$formKey}' not found. chat_id={$chatId}");
            return;
        }

        $form = $this->forms[$formKey];
        $steps = array_keys($form['fields']);
        $initialStep = $steps[0];

        $state = [
            'form_key' => $formKey,
            'current_step' => $initialStep,
            'chat_id' => $chatId,
            'steps' => $steps,
            'data' => [],
            'form_message_id' => $messageId,
            'pages' => [],
        ];

        $this->stateManager->saveState($chatId, $state);
        $this->askQuestion($chatId, $callbackQueryId);
    }

    public function handle(string $chatId, $input, ?string $callbackQueryId = null): void
    {
        if (!$this->stateManager->lockState($chatId)) {
            $this->bot->sendRequest('sendMessage', [
                'chat_id' => $chatId,
                'text' => '⏳ در حال پردازش درخواست قبلی شما هستم...'
            ]);
            return;
        }

        try {
            $state = $this->stateManager->getState($chatId);
            if (!$state || !isset($state['form_key'])) {
                $this->sendUserFriendlyError($chatId, "فرمی برای پردازش یافت نشد.");
                return;
            }

            $formKey = $state['form_key'];
            $stepKey = $state['current_step'];
            $fieldConfig = $this->forms[$formKey]['fields'][$stepKey] ?? null;

            if (!$fieldConfig) {
                $this->sendUserFriendlyError($chatId, "خطایی در پردازش فرم رخ داد.");
                return;
            }

            $value = $this->extractValueFromInput($input);
            if ($value === null) {
                $this->sendUserFriendlyError($chatId, "ورودی نامعتبر است. لطفاً ورودی مناسب را وارد کنید.");
                return;
            }

            // 🎯 ورود به حالت قیمت‌گذاری
            if (isset($state['pricing_for'])) {

                $optionKey = $state['pricing_for'];
                $allOptions = $this->forms[$formKey]['fields']['transport_options']['options'] ?? [];

                if (!isset($allOptions[$optionKey])) {
                    $this->sendUserFriendlyError($chatId, "گزینه قیمت‌گذاری نامعتبر است.");
                    unset($state['pricing_for']);
                    $this->stateManager->saveState($chatId, $state);
                    $this->proceedToNextStep($chatId);
                    return;
                }

                $optionLabel = $allOptions[$optionKey];

                if (!is_numeric($value)) {
                    $this->sendUserFriendlyError($chatId, "مبلغ وارد شده برای \"$optionLabel\" نامعتبر است. لطفاً فقط عدد وارد کنید.");
                    $this->askForNextPrice($chatId, true);
                    return;
                }

                $cleanValue = preg_replace('/[^\d]/', '', $value);
                $amount = (int)$cleanValue;

                if (!isset($state['data']['pricing'])) {
                    $state['data']['pricing'] = [];
                }

                $state['data']['pricing'][$optionKey] = [
                    'label' => $optionLabel,
                    'amount' => $amount
                ];
                unset($state['pricing_for']);
                $this->stateManager->saveState($chatId, $state);
                $this->askForNextPrice($chatId);
                return;
            }

            // ⛔️ بررسی دکمه‌های ثابت
            if (is_string($value)) {
                switch ($value) {
                    case 'form_action_back':
                        $this->goToPreviousStep($chatId);
                        return;
                    case 'form_action_cancel':
                        $this->cancelForm($chatId, $state);
                        return;
                    case 'form_page_prev':
                    case 'form_page_next':
                        $this->handlePageChange($chatId, $value, $state);
                        return;
                    case 'form_action_proceed':
                        $currentStepKey = $state['current_step'];
                        $currentFieldConfig = $this->forms[$formKey]['fields'][$currentStepKey];
                        $currentValue = $state['data'][$currentStepKey] ?? [];

                        $validationResult = $this->validate(
                            $currentValue,
                            $currentFieldConfig['validation'] ?? '',
                            $state['data'],
                            $callbackQueryId,
                            $chatId
                        );
                        if ($validationResult) {
                            $this->proceedToNextStep($chatId);
                        }
                        return;
                    case 'form_action_skip':
                        $state['data'][$stepKey] = null;
                        $this->stateManager->saveState($chatId, $state);
                        $this->proceedToNextStep($chatId);
                        return;
                }
            }


            // 🔘 گزینه‌های چندتایی
            if (is_string($value) && str_starts_with($value, 'form_toggle_option_')) {
                $optionKey = str_replace('form_toggle_option_', '', $value);
                if (!isset($fieldConfig['options'][$optionKey])) {
                    $this->sendUserFriendlyError($chatId, "گزینه انتخاب‌شده نامعتبر است.");
                    return;
                }

                $selected = $state['data'][$stepKey] ?? [];
                $selected = in_array($optionKey, $selected)
                    ? array_diff($selected, [$optionKey])
                    : array_merge($selected, [$optionKey]);

                $state['data'][$stepKey] = array_values($selected);
                $this->stateManager->saveState($chatId, $state);
                $this->askQuestion($chatId);
                return;
            }

            // 🔒 بررسی غیرمنتظره
            if (isset($state['pricing_for'])) {
                $this->sendUserFriendlyError($chatId, "خطایی در قیمت‌گذاری رخ داده است. لطفاً مجدد تلاش کنید.");
                return;
            }


            // ✅ اعتبارسنجی نهایی
            $fieldType = $fieldConfig['type'] ?? 'text';
            if ($fieldType === 'location') {
                if (is_array($value) && isset($value['latitude'], $value['longitude'])) {
                    // ولیدیشن موفق است
                } else {
                    $this->sendUserFriendlyError($chatId, "لطفاً یک موقعیت مکانی (Location) از طریق دکمه سنجاق (📎) ارسال کنید.");
                    return;
                }
            } else {
                // ولیدیشن برای سایر فیلدها
                $validationResult = $this->validate($value, $fieldConfig['validation'] ?? '', $state['data'], $callbackQueryId, $chatId);
                if (!$validationResult) {
                    return;
                }
            }



            $state['data'][$stepKey] = $this->extractValueForStorage($value, $fieldConfig['type'] ?? 'text');
            $this->stateManager->saveState($chatId, $state);
            $this->proceedToNextStep($chatId);
        } finally {
            $this->stateManager->unlockState($chatId);
        }
    }



    private function extractValueFromInput($input)
    {
        if (is_string($input)) {
            return $input;
        }
        if (is_array($input)) {
            if (isset($input['photo'])) return $input;
            if (isset($input['location'])) return $input['location']; // ✅ این خط را اضافه کنید
            if (isset($input['text'])) return $input['text'];
        }
        return null;
    }

    private function extractValueForStorage($value, $type)
    {
        if ($type === 'photo' && is_array($value)) {
            return end($value['photo'])['file_id'];
        }
        // ✅ اگر نوع فیلد location بود، خود آرایه لوکیشن را برگردان
        if ($type === 'location' && is_array($value)) {
            return $value; // ['latitude' => ..., 'longitude' => ...]
        }
        return $value;
    }


    public function goToPreviousStep(string $chatId): void
    {
        $state = $this->stateManager->getState($chatId);
        if (!$state) return;

        $currentStepIndex = array_search($state['current_step'], $state['steps']);

        // از یک مرحله قبل از مرحله فعلی، شروع به جستجو به عقب می‌کنیم
        $previousStepIndex = $currentStepIndex - 1;

        while ($previousStepIndex >= 0) {
            $previousStepKey = $state['steps'][$previousStepIndex];
            $fieldConfig = $this->forms[$state['form_key']]['fields'][$previousStepKey];
            $fieldType = $fieldConfig['type'] ?? 'text';

            $shouldSkip = false;

            // مراحل شرطی را بررسی می‌کنیم تا از آنها بپریم
            if ($fieldType === 'conditional_text') {
                $conditionField = $fieldConfig['condition_field'];
                $conditionValue = $fieldConfig['condition_value'];
                if (!in_array($conditionValue, $state['data'][$conditionField] ?? [])) {
                    $shouldSkip = true;
                }
            }
            if ($fieldType === 'conditional_pricing') {
                $basedOnField = $fieldConfig['based_on'];
                if (empty($state['data'][$basedOnField] ?? [])) {
                    $shouldSkip = true;
                }
            }

            if ($shouldSkip) {
               
                $previousStepIndex--;
                continue;
            } else {
                for ($i = $currentStepIndex; $i > $previousStepIndex; $i--) {
                    $stepToClear = $state['steps'][$i];
                    unset($state['data'][$stepToClear]);
                    error_log("Form data for step '{$stepToClear}' cleared due to going back.");
                }
                $state['current_step'] = $previousStepKey;
                $this->stateManager->saveState($chatId, $state);
                $this->askQuestion($chatId);
                return; 
            }
        }

        error_log("Could not find a valid previous step to go back to for chatId: {$chatId}");
    }

    public function handleAttachment(string $chatId, array $message): void
    {
        $item = null;
        if (!empty($message['text'])) {
            $item = ['type' => 'text', 'file_id' => null, 'caption' => $message['text']];
        } elseif (!empty($message['photo'])) {
            $item = ['type' => 'photo', 'file_id' => end($message['photo'])['file_id'], 'caption' => $message['caption'] ?? null];
        } elseif (!empty($message['video'])) {
            $item = ['type' => 'video', 'file_id' => $message['video']['file_id'], 'caption' => $message['caption'] ?? null];
        } elseif (!empty($message['document'])) {
            $item = ['type' => 'document', 'file_id' => $message['document']['file_id'], 'caption' => $message['caption'] ?? null];
        }
        if ($item) {
            $state = $this->stateManager->getState($chatId);
            if ($state && ($state['current_step'] ?? '') === 'attachments') {
                if (!isset($state['temp_attachments'])) $state['temp_attachments'] = [];
                $state['temp_attachments'][] = $item;
                $this->stateManager->saveState($chatId, $state);
                $this->bot->sendRequest("sendMessage", ['chat_id' => $chatId, 'text' => '✅ پیوست شما افزوده شد.']);
            }
        }
    }

    private function handleMultiInputStart(string $chatId, array $fieldConfig, array &$state): void
    {
        $state['temp_attachments'] = [];
        $this->stateManager->saveState($chatId, $state);
        $prompt = $fieldConfig['prompt'];
        $finishButtonText = $fieldConfig['finish_button_text'] ?? 'اتمام';
        $messageId = $state['form_message_id'] ?? null;

        $params = [
            'chat_id' => $chatId,
            'text' => $prompt,
            'reply_markup' => json_encode([
                'inline_keyboard' => [[['text' => $finishButtonText, 'callback_data' => 'form_action_finish_attachments']]]
            ])
        ];
        if ($messageId) {
            $this->bot->sendRequest('editMessageText', array_merge($params, ['message_id' => $messageId]));
        } else {
            $this->bot->sendRequest('sendMessage', $params);
        }
    }

    public function askQuestion(string $chatId, ?string $callbackQueryId = null): void
    {
        $state = $this->stateManager->getState($chatId);
        if (!$state) {
            $this->sendUserFriendlyError($chatId, "خطای داخلی در فرم رخ داد. لطفاً دوباره تلاش کنید.");
            return;
        }

        $stepKey = $state['current_step'];
        $formKey = $state['form_key'];
        $fieldConfig = $this->forms[$formKey]['fields'][$stepKey];
        $data = $state['data'] ?? [];
        $messageId = $state['form_message_id'] ?? null;
        $questionText = $this->buildQuestionText($formKey, $stepKey, $data);
        $fieldType = $fieldConfig['type'] ?? 'text';
        $keyboard = $this->buildKeyboard($formKey, $stepKey, $data, $chatId);
        // برای فیلدهای تاریخ و زمان که منطق کاملاً متفاوتی دارند، بلوک را حفظ می‌کنیم
        if ($fieldType === 'datepicker' || $fieldType === 'timepicker') {
            $datePicker = new \Bot\DatePicker();
            $pickerData = ($fieldType === 'datepicker')
                ? $datePicker->generate(null, null, null, $fieldConfig['prefix'])
                : $datePicker->generateTimePicker(12, 0, $fieldConfig['prefix']);
            $replyMarkup = json_decode($pickerData['reply_markup'], true); // تبدیل به آرایه
            $pickerKeyboard = $replyMarkup['inline_keyboard'] ?? [];

            $combinedKeyboard = array_merge($pickerKeyboard, $keyboard);
            // اگر فقط خروجی JSON می‌خواهید
            error_log(json_encode($combinedKeyboard));

// یا برای خروجی خواناتر (از

            $this->bot->sendRequest('editMessageText', [
                'chat_id' => $chatId,
                'message_id' => $messageId,
                'text' => $questionText,
                'parse_mode' => 'HTML',
                'reply_markup' => $pickerData['reply_markup']
            ]);
            if ($callbackQueryId) {
                $this->bot->sendRequest('answerCallbackQuery', ['callback_query_id' => $callbackQueryId]);
            }
            return;
        }

        // تمام انواع دیگر کیبورد (از جمله location) از این منطق پیروی می‌کنند


        $params = [
            'chat_id' => $chatId,
            'text' => $questionText,
            'parse_mode' => 'HTML',
            'reply_markup' => json_encode(['inline_keyboard' => $keyboard]),
        ];

        $response = null;
        if ($messageId) {
            $response = $this->bot->sendRequest('editMessageText', array_merge($params, ['message_id' => $messageId]));
        } else {
            $response = $this->bot->sendRequest('sendMessage', $params);
        }

        if ($response && isset($response['result']['message_id']) && !$messageId) {
            $state['form_message_id'] = $response['result']['message_id'];
            $this->stateManager->saveState($chatId, $state);
        } elseif (!$response) {
            error_log("[Form Message Error] Failed to send or edit form question. chat_id={$chatId}, step={$stepKey}");
        }

        if ($callbackQueryId) {
            $this->bot->sendRequest('answerCallbackQuery', ['callback_query_id' => $callbackQueryId]);
        }
    }

    private function buildQuestionText(string $formKey, string $currentStepKey, array $data): string
    {
        $summary = "<b>خلاصه اطلاعات ثبت شده:</b>\n";
        $hasData = false;
        $formFields = $this->forms[$formKey]['fields'];

        foreach ($formFields as $key => $fieldConfig) {
            if ($key === $currentStepKey) {
                break;
            }

            // فقط فیلدهایی را در خلاصه نمایش می‌دهیم که مقداری برایشان ثبت شده باشد
            if (isset($data[$key]) && !empty($data[$key])) {
                $hasData = true;
                $label = $fieldConfig['label'];
                $value = $data[$key];
                $displayValue = '';

                // بر اساس کلید هر فیلد، مقدار نمایشی مناسب را تولید می‌کنیم
                switch ($key) {
                    case 'start_date':
                    case 'end_date':
                        $displayValue = $this->bot->gregorianToJalali($value);
                        break;

                    case 'start_time':
                    case 'end_time':
                        $displayValue = htmlspecialchars((string)$value);
                        break;

                    case 'transport_options':
                    case 'services_options':
                        if (is_array($value)) {
                            $allOptions = $fieldConfig['options'];
                            $selectedLabels = array_map(fn($k) => $allOptions[$k] ?? $k, $value);
                            $displayValue = implode('، ', $selectedLabels);
                        }
                        break;

                    case 'location': // ✅ مدیریت اختصاصی برای فیلد لوکیشن
                        // if (is_array($value) && isset($value['latitude'], $value['longitude'])) {
                        //     $lat = $value['latitude'];
                        //     $lon = $value['longitude'];
                        //     // ساخت لینک استاندارد و قابل کلیک برای گوگل مپ
                        //     $displayValue = "<a href='https://www.google.com/maps/search/?api=1&query={$lat},{$lon}'>مشاهده روی نقشه</a>";
                        // } else {
                        //     $displayValue = '✅ (ثبت شد)';
                        // }
                        $displayValue = '✅ (ثبت شد)';
                        break;

                    case 'pricing':
                        if (is_array($value)) {
                            $priceStrings = [];
                            foreach ($value as $priceInfo) {
                                if (is_array($priceInfo) && isset($priceInfo['label'], $priceInfo['amount'])) {
                                    $priceStrings[] = htmlspecialchars($priceInfo['label']) . ": " . number_format($priceInfo['amount']) . " تومان";
                                }
                            }
                            $displayValue = implode("\n- ", $priceStrings);
                            if ($displayValue) {
                                $displayValue = "\n- " . $displayValue;
                            }
                        }
                        break;

                    default:
                        // این بلوک پیش‌فرض از خطا برای سایر فیلدهایی که ممکن است آرایه باشند جلوگیری می‌کند
                        if (is_array($value)) {
                            $displayValue = '✅ (اطلاعات ثبت شد)';
                        } else {
                            $displayValue = htmlspecialchars((string)$value);
                        }
                        break;
                }

                $summary .= "<b>- {$label}:</b> " . $displayValue . "\n";
            }
        }

        if (!$hasData) {
            $summary = '';
        }

        $prompt = $formFields[$currentStepKey]['prompt'];
        return $summary . "\n" . $prompt;
    }
    /**
     * بر اساس نوع فیلد مرحله فعلی، کیبورد مناسب را تولید می‌کند.
     *
     * @param string $formKey کلید فرم فعلی
     * @param string $stepKey کلید مرحله فعلی
     * @param array $data داده‌های جمع‌آوری شده تا کنون
     * @param string $chatId شناسه چت
     * @return array آرایه‌ای از دکمه‌ها برای نمایش در کیبورد
     */
    public function buildKeyboard(string $formKey, string $stepKey, array $data, string $chatId): array
    {
        $fieldConfig = $this->forms[$formKey]['fields'][$stepKey];
        $keyboard = [];
        $fieldType = $fieldConfig['type'] ?? 'text';

        // استفاده از ساختار switch برای خوانایی و مدیریت بهتر انواع فیلدها
        switch ($fieldType) {
            case 'location':
                // برای نوع location، فقط به دکمه‌های ناوبری نیاز داریم که در انتهای تابع اضافه می‌شوند.
                // بنابراین در اینجا کار خاصی انجام نمی‌دهیم.
                break;

            case 'multi_select':
                $selectedOptions = $data[$stepKey] ?? [];
                $optionButtons = [];

                foreach ($fieldConfig['options'] as $optionKey => $label) {
                    $text = in_array($optionKey, $selectedOptions) ? "✅ " . $label : "🔲 " . $label;
                    $optionButtons[] = ["text" => $text, "callback_data" => "form_toggle_option_" . $optionKey];
                }

                if (!empty($optionButtons)) {
                    $keyboard = array_chunk($optionButtons, 2);
                }

                $keyboard[] = [["text" => "✅ تأیید و ادامه", "callback_data" => "form_action_proceed"]];
                break;

            case 'buttons':
                if (!empty($fieldConfig['options'])) {
                    $keyboard = array_merge($keyboard, $fieldConfig['options']);
                }
                break;

            case 'dynamic_buttons':
                if (!empty($fieldConfig['source'])) {
                    $sourceName = $fieldConfig['source'];

                    if (!isset(self::$fileCache[$sourceName])) {
                        $sourceFile = __DIR__ . '/data/' . $sourceName;
                        self::$fileCache[$sourceName] = file_exists($sourceFile)
                            ? json_decode(file_get_contents($sourceFile), true)
                            : [];
                    }
                    $optionsData = self::$fileCache[$sourceName];

                    $filterKey = $fieldConfig['source_key'] ?? $fieldConfig['source_filter_by'] ?? null;
                    if ($filterKey && isset($data[$filterKey])) {
                        $filterValue = $data[$filterKey];
                        $optionsData = $optionsData[$filterValue]['cities'] ?? ($optionsData[$filterValue] ?? []);
                    }

                    $itemsPerPage = $fieldConfig['items_per_page'] ?? 10;
                    $currentPage = $this->stateManager->getStepPage($chatId, $stepKey);
                    $totalItems = count($optionsData);
                    $totalPages = ceil($totalItems / $itemsPerPage);
                    $offset = ($currentPage - 1) * $itemsPerPage;
                    $paginatedOptions = array_slice($optionsData, $offset, $itemsPerPage, true);

                    $tempRow = [];
                    foreach ($paginatedOptions as $key => $option) {
                        $text = is_array($option) ? ($option['name'] ?? $key) : $option;
                        $callback = is_array($option) ? ($option['name'] ?? $key) : $option;
                        $tempRow[] = ['text' => $text, 'callback_data' => $callback];

                        if (count($tempRow) >= 2) {
                            $keyboard[] = $tempRow;
                            $tempRow = [];
                        }
                    }
                    if (!empty($tempRow)) {
                        $keyboard[] = $tempRow;
                    }

                    $paginationRow = [];
                    if ($currentPage > 1) {
                        $paginationRow[] = ['text' => '⬅️ قبلی', 'callback_data' => 'form_page_prev'];
                    }
                    if ($currentPage < $totalPages) {
                        $paginationRow[] = ['text' => 'بعدی ➡️', 'callback_data' => 'form_page_next'];
                    }
                    if (!empty($paginationRow)) {
                        $keyboard[] = $paginationRow;
                    }
                }
                break;
        }

        $navigationRow = [];
        $currentStepIndex = array_search($stepKey, array_keys($this->forms[$formKey]['fields']));

        if ($currentStepIndex > 0) {
            $navigationRow[] = ['text' => '🔙 بازگشت', 'callback_data' => 'form_action_back'];
        }

        if (isset($fieldConfig['skippable']) && $fieldConfig['skippable'] === true) {
            $navigationRow[] = ['text' => '⏭️ رد کردن', 'callback_data' => 'form_action_skip'];
        }

        $navigationRow[] = ['text' => '❌ لغو', 'callback_data' => 'form_action_cancel'];

        if (!empty($navigationRow)) {
            $keyboard[] = $navigationRow;
        }

        return $keyboard;
    }
    private function goBack(string $chatId, array &$state): void
    {
        $currentStepIndex = array_search($state['current_step'], $state['steps']);

        if ($currentStepIndex > 0) {
            $previousStepKey = $state['steps'][$currentStepIndex - 1];
            $state['current_step'] = $previousStepKey;
            $this->stateManager->saveStepPage($chatId, $previousStepKey, 1);
            $this->stateManager->saveState($chatId, $state);
            $this->askQuestion($chatId);
        }
    }

    private function handlePageChange(string $chatId, string $input, array &$state): void
    {
        $parts = explode('_', $input);
        $direction = end($parts);
        $stepKey = $state['current_step'];

        $currentPage = $this->stateManager->getStepPage($chatId, $stepKey);
        $newPage = ($direction === 'next') ? $currentPage + 1 : max(1, $currentPage - 1);

        $this->stateManager->saveStepPage($chatId, $stepKey, $newPage);

        $updatedState = $this->stateManager->getState($chatId);
        $this->askQuestion($chatId, $updatedState);
    }

    private function validateInput(string $chatId, &$input, string $fieldKey, array $fieldConfig, array $stateData): mixed
    {
        $rules = $fieldConfig['validation'] ?? '';

        if (($fieldKey === 'min_salary' || $fieldKey === 'max_salary') && $input === "توافقی") {
            $input = null;
        }

        if ($fieldKey === 'verify_code') {
            $storedCode = $this->stateManager->getVerificationCode($chatId);
            if ($storedCode !== $input) {
                return 'کد وارد شده صحیح نمی‌باشد.';
            }
            $this->stateManager->clearVerificationCode($chatId);
            $rules = str_replace('matches_code', '', $rules);
        }

        return $this->validate($input, $rules, $stateData, null, $chatId);
    }

    private function validate($input, string $rules, array $allData, ?string $callbackQueryId = null, ?string $chatId = null): mixed
    {
        $rules = explode('|', $rules);

        if (in_array('nullable', $rules) && (is_null($input) || $input === '')) {
            return true;
        }

        foreach ($rules as $rule) {
            $rule = trim($rule);
            $errorMessage = null;
            if ($rule === 'nullable' || (is_null($input) || $input === '')) {
                continue;
            }

            if ($rule === 'required' && (is_null($input) || (is_string($input) && trim($input) === '') || (is_array($input) && empty($input)))) {
                $errorMessage = 'این فیلد اجباری است.';
            }

            if ($rule === 'numeric' && !is_numeric($input)) {
                $errorMessage = 'ورودی باید یک عدد باشد.';
            }
            if ($rule === 'phone_number' && !preg_match('/^(09\d{9})$/', $input)) {
                $errorMessage = 'فرمت شماره تلفن صحیح نیست. (مثال: 09123456789)';
            }

            if (str_starts_with($rule, 'gte_time:')) {
                if (isset($allData['start_date'], $allData['end_date']) && $allData['start_date'] === $allData['end_date']) {
                    $startTime = $allData['start_time'] ?? '00:00';
                    $endTime = $input;
                    if (strtotime($endTime) <= strtotime($startTime)) {
                        $errorMessage = 'در تاریخ یکسان، ساعت پایان باید بعد از ساعت شروع باشد.';
                    }
                }
            }

            if (str_starts_with($rule, 'min:')) {
                $min = (int)str_replace('min:', '', $rule);
                if (mb_strlen((string)$input) < $min) $errorMessage = "ورودی باید حداقل {$min} کاراکتر باشد.";
            }
            if (str_starts_with($rule, 'max:')) {
                $max = (int)str_replace('max:', '', $rule);
                if (mb_strlen((string)$input) > $max) $errorMessage = "ورودی باید حداکثر {$max} کاراکتر باشد.";
            }
            if (str_starts_with($rule, 'gte_date:')) {
                $compareField = str_replace('gte_date:', '', $rule);
                if (isset($allData[$compareField])) {
                    $startDate = $allData[$compareField];
                    $endDate = $input;
                    if (strtotime($endDate) < strtotime($startDate)) {
                        $errorMessage = 'تاریخ پایان نمی‌تواند قبل از تاریخ شروع باشد.';
                    }
                }
            }
            if (str_starts_with($rule, 'gte:')) {
                $compareField = str_replace('gte:', '', $rule);
                if (isset($allData[$compareField]) && is_numeric($input) && is_numeric($allData[$compareField]) && (int)$input < (int)$allData[$compareField]) {
                    $errorMessage = 'مقدار حداکثر حقوق نمی‌تواند کمتر از حداقل حقوق باشد.';
                }
            }
            if (str_starts_with($rule, 'min_array:')) {
                $min = (int)str_replace('min_array:', '', $rule);
                if (!is_array($input) || count($input) < $min) {
                    $errorMessage = "باید حداقل {$min} گزینه انتخاب شود.";
                }
            }

            if ($errorMessage) {
                if ($chatId !== null) {
                    $this->sendUserFriendlyError($chatId, $errorMessage, $callbackQueryId);
                }
                return false;
            }
        }
        return true;
    }

    private function sendUserFriendlyError(string $chatId, string $errorMessage, ?string $callbackQueryId = null): void
    {
        if ($callbackQueryId) {
            $this->bot->sendRequest("answerCallbackQuery", [
                'callback_query_id' => $callbackQueryId,
                'text' => '❌ ' . $errorMessage,
                'show_alert' => true
            ]);
        } else {
            $res = $this->bot->sendRequest("sendMessage", [
                'chat_id' => $chatId,
                'text' => '❌ ' . $errorMessage,
            ]);

            sleep(4);
            $this->bot->sendRequest("deleteMessage", [
                "chat_id" => $chatId,
                "message_id" => $res['result']['message_id']
            ]);
        }
    }

    private function handlePhoneVerification(string $chatId, string $phoneNumber): void
    {
        $verificationCode = (string)rand(10000, 99999);
        $this->stateManager->saveVerificationCode($chatId, $verificationCode);
        $this->bot->sendRequest("sendMessage", [
            'chat_id' => $chatId,
            'text' => "کد تایید شما : " . $verificationCode
        ]);
    }

    private function completeForm(string $chatId, array $state): void
    {
        $formKey = $state['form_key'];
        $formConfig = $this->forms[$formKey];

        if (isset($state['temp_attachments'])) {
            $state['data']['attachments'] = $state['temp_attachments'];
            unset($state['temp_attachments']);
        }

        $data = $state['data'];
        if (isset($state['form_message_id'])) {
            $data['form_message_id'] = $state['form_message_id'];
        }
        $result = null;

        if (isset($formConfig['on_complete']) && is_callable($formConfig['on_complete'])) {
            $result = call_user_func($formConfig['on_complete'], $data, $chatId);
        }

        $messageId = $state['form_message_id'] ?? null;
        if (isset($formConfig['on_complete_prompt'])) {
            $promptConfig = $formConfig['on_complete_prompt'];
            $text = $promptConfig['text'];

            if (isset($result['ad_id'])) $text = str_replace('{ad_id}', $result['ad_id'], $text);
            if (isset($result['fee'])) $text = str_replace('{fee}', number_format($result['fee']), $text);

            $keyboard = $promptConfig['keyboard'] ?? [];
            if ($result && !empty($keyboard)) {
                $keyboardString = json_encode($keyboard);
                if (isset($result['payment_url'])) $keyboardString = str_replace('{payment_url}', $result['payment_url'], $keyboardString);
                $keyboard = json_decode($keyboardString, true);
            }

            $method = $messageId ? 'editMessageText' : 'sendMessage';
            $params = [
                'chat_id' => $chatId,
                'text' => $text,
                'parse_mode' => 'HTML',
                'reply_markup' => !empty($keyboard) ? json_encode(['inline_keyboard' => $keyboard]) : json_encode([]),
            ];
            if ($messageId) $params['message_id'] = $messageId;

            $this->bot->sendRequest($method, $params);
        }

        $this->stateManager->clearState($chatId);
    }

    // in file: FormManager.php

    private function cancelForm(string $chatId, array $state): void
    {
        $formKey = $state['form_key'];
        $message = $this->forms[$formKey]['on_cancel'] ?? 'عملیات لغو شد.';
        $messageId = $state['form_message_id'] ?? null;
        $mainMenuKeyboard = $this->bot->getMainKeyboard();


        if ($messageId) {
            $this->bot->sendRequest('editMessageText', [
                'chat_id' => $chatId,
                'message_id' => $messageId,
                'text' => $message,
                'reply_markup' => $mainMenuKeyboard
            ]);
        } else {
            $this->bot->sendRequest('sendMessage', [
                'chat_id' => $chatId,
                'text' => $message,
                'reply_markup' => $mainMenuKeyboard
            ]);
        }

        $this->stateManager->clearState($chatId);
    }

    public function proceedToNextStep(string $chatId): void
    {
        $state = $this->stateManager->getState($chatId);
        if (!$state) return;

        $currentStepIndex = array_search($state['current_step'], $state['steps']);
        $nextStepIndex = $currentStepIndex + 1;

        while ($nextStepIndex < count($state['steps'])) {
            $nextStepKey = $state['steps'][$nextStepIndex];
            $nextFieldConfig = $this->forms[$state['form_key']]['fields'][$nextStepKey];
            $fieldType = $nextFieldConfig['type'] ?? 'text';

            $shouldSkip = false;
            if ($fieldType === 'conditional_text') {
                $conditionField = $nextFieldConfig['condition_field'];
                $conditionValue = $nextFieldConfig['condition_value'];
                if (!in_array($conditionValue, $state['data'][$conditionField] ?? [])) {
                    $shouldSkip = true;
                }
            }
            if ($fieldType === 'conditional_pricing') {
                if (empty($state['data'][$nextFieldConfig['based_on']] ?? [])) {
                    $shouldSkip = true;
                }
            }
            if ($shouldSkip) {
                $state['data'][$nextStepKey] = null;
                $this->stateManager->saveState($chatId, $state);
                $nextStepIndex++;
                continue;
            }

            $state['current_step'] = $nextStepKey;
            $this->stateManager->saveState($chatId, $state);

            if ($fieldType === 'conditional_pricing') {
                $this->askForNextPrice($chatId);
            } else {
                $this->askQuestion($chatId);
            }
            return;
        }
        $this->completeForm($chatId, $state);
    }

    private function askForNextPrice(string $chatId, bool $isRetry = false): void
    {
        $state = $this->stateManager->getState($chatId);
        if (!$state) return;

        $optionsToPrice = $state['data']['transport_options'] ?? [];
        $pricedOptions = array_keys($state['data']['pricing'] ?? []);
        $pendingOptions = array_diff($optionsToPrice, $pricedOptions);

        if (empty($pendingOptions)) {
            unset($state['pricing_for']);
            $this->stateManager->saveState($chatId, $state);
            $this->proceedToNextStep($chatId);
            return;
        }

        if (!$isRetry) {
            $nextOptionKey = array_shift($pendingOptions);
            $state['pricing_for'] = $nextOptionKey;
            $this->stateManager->saveState($chatId, $state);
        } else {
            $nextOptionKey = $state['pricing_for'];
        }

        $allOptions = $this->forms[$state['form_key']]['fields']['transport_options']['options'];
        $optionLabel = $allOptions[$nextOptionKey] ?? $nextOptionKey;
        $summary = $this->buildQuestionText($state['form_key'], 'pricing', $state['data']);

        $keyboard = [['text' => '🔙 بازگشت', 'callback_data' => 'form_action_back'], ['text' => '❌ لغو', 'callback_data' => 'form_action_cancel']];

        $this->bot->sendRequest("editMessageText", [
            'chat_id' => $chatId,
            'message_id' => $state['form_message_id'],
            'text' => $summary . " هزینه تور برای <b>\"" . $optionLabel . "\"</b> :",
            'parse_mode' => 'HTML',
            'reply_markup' => json_encode(['inline_keyboard' => [$keyboard]])
        ]);
    }
}

class FormProcessor {}

class TourFormProcessor
{

//    public static function saveTourAndPost(array $data, string $chatId): void
//    {
//
//        $form_message_id = $data['form_message_id'];
//        unset($data['form_message_id']);
//
//        $db = new Database();
//        $bot = new BotHandler($chatId, null, null, null);
//        $tourId = $db->insertCompleteTour($chatId, $data);
//        if (!$tourId) {
//            $bot->sendRequest('sendMessage', [
//                'chat_id' => $chatId,
//                'text'    => '❌ خطایی در ذخیره‌سازی تور در دیتابیس رخ داد. لطفاً با پشتیبانی تماس بگیرید.'
//            ]);
//            return;
//        }
//        error_log('data: ' . print_r($data, true));
//
//        if (!empty($form_message_id)) {
//            $bot->sendRequest('deleteMessage', [
//                'chat_id'    => $chatId,
//                'message_id' => $form_message_id
//            ]);
//        }
//
//        $summaryText = self::buildFinalSummary($data, $bot);
//        $replyMarkup = json_encode([
//            'inline_keyboard' => [
//                [
//                    [
//                        'text' => '📍 ثبت‌نام در تور',
//                        'url'  => $bot->botLink . "register_{$tourId}"
//                    ]
//                ]
//            ]
//        ], JSON_UNESCAPED_UNICODE);
//
//
//        $sendTourMessage = function ($targetChatId) use ($bot, $data, $summaryText, $replyMarkup, $db, $tourId) {
//            if (!empty($data['banner']) && mb_strlen($summaryText, 'UTF-8') <= 1024) {
//                $response=$bot->sendRequest('sendPhoto', [
//                    'chat_id'      => $targetChatId,
//                    'photo'        => $data['banner'],
//                    'caption'      => $summaryText,
//                    'parse_mode'   => 'HTML',
//                    'reply_markup' => $replyMarkup
//                ]);
//            } else {
//               $response= $bot->sendRequest('sendMessage', [
//                    'chat_id'      => $targetChatId,
//                    'text'         => $summaryText,
//                    'parse_mode'   => 'HTML',
//                    'reply_markup' => $replyMarkup
//                ]);
//            }
//            error_log(print_r($response,true));
//            if (!empty($response['ok']) && !empty($response['result'])) {
//                $channelMessageId = $response['result']['message_id'];
//                $channelId = $response['result']['chat']['id'];
//                error_log("Updating tour {$tourId} with channel_id = {$channelId} and message_id = {$channelMessageId}");
//
//                $db->updateTourField($tourId, 'channel_id', $channelId);
//                $db->updateTourField($tourId, 'channel_message_id', $channelMessageId);
//            }
//        };
//
//        $sendTourMessage($chatId); // به خود کاربر
//
//        if ($channel = $db->getExplorerChannel($chatId)) {
//            $sendTourMessage($channel);
//        }
//    }

    public static function saveTourAndPost(array $data, string $chatId): void
    {
        $form_message_id = $data['form_message_id'];
        unset($data['form_message_id']);

        $db = new Database();
        $bot = new BotHandler($chatId, null, null, null);

        $tourId = $db->insertCompleteTour($chatId, $data);
        if (!$tourId) {
            $bot->sendRequest('sendMessage', [
                'chat_id' => $chatId,
                'text'    => '❌ خطایی در ذخیره‌سازی تور در دیتابیس رخ داد. لطفاً با پشتیبانی تماس بگیرید.'
            ]);
            return;
        }

        error_log('data: ' . print_r($data, true));

        if (!empty($form_message_id)) {
            $bot->sendRequest('deleteMessage', [
                'chat_id'    => $chatId,
                'message_id' => $form_message_id
            ]);
        }
        $summaryText = self::buildFinalSummary($data, $bot);
        // ارسال دکمه "درج در کانال و گروه"
        $bot->sendRequest('sendMessage', [
            'chat_id' => $chatId,

            'text'    => $summaryText."\n".'✅ تور با موفقیت ذخیره شد. آیا مایلید در کانال و گروه درج شود؟',
            'parse_mode'   => 'HTML',
            'reply_markup' => json_encode([
                'inline_keyboard' => [
                    [
                        ['text' => '📤 درج در کانال و گروه', 'callback_data' => "postToBoth_{$tourId}"]

                    ],
                [

                    ["text" => "🔙 بازگشت به منوی اصلی", "callback_data" => "go_to_menu"]
                ]
                ]
            ], JSON_UNESCAPED_UNICODE)
        ]);
    }


    private static function buildFinalSummary(array $data, BotHandler $bot): string
    {
        $summary = "🏕️ <b>~ " . htmlspecialchars($data['title'] ?? '') . " ~</b>\n\n";

        if (!empty($data['description'])) {
            $summary .= "📝 " . htmlspecialchars($data['description']) . "\n\n";
        }

        if (!empty($data['difficulty'])) {
            $difficultyLabels = [
                '1' => 'آسان (۱ از ۵)',
                '2' => 'معمولی (۲ از ۵)',
                '3' => 'متوسط (۳ از ۵)',
                '4' => 'چالش‌برانگیز (۴ از ۵)',
                '5' => 'سخت (۵ از ۵)'
            ];
            $label = $difficultyLabels[$data['difficulty']] ?? $data['difficulty'];
            $summary .= "🧗‍♂️ <b>سطح برنامه:</b> {$label}\n";
        }
        if (!empty($data['origin_address'])) {
            $summary .= "🚩 <b>مبدا حرکت:</b> " . htmlspecialchars($data['origin_address']) . "\n";
        }

        if (!empty($data['region'])) {
            $summary .= "📍 <b>منطقه:</b> " . htmlspecialchars($data['region']) . "\n";
        }

        if (!empty($data['location']['latitude']) && !empty($data['location']['longitude'])) {
            $lat = $data['location']['latitude'];
            $lon = $data['location']['longitude'];
            $summary .= "🗺️ <b> منطقه تور:</b> <a href='https://www.google.com/maps/search/?api=1&query={$lat},{$lon}'>مشاهده روی نقشه</a>\n";
        }

        // زمان‌بندی برنامه
        if (!empty($data['start_date']) && !empty($data['end_date'])) {
            $startDate = $bot->gregorianToJalali($data['start_date']);
            $endDate = $bot->gregorianToJalali($data['end_date']);
            $startTime = $data['start_time'] ?? 'نامشخص';
            $endTime = $data['end_time'] ?? 'نامشخص';

            if ($data['start_date'] === $data['end_date']) {
                $summary .= "\n🗓️ <b>تاریخ:</b> {$startDate}\n";
                $summary .= "⏰ <b>زمان:</b> از {$startTime} تا {$endTime}\n";
            } else {
                $summary .= "\n🗓️ <b>حرکت:</b> {$startDate} ساعت {$startTime}\n";
                $summary .= "🗓️ <b>بازگشت:</b> {$endDate} ساعت {$endTime}\n";
            }
        }

        // هزینه‌ها
        if (!empty($data['pricing']) && is_array($data['pricing'])) {
            $summary .= "\n💰 <b>هزینه‌ تور:</b>\n";
            foreach ($data['pricing'] as $priceInfo) {
                if (is_array($priceInfo) && $priceInfo['amount']>0) {

                    $summary .= "• " . htmlspecialchars($priceInfo['label']) . ": <b>" . number_format($priceInfo['amount']) . "</b> تومان\n";
                }
                else if($priceInfo['amount']==0){
                    $summary .= "• " . htmlspecialchars($priceInfo['label']) . ": <b>رایگان</b> \n";

                }
            }
        }

        // خدمات
        if (!empty($data['services_options']) && is_array($data['services_options'])) {
            $servicesMap = [
                'insurance' => '🛡️ بیمه',
                'accommodation' => '🏡 اسکان',
                'meals' => '🍱 وعده غذایی'
            ];

            $summary .= "\n🛎️ <b>خدمات:</b>\n";
            foreach ($data['services_options'] as $service) {
                $summary .= "• " . ($servicesMap[$service] ?? htmlspecialchars($service)) . "\n";
            }

            if (in_array('meals', $data['services_options']) && !empty($data['meal_details'])) {
                $summary .= "  ⤷ <i>جزئیات: " . htmlspecialchars($data['meal_details']) . "</i>\n";
            }
        }

        if (!empty($data['required_items'])) {
            $summary .= "\n🎒 <b>لوازم مورد نیاز:</b>\n" . htmlspecialchars($data['required_items']) . "\n";
        }

        if (!empty($data['capacity'])) {
            $summary .= "\n👥 <b>ظرفیت:</b> " . htmlspecialchars($data['capacity']) . " نفر\n";
        }

        if (!empty($data['notes'])) {
            $summary .= "\n⚠️ <b>نکات مهم:</b>\n" . htmlspecialchars($data['notes']) . "\n";
        }

        return trim($summary);
    }


}
