<?php

/**
 * ScheduleConditions Trait
 *
 * Universal scheduling restrictions for PrestaShop admin controllers.
 * Features:
 * - Datetime range: Specific period with start/end datetime
 * - Weekly schedule: Per-day time ranges with visual timeline sliders
 * - Public holiday exclusions (optional, requires HolidayProviderInterface)
 *
 * Usage:
 * 1. Add `use ScheduleConditions;` to your admin controller
 * 2. Call `$this->initScheduleConditions()` in setMedia() after parent::setMedia()
 * 3. Use `$this->renderScheduleConditionsHtml()` to render the form section
 * 4. Use `$this->getScheduleConditionsJsConfig()` for JS configuration
 * 5. Use `$this->evaluateScheduleConditions()` to check if current time matches
 *
 * For public holiday exclusions, override getScheduleHolidayProvider() method
 * to return a class name implementing HolidayProviderInterface.
 *
 * Asset paths can be configured by overriding getScheduleConditionsAssetPath()
 *
 * @author    mypresta.rocks <info@mypresta.rocks>
 * @copyright Copyright (c) mypresta.rocks
 * @license   MIT
 */

namespace MyPrestaRocks\EntitySelector;

use Context;
use Tools;
use Country;

trait ScheduleConditions
{
    /**
     * @var bool Whether schedule assets have been loaded
     */
    protected $scheduleConditionsAssetsLoaded = false;

    /**
     * @var array Default configuration for schedule conditions
     */
    protected $scheduleConditionsDefaults = [
        'id' => 'schedule-conditions',
        'name_prefix' => 'schedule_',
        'show_datetime_range' => true,
        'show_weekly_schedule' => true,
        'show_holiday_exclusions' => true,
        'title' => 'Schedule',
        'subtitle' => 'Define when this should be active',
    ];

    /**
     * Get base path for schedule conditions assets
     * Override this method to customize asset location
     *
     * @return string Path ending with /
     */
    protected function getScheduleConditionsAssetPath()
    {
        return $this->module->getPathUri() . 'views/';
    }

    /**
     * Get holiday provider class name
     * Override this method to enable public holiday exclusions
     *
     * @return string|null Class name implementing HolidayProviderInterface, or null if not available
     */
    protected function getScheduleHolidayProvider()
    {
        return null;
    }

    /**
     * Get the admin link for managing holidays
     * Override this method to customize the holiday management link
     *
     * @return string|null Admin URL or null if not available
     */
    protected function getScheduleHolidayAdminLink()
    {
        return null;
    }

    /**
     * Translate a string for ScheduleConditions
     * Override this method to customize translation handling
     *
     * @param string $string String to translate
     * @return string Translated string
     */
    protected function transScheduleConditions($string)
    {
        return $this->module->l($string, 'ScheduleConditions');
    }

    /**
     * Days of the week definitions (starting Monday for display)
     */
    protected function getScheduleDaysOfWeek()
    {
        return [
            1 => ['key' => 'monday', 'label' => $this->transScheduleConditions('Monday'), 'short' => $this->transScheduleConditions('Mon')],
            2 => ['key' => 'tuesday', 'label' => $this->transScheduleConditions('Tuesday'), 'short' => $this->transScheduleConditions('Tue')],
            3 => ['key' => 'wednesday', 'label' => $this->transScheduleConditions('Wednesday'), 'short' => $this->transScheduleConditions('Wed')],
            4 => ['key' => 'thursday', 'label' => $this->transScheduleConditions('Thursday'), 'short' => $this->transScheduleConditions('Thu')],
            5 => ['key' => 'friday', 'label' => $this->transScheduleConditions('Friday'), 'short' => $this->transScheduleConditions('Fri')],
            6 => ['key' => 'saturday', 'label' => $this->transScheduleConditions('Saturday'), 'short' => $this->transScheduleConditions('Sat')],
            0 => ['key' => 'sunday', 'label' => $this->transScheduleConditions('Sunday'), 'short' => $this->transScheduleConditions('Sun')],
        ];
    }

    /**
     * Initialize schedule conditions assets
     */
    protected function initScheduleConditions()
    {
        if ($this->scheduleConditionsAssetsLoaded) {
            return;
        }

        $assetPath = $this->getScheduleConditionsAssetPath();

        // Load combined Tailwind CSS (includes target-conditions, modal, condition-traits, list-preview)
        $this->addCSS($assetPath . 'css/admin/tailwind-output.css');
        $this->addJS($assetPath . 'js/admin/schedule-conditions.js');

        // Load TargetConditions JS for holiday country picker
        $this->addJS($assetPath . 'js/admin/target-conditions.js');

        $this->scheduleConditionsAssetsLoaded = true;
    }

    /**
     * Get JS configuration for schedule conditions
     */
    protected function getScheduleConditionsJsConfig($config = [])
    {
        $config = array_merge($this->scheduleConditionsDefaults, $config);

        return [
            'id' => $config['id'],
            'namePrefix' => $config['name_prefix'],
            'trans' => [
                'title' => $config['title'],
                'subtitle' => $config['subtitle'],
                'datetime_range' => $this->transScheduleConditions('Date & Time Range'),
                'datetime_start' => $this->transScheduleConditions('Start'),
                'datetime_end' => $this->transScheduleConditions('End'),
                'weekly_schedule' => $this->transScheduleConditions('Weekly Schedule'),
                'all_day' => $this->transScheduleConditions('All day'),
                'no_restriction' => $this->transScheduleConditions('No restriction'),
                'always_active' => $this->transScheduleConditions('Always active'),
                'copy_to_all' => $this->transScheduleConditions('Copy to all days'),
                'reset' => $this->transScheduleConditions('Reset'),
            ],
            'daysOfWeek' => $this->getScheduleDaysOfWeek(),
        ];
    }

    /**
     * Render schedule conditions HTML
     *
     * @param array $config Configuration options
     * @param array $savedData Previously saved schedule data
     * @return string HTML
     */
    protected function renderScheduleConditionsHtml($config = [], $savedData = [])
    {
        $config = array_merge($this->scheduleConditionsDefaults, $config);
        $prefix = $config['name_prefix'];

        // Parse saved data
        $datetimeStart = isset($savedData['datetime_start']) ? $savedData['datetime_start'] : '';
        $datetimeEnd = isset($savedData['datetime_end']) ? $savedData['datetime_end'] : '';
        $weeklySchedule = isset($savedData['weekly_schedule']) ? $savedData['weekly_schedule'] : [];
        $excludeHolidays = isset($savedData['exclude_holidays']) ? (bool) $savedData['exclude_holidays'] : false;
        $holidayCountries = isset($savedData['holiday_countries']) ? $savedData['holiday_countries'] : [];

        // Determine if schedule is enabled
        $hasDatetimeRange = !empty($datetimeStart) || !empty($datetimeEnd);
        $hasWeeklySchedule = !empty($weeklySchedule);
        $hasHolidayExclusions = $excludeHolidays && !empty($holidayCountries);
        $scheduleEnabled = $hasDatetimeRange || $hasWeeklySchedule || $hasHolidayExclusions;

        // Format datetime for HTML5 datetime-local input
        if ($datetimeStart && $datetimeStart !== '0000-00-00 00:00:00') {
            $datetimeStart = date('Y-m-d\TH:i', strtotime($datetimeStart));
        } else {
            $datetimeStart = '';
        }
        if ($datetimeEnd && $datetimeEnd !== '0000-00-00 00:00:00') {
            $datetimeEnd = date('Y-m-d\TH:i', strtotime($datetimeEnd));
        } else {
            $datetimeEnd = '';
        }

        $collapsedClass = $scheduleEnabled ? '' : ' collapsed';
        $html = '<div class="condition-trait schedule-conditions' . $collapsedClass . '" id="' . htmlspecialchars($config['id']) . '-wrapper">';

        // Header with toggle
        $html .= '<div class="condition-trait-header">';
        $html .= '<div class="trait-header-left">';
        $html .= '<i class="icon-clock-o trait-icon"></i>';
        $html .= '<div class="trait-title-group">';
        $html .= '<span class="trait-title">' . htmlspecialchars($config['title']) . '</span>';
        $html .= '<span class="trait-subtitle">' . htmlspecialchars($config['subtitle']) . '</span>';
        $html .= '</div>';
        // Schedule summary (shows current configuration at a glance)
        $scheduleDescData = [
            'enabled' => $scheduleEnabled,
            'datetime_start' => isset($savedData['datetime_start']) ? $savedData['datetime_start'] : '',
            'datetime_end' => isset($savedData['datetime_end']) ? $savedData['datetime_end'] : '',
            'weekly_schedule' => $weeklySchedule,
            'exclude_holidays' => $excludeHolidays,
            'holiday_countries' => $holidayCountries,
        ];
        $summaryText = $this->getScheduleDescription($scheduleDescData);
        $summaryVisible = $scheduleEnabled ? '' : ' style="display:none;"';
        $html .= '<span class="trait-summary"' . $summaryVisible . '>' . htmlspecialchars($summaryText) . '</span>';
        $html .= '</div>';
        // Expand/collapse all toggle - determine initial state based on section states
        $datetimeSectionCollapsed = empty($datetimeStart) && empty($datetimeEnd);
        $weeklySectionCollapsed = empty($weeklySchedule);
        $holidaySectionCollapsed = !$excludeHolidays;
        $allSectionsCollapsed = $datetimeSectionCollapsed && $weeklySectionCollapsed && $holidaySectionCollapsed;

        $buttonState = $allSectionsCollapsed ? 'collapsed' : 'expanded';
        $buttonIcon = $allSectionsCollapsed ? 'icon-expand' : 'icon-compress';
        $buttonTitle = $allSectionsCollapsed ? $this->transScheduleConditions('Expand all sections') : $this->transScheduleConditions('Collapse all sections');

        $html .= '<div class="trait-header-right">';
        $switchId = $config['id'] . '-enabled';
        $html .= '<span class="switch prestashop-switch fixed-width-xl" onclick="event.stopPropagation();">';
        // "Always" = on (value 0, no schedule), "Scheduled" = off (value 1, schedule enabled)
        $html .= '<input type="radio" name="' . $prefix . 'enabled" id="' . $switchId . '_on" value="0"' . (!$scheduleEnabled ? ' checked' : '') . ' class="schedule-enabled-toggle">';
        $html .= '<label for="' . $switchId . '_on">' . $this->transScheduleConditions('Always') . '</label>';
        $html .= '<input type="radio" name="' . $prefix . 'enabled" id="' . $switchId . '_off" value="1"' . ($scheduleEnabled ? ' checked' : '') . ' class="schedule-enabled-toggle">';
        $html .= '<label for="' . $switchId . '_off">' . $this->transScheduleConditions('Scheduled') . '</label>';
        $html .= '<a class="slide-button btn"></a>';
        $html .= '</span>';
        // Expand/collapse all sections button (in header)
        $html .= '<div class="trait-header-actions" onclick="event.stopPropagation();">';
        $html .= '<button type="button" class="btn-toggle-groups" data-state="' . $buttonState . '" title="' . $buttonTitle . '">';
        $html .= '<i class="' . $buttonIcon . '"></i>';
        $html .= '</button>';
        $html .= '</div>';
        // Collapse chevron icon - CSS provides content and rotates when collapsed
        $html .= '<span class="collapse-icon"></span>';
        $html .= '</div>';
        $html .= '</div>';

        // Collapsible body
        $html .= '<div class="condition-trait-body"' . ($scheduleEnabled ? '' : ' style="display:none;"') . '>';

        // Datetime Range Section
        if ($config['show_datetime_range']) {
            $datetimeHasValue = !empty($datetimeStart) || !empty($datetimeEnd);
            $datetimeCollapsed = !$datetimeHasValue ? ' collapsed' : '';
            $html .= '<div class="schedule-section schedule-datetime-range collapsible-section' . $datetimeCollapsed . '">';
            $html .= '<div class="section-header" data-toggle="collapse">';
            $html .= '<span class="section-label"><i class="icon-calendar"></i> ' . $this->transScheduleConditions('Date & Time Range') . '</span>';
            $html .= '<span class="section-collapse-icon"></span>';
            $html .= '</div>';
            $html .= '<div class="section-content"' . (!$datetimeHasValue ? ' style="display:none;"' : '') . '>';
            $html .= '<div class="datetime-range-inputs">';
            $html .= '<div class="datetime-input-group">';
            $html .= '<label>' . $this->transScheduleConditions('From') . '</label>';
            $html .= '<input type="datetime-local" name="' . $prefix . 'datetime_start" class="form-control" value="' . htmlspecialchars($datetimeStart) . '">';
            $html .= '</div>';
            $html .= '<span class="range-separator">→</span>';
            $html .= '<div class="datetime-input-group">';
            $html .= '<label>' . $this->transScheduleConditions('Until') . '</label>';
            $html .= '<input type="datetime-local" name="' . $prefix . 'datetime_end" class="form-control" value="' . htmlspecialchars($datetimeEnd) . '">';
            $html .= '</div>';
            $html .= '</div>';
            $html .= '<p class="section-hint">' . $this->transScheduleConditions('Leave empty for no date/time restriction. Example: Christmas Eve 08:00 to 16:00') . '</p>';
            $html .= '</div>';
            $html .= '</div>';
        }

        // Weekly Schedule Section (visual timelines per day)
        if ($config['show_weekly_schedule']) {
            $weeklyHasCustom = !empty($weeklySchedule);
            $weeklyCollapsed = !$weeklyHasCustom ? ' collapsed' : '';
            $html .= '<div class="schedule-section schedule-weekly collapsible-section' . $weeklyCollapsed . '">';
            $html .= '<div class="section-header" data-toggle="collapse">';
            $html .= '<span class="section-label"><i class="icon-calendar-check-o"></i> ' . $this->transScheduleConditions('Weekly Schedule') . '</span>';
            $html .= '<span class="section-collapse-icon"></span>';
            $html .= '</div>';
            $html .= '<div class="section-content"' . (!$weeklyHasCustom ? ' style="display:none;"' : '') . '>';

            // Quick actions
            $html .= '<div class="weekly-quick-actions">';
            $html .= '<button type="button" class="btn btn-sm btn-copy-first-day">' . $this->transScheduleConditions('Copy Monday to all') . '</button>';
            $html .= '<button type="button" class="btn btn-sm btn-reset-schedule">' . $this->transScheduleConditions('Reset all') . '</button>';
            $html .= '</div>';

            // Hidden input for JSON data
            $html .= '<input type="hidden" name="' . $prefix . 'weekly_schedule" class="weekly-schedule-data" value="' . htmlspecialchars(json_encode($weeklySchedule)) . '">';

            // Day timelines
            $html .= '<div class="day-timelines">';

            // Time header (hours)
            $html .= '<div class="timeline-header">';
            $html .= '<div class="timeline-day-label"></div>';
            $html .= '<div class="timeline-hours">';
            for ($h = 0; $h <= 24; $h += 6) {
                $html .= '<span class="hour-mark" style="left: ' . (($h / 24) * 100) . '%">' . sprintf('%02d:00', $h % 24) . '</span>';
            }
            $html .= '</div>';
            $html .= '</div>';

            foreach ($this->getScheduleDaysOfWeek() as $dayNum => $dayDef) {
                $daySchedule = isset($weeklySchedule[$dayNum]) ? $weeklySchedule[$dayNum] : null;
                $isEnabled = $daySchedule !== null && isset($daySchedule['enabled']) ? $daySchedule['enabled'] : true;
                $startMinutes = $daySchedule !== null && isset($daySchedule['start']) ? $daySchedule['start'] : 0;
                $endMinutes = $daySchedule !== null && isset($daySchedule['end']) ? $daySchedule['end'] : 1440;

                $html .= '<div class="day-timeline" data-day="' . $dayNum . '">';
                $html .= '<div class="timeline-day-label">';
                $html .= '<label class="day-enabled-checkbox">';
                $html .= '<input type="checkbox" class="day-enabled"' . ($isEnabled ? ' checked' : '') . '>';
                $html .= '<span class="checkbox-custom"></span>';
                $html .= '<span class="day-name">' . htmlspecialchars($dayDef['label']) . '</span>';
                $html .= '</label>';
                $html .= '</div>';
                $html .= '<div class="timeline-track' . (!$isEnabled ? ' disabled' : '') . '">';
                $html .= '<div class="timeline-range" style="left: ' . (($startMinutes / 1440) * 100) . '%; width: ' . ((($endMinutes - $startMinutes) / 1440) * 100) . '%"></div>';
                $html .= '<div class="timeline-handle handle-start" style="left: ' . (($startMinutes / 1440) * 100) . '%"></div>';
                $html .= '<div class="timeline-handle handle-end" style="left: ' . (($endMinutes / 1440) * 100) . '%"></div>';
                $html .= '</div>';
                $html .= '<div class="timeline-time-inputs">';
                $html .= '<input type="text" class="time-input time-input-start" value="' . $this->formatMinutesToTime($startMinutes) . '" placeholder="00:00" maxlength="5"' . (!$isEnabled ? ' disabled' : '') . '>';
                $html .= '<span class="time-separator">-</span>';
                $html .= '<input type="text" class="time-input time-input-end" value="' . $this->formatMinutesToTime($endMinutes) . '" placeholder="24:00" maxlength="5"' . (!$isEnabled ? ' disabled' : '') . '>';
                $html .= '</div>';
                $html .= '</div>';
            }

            $html .= '</div>'; // End day-timelines
            $html .= '<p class="section-hint">' . $this->transScheduleConditions('Drag the handles or type times directly. Uncheck a day to disable it.') . '</p>';
            $html .= '</div>';
            $html .= '</div>';
        }

        // Holiday Exclusions Section
        if ($config['show_holiday_exclusions']) {
            $html .= $this->renderHolidayExclusionsSection($prefix, $excludeHolidays, $holidayCountries);
        }

        // Server time hint
        $serverTime = date('H:i');
        $serverDay = date('l');
        $html .= '<div class="schedule-server-time">';
        $html .= '<i class="icon-info-circle"></i> ';
        $html .= sprintf(
            $this->transScheduleConditions('Server time: %s, %s'),
            '<strong>' . $serverDay . '</strong>',
            '<strong>' . $serverTime . '</strong>'
        );
        $html .= '</div>';

        $html .= '</div>'; // End body
        $html .= '</div>'; // End wrapper

        return $html;
    }

    /**
     * Format minutes (0-1440) to time string (HH:MM)
     */
    protected function formatMinutesToTime($minutes)
    {
        $minutes = max(0, min(1440, (int) $minutes));
        $hours = floor($minutes / 60);
        $mins = $minutes % 60;
        return sprintf('%02d:%02d', $hours % 24, $mins);
    }

    /**
     * Parse time string to minutes
     */
    protected function parseTimeToMinutes($time)
    {
        if (preg_match('/^(\d{1,2}):(\d{2})/', $time, $matches)) {
            return ((int) $matches[1] * 60) + (int) $matches[2];
        }
        return 0;
    }

    /**
     * Parse schedule data from form submission
     *
     * @param string $prefix Form field prefix
     * @return array Parsed schedule data
     */
    protected function parseScheduleConditionsFromPost($prefix = 'schedule_')
    {
        $data = [
            'enabled' => Tools::getValue($prefix . 'enabled', '0') === '1',
            'datetime_start' => null,
            'datetime_end' => null,
            'weekly_schedule' => [],
            'exclude_holidays' => false,
            'holiday_countries' => [],
        ];

        if (!$data['enabled']) {
            return $data;
        }

        // Parse datetime range
        $datetimeStart = Tools::getValue($prefix . 'datetime_start', '');
        if ($datetimeStart && $datetimeStart !== '0000-00-00T00:00') {
            $data['datetime_start'] = date('Y-m-d H:i:s', strtotime($datetimeStart));
        }

        $datetimeEnd = Tools::getValue($prefix . 'datetime_end', '');
        if ($datetimeEnd && $datetimeEnd !== '0000-00-00T00:00') {
            $data['datetime_end'] = date('Y-m-d H:i:s', strtotime($datetimeEnd));
        }

        // Parse weekly schedule from JSON
        $weeklyJson = Tools::getValue($prefix . 'weekly_schedule', '');
        if ($weeklyJson) {
            $weeklyData = json_decode($weeklyJson, true);
            if (is_array($weeklyData)) {
                foreach ($weeklyData as $day => $schedule) {
                    $dayNum = (int) $day;
                    if ($dayNum >= 0 && $dayNum <= 6 && is_array($schedule)) {
                        $data['weekly_schedule'][$dayNum] = [
                            'enabled' => isset($schedule['enabled']) ? (bool) $schedule['enabled'] : true,
                            'start' => isset($schedule['start']) ? max(0, min(1440, (int) $schedule['start'])) : 0,
                            'end' => isset($schedule['end']) ? max(0, min(1440, (int) $schedule['end'])) : 1440,
                        ];
                    }
                }
            }
        }

        // Parse holiday exclusions (radio button: 1 = yes, 0 = no)
        $data['exclude_holidays'] = Tools::getValue($prefix . 'exclude_holidays', '0') === '1';
        $holidayCountries = Tools::getValue($prefix . 'holiday_countries', []);
        if (is_array($holidayCountries)) {
            $data['holiday_countries'] = array_map('intval', array_filter($holidayCountries));
        }

        return $data;
    }

    /**
     * Serialize schedule data to JSON for storage
     *
     * @param array $data Schedule data array
     * @return string JSON string
     */
    protected function serializeScheduleConditions($data)
    {
        return json_encode($data);
    }

    /**
     * Parse schedule data from JSON
     *
     * @param string $json JSON string
     * @return array Schedule data
     */
    protected function parseScheduleConditions($json)
    {
        if (empty($json)) {
            return [];
        }

        $data = json_decode($json, true);
        return is_array($data) ? $data : [];
    }

    /**
     * Evaluate if current time matches the schedule conditions
     *
     * @param array $scheduleData Schedule configuration
     * @param int|null $timestamp Optional timestamp to check (defaults to now)
     * @return bool True if schedule allows, false otherwise
     */
    protected function evaluateScheduleConditions($scheduleData, $timestamp = null)
    {
        // No schedule or disabled = always active
        if (empty($scheduleData) || empty($scheduleData['enabled'])) {
            return true;
        }

        if ($timestamp === null) {
            $timestamp = time();
        }

        $currentDatetime = date('Y-m-d H:i:s', $timestamp);
        $currentMinutes = ((int) date('H', $timestamp) * 60) + (int) date('i', $timestamp);
        $currentDayOfWeek = (int) date('w', $timestamp); // 0 = Sunday

        // Check datetime range
        if (!empty($scheduleData['datetime_start']) && $scheduleData['datetime_start'] !== '0000-00-00 00:00:00') {
            if ($currentDatetime < $scheduleData['datetime_start']) {
                return false;
            }
        }

        if (!empty($scheduleData['datetime_end']) && $scheduleData['datetime_end'] !== '0000-00-00 00:00:00') {
            if ($currentDatetime > $scheduleData['datetime_end']) {
                return false;
            }
        }

        // Check weekly schedule
        if (!empty($scheduleData['weekly_schedule']) && is_array($scheduleData['weekly_schedule'])) {
            $weeklySchedule = $scheduleData['weekly_schedule'];

            // Check if current day has a schedule
            if (isset($weeklySchedule[$currentDayOfWeek])) {
                $daySchedule = $weeklySchedule[$currentDayOfWeek];

                // Day is disabled
                if (isset($daySchedule['enabled']) && !$daySchedule['enabled']) {
                    return false;
                }

                // Check time range for this day
                $startMinutes = isset($daySchedule['start']) ? (int) $daySchedule['start'] : 0;
                $endMinutes = isset($daySchedule['end']) ? (int) $daySchedule['end'] : 1440;

                if ($currentMinutes < $startMinutes || $currentMinutes > $endMinutes) {
                    return false;
                }
            }
        }

        // Check holiday exclusions
        if (!empty($scheduleData['exclude_holidays']) && !empty($scheduleData['holiday_countries'])) {
            $holidayProvider = $this->getScheduleHolidayProvider();
            if ($holidayProvider !== null) {
                $currentDate = date('Y-m-d', $timestamp);
                if ($holidayProvider::isHoliday($currentDate, $scheduleData['holiday_countries'])) {
                    return false;
                }
            }
        }

        return true;
    }

    /**
     * Get human-readable description of schedule
     *
     * @param array $scheduleData Schedule configuration
     * @return string Human-readable description
     */
    protected function getScheduleDescription($scheduleData)
    {
        if (empty($scheduleData) || empty($scheduleData['enabled'])) {
            return $this->transScheduleConditions('Always active');
        }

        $parts = [];

        // Datetime range description
        if (!empty($scheduleData['datetime_start']) || !empty($scheduleData['datetime_end'])) {
            $datetimeStart = !empty($scheduleData['datetime_start']) && $scheduleData['datetime_start'] !== '0000-00-00 00:00:00'
                ? date('M j, Y H:i', strtotime($scheduleData['datetime_start']))
                : null;
            $datetimeEnd = !empty($scheduleData['datetime_end']) && $scheduleData['datetime_end'] !== '0000-00-00 00:00:00'
                ? date('M j, Y H:i', strtotime($scheduleData['datetime_end']))
                : null;

            if ($datetimeStart && $datetimeEnd) {
                $parts[] = sprintf($this->transScheduleConditions('%s to %s'), $datetimeStart, $datetimeEnd);
            } elseif ($datetimeStart) {
                $parts[] = sprintf($this->transScheduleConditions('From %s'), $datetimeStart);
            } elseif ($datetimeEnd) {
                $parts[] = sprintf($this->transScheduleConditions('Until %s'), $datetimeEnd);
            }
        }

        // Weekly schedule description
        if (!empty($scheduleData['weekly_schedule']) && is_array($scheduleData['weekly_schedule'])) {
            $weeklySchedule = $scheduleData['weekly_schedule'];
            $dayLabels = $this->getScheduleDaysOfWeek();

            $enabledDays = [];
            $hasCustomTimes = false;

            foreach ($weeklySchedule as $dayNum => $schedule) {
                if (!isset($schedule['enabled']) || $schedule['enabled']) {
                    $enabledDays[] = $dayNum;
                    $start = isset($schedule['start']) ? (int) $schedule['start'] : 0;
                    $end = isset($schedule['end']) ? (int) $schedule['end'] : 1440;
                    if ($start > 0 || $end < 1440) {
                        $hasCustomTimes = true;
                    }
                }
            }

            if (count($enabledDays) < 7) {
                // Some days disabled
                sort($enabledDays);
                $weekdays = [1, 2, 3, 4, 5];
                $weekends = [0, 6];

                if ($enabledDays == $weekdays) {
                    $parts[] = $this->transScheduleConditions('Weekdays only');
                } elseif ($enabledDays == $weekends) {
                    $parts[] = $this->transScheduleConditions('Weekends only');
                } else {
                    $dayNames = [];
                    foreach ($enabledDays as $d) {
                        if (isset($dayLabels[$d])) {
                            $dayNames[] = $dayLabels[$d]['short'];
                        }
                    }
                    if (!empty($dayNames)) {
                        $parts[] = implode(', ', $dayNames);
                    }
                }
            }

            if ($hasCustomTimes) {
                $parts[] = $this->transScheduleConditions('Custom hours');
            }
        }

        // Holiday exclusion description
        if (!empty($scheduleData['exclude_holidays']) && !empty($scheduleData['holiday_countries'])) {
            $countryCount = count($scheduleData['holiday_countries']);
            $parts[] = sprintf($this->transScheduleConditions('Excl. holidays (%d countries)'), $countryCount);
        }

        return !empty($parts) ? implode(' • ', $parts) : $this->transScheduleConditions('Always active');
    }

    /**
     * Render holiday exclusions section HTML
     * Uses the TargetConditions interface for country selection
     *
     * @param string $prefix Form field prefix
     * @param bool $excludeHolidays Whether holiday exclusions are enabled
     * @param array $holidayCountries Selected country IDs
     * @return string HTML
     */
    protected function renderHolidayExclusionsSection($prefix, $excludeHolidays, $holidayCountries)
    {
        $holidayProvider = $this->getScheduleHolidayProvider();

        // Get countries that have holidays configured
        $countriesWithHolidays = [];
        if ($holidayProvider !== null) {
            $countriesWithHolidays = $holidayProvider::getCountriesWithHolidays();
        }

        $holidayCollapsed = !$excludeHolidays ? ' collapsed' : '';
        $html = '<div class="schedule-section schedule-holidays collapsible-section' . $holidayCollapsed . '">';

        // Section header with integrated switch toggle
        $html .= '<div class="section-header" data-toggle="collapse">';
        $html .= '<span class="section-label"><i class="icon-calendar-times-o"></i> ' . $this->transScheduleConditions('Public Holiday Exclusions') . '</span>';
        $html .= '<div class="section-header-right">';
        $html .= '<div class="holiday-enable-toggle" onclick="event.stopPropagation();">';
        $switchId = $prefix . 'exclude_holidays_switch';
        $html .= '<span class="switch prestashop-switch fixed-width-lg">';
        $html .= '<input type="radio" name="' . $prefix . 'exclude_holidays" id="' . $switchId . '_on" value="1"' . ($excludeHolidays ? ' checked' : '') . ' class="holiday-exclude-toggle">';
        $html .= '<label for="' . $switchId . '_on">' . $this->transScheduleConditions('Yes') . '</label>';
        $html .= '<input type="radio" name="' . $prefix . 'exclude_holidays" id="' . $switchId . '_off" value="0"' . (!$excludeHolidays ? ' checked' : '') . ' class="holiday-exclude-toggle">';
        $html .= '<label for="' . $switchId . '_off">' . $this->transScheduleConditions('No') . '</label>';
        $html .= '<a class="slide-button btn"></a>';
        $html .= '</span>';
        $html .= '</div>';
        $html .= '<span class="section-collapse-icon"></span>';
        $html .= '</div>';
        $html .= '</div>';

        $html .= '<div class="section-content"' . (!$excludeHolidays ? ' style="display:none;"' : '') . '>';

        // Country selection wrapper (shown when enabled)
        $html .= '<div class="holiday-countries-wrapper"' . (!$excludeHolidays ? ' style="display:none;"' : '') . '>';

        // Countries with holidays badge
        if (!empty($countriesWithHolidays)) {
            $html .= '<div class="holiday-countries-available">';
            $html .= '<span class="badge badge-info">' . sprintf($this->transScheduleConditions('%d countries with holidays configured'), count($countriesWithHolidays)) . '</span>';
            $html .= '</div>';
        }

        // Build saved data structure for TargetConditions
        $savedData = [];
        if (!empty($holidayCountries)) {
            $savedData['countries'] = [
                'groups' => [
                    [
                        'include' => [
                            'method' => 'specific',
                            'values' => array_map('intval', $holidayCountries),
                        ],
                        'excludes' => [],
                    ],
                ],
            ];
        }

        // Render TargetConditions block for countries only
        $html .= $this->renderHolidayCountriesTargetBlock($prefix, $savedData);

        // Upcoming holidays preview
        if (!empty($holidayCountries) && $holidayProvider !== null) {
            $upcomingHolidays = $holidayProvider::getHolidaysInRange(
                $holidayCountries,
                date('Y-m-d'),
                date('Y-m-d', strtotime('+30 days'))
            );

            if (!empty($upcomingHolidays)) {
                $html .= '<div class="holiday-preview">';
                $html .= '<label>' . $this->transScheduleConditions('Upcoming holidays (next 30 days)') . '</label>';
                $html .= '<ul class="holiday-list">';
                foreach (array_slice($upcomingHolidays, 0, 5) as $holiday) {
                    $html .= '<li>';
                    $html .= '<span class="holiday-date">' . date('M j', strtotime($holiday['holiday_date'])) . '</span>';
                    $html .= '<span class="holiday-name">' . htmlspecialchars($holiday['display_name']) . '</span>';
                    if (isset($holiday['country_iso'])) {
                        $html .= '<span class="holiday-country">' . $holiday['country_iso'] . '</span>';
                    }
                    $html .= '</li>';
                }
                if (count($upcomingHolidays) > 5) {
                    $html .= '<li class="more-holidays">+' . (count($upcomingHolidays) - 5) . ' ' . $this->transScheduleConditions('more') . '</li>';
                }
                $html .= '</ul>';
                $html .= '</div>';
            }
        }

        // Link to holiday management (if provided)
        $holidayAdminLink = $this->getScheduleHolidayAdminLink();
        if ($holidayAdminLink !== null) {
            $html .= '<div class="holiday-manage-link">';
            $html .= '<a href="' . htmlspecialchars($holidayAdminLink) . '" target="_blank">';
            $html .= '<i class="icon-cog"></i> ' . $this->transScheduleConditions('Manage holidays');
            $html .= '</a>';
            $html .= '</div>';
        }

        $html .= '</div>'; // End holiday-countries-wrapper

        $html .= '<p class="section-hint">' . $this->transScheduleConditions('When enabled, this schedule will be inactive on selected countries\' public holidays.') . '</p>';
        $html .= '</div>';
        $html .= '</div>';

        return $html;
    }

    /**
     * Render TargetConditions block for holiday countries
     * Creates a standalone target-conditions widget for country selection
     *
     * @param string $prefix Form field prefix
     * @param array $savedData Saved target conditions data
     * @return string HTML
     */
    protected function renderHolidayCountriesTargetBlock($prefix, $savedData)
    {
        $blockType = 'countries';
        $blockData = $savedData[$blockType] ?? [];
        $groups = $blockData['groups'] ?? [];
        $hasGroups = !empty($groups);

        // Get country selection methods
        $methods = $this->getHolidayCountrySelectionMethods();

        // Build JS config for this target block
        $jsConfig = [
            'id' => 'holiday-countries-target',
            'name' => $prefix . 'holiday_countries_data',
            'namePrefix' => $prefix,
            'ajaxUrl' => $this->context->link->getAdminLink($this->controller_name),
            'mode' => 'multi',
            'emptyMeansAll' => false,
            'blocks' => [
                'countries' => [
                    'label' => $this->transScheduleConditions('Countries'),
                    'icon' => 'icon-flag',
                    'entity_label' => $this->transScheduleConditions('country'),
                    'entity_label_plural' => $this->transScheduleConditions('countries'),
                    'selection_methods' => $methods,
                    'mode' => 'multi',
                ],
            ],
            'trans' => $this->getTargetConditionsTranslations(),
        ];

        $jsConfigJson = htmlspecialchars(json_encode($jsConfig), ENT_QUOTES, 'UTF-8');

        $html = '<div class="target-conditions-trait holiday-countries-target layout-form-group"';
        $html .= ' data-entity-selector-id="holiday-countries-target"';
        $html .= ' data-mode="multi"';
        $html .= ' data-config=\'' . $jsConfigJson . '\'>';

        // Hidden input for serialized data
        $html .= '<input type="hidden" name="' . $prefix . 'holiday_countries_data" class="target-conditions-data" value="' . htmlspecialchars(json_encode($savedData)) . '">';

        // Target blocks wrapper (single block for countries)
        $html .= '<div class="target-blocks-wrapper">';
        $html .= $this->renderHolidayCountriesBlock($blockType, $methods, $groups);
        $html .= '</div>';

        $html .= '</div>';

        return $html;
    }

    /**
     * Render the countries target block
     */
    protected function renderHolidayCountriesBlock($blockType, $methods, $groups)
    {
        $hasGroups = !empty($groups);
        $emptyStateText = $this->transScheduleConditions('All countries included');

        $html = '<div class="target-block active" data-block-type="' . htmlspecialchars($blockType) . '" data-mode="multi">';
        $html .= '<div class="block-body">';
        $html .= '<div class="groups-container">';

        if ($hasGroups) {
            foreach ($groups as $groupIndex => $group) {
                $html .= $this->renderHolidayCountriesGroup($blockType, $methods, $group, $groupIndex);
            }
        } else {
            $html .= '<div class="groups-empty-state">';
            $html .= '<span class="empty-state-text">' . $emptyStateText . '</span>';
            $html .= '</div>';
        }

        $html .= '</div>'; // End groups-container

        // Add group button with tooltip
        $groupsTooltip = '<strong>' . $this->transScheduleConditions('Selection Groups') . '</strong>';
        $groupsTooltip .= '<p>' . $this->transScheduleConditions('Groups let you combine multiple selection criteria:') . '</p>';
        $groupsTooltip .= '<div class="tooltip-list">';
        $groupsTooltip .= '<div><strong>' . $this->transScheduleConditions('Include') . ':</strong> ' . $this->transScheduleConditions('Choose which items to select (by category, manufacturer, pattern, etc.)') . '</div>';
        $groupsTooltip .= '<div><strong>' . $this->transScheduleConditions('Exclude') . ':</strong> ' . $this->transScheduleConditions('Remove specific items from your selection') . '</div>';
        $groupsTooltip .= '</div>';
        $groupsTooltip .= '<p class="tooltip-logic"><strong>' . $this->transScheduleConditions('Logic:') . '</strong> ' . $this->transScheduleConditions('Multiple groups are combined with OR. Within a group: Include MINUS Exclude.') . '</p>';

        $html .= '<div class="block-footer">';
        $html .= '<button type="button" class="btn-add-group">';
        $html .= '<i class="icon-plus"></i> ' . $this->transScheduleConditions('Add selection group');
        $html .= '</button>';
        $html .= '<span class="mpr-info-wrapper" data-details="' . htmlspecialchars($groupsTooltip) . '">';
        $html .= '<i class="icon-question-sign"></i>';
        $html .= '</span>';
        $html .= '</div>';

        $html .= '</div>'; // End block-body
        $html .= '</div>'; // End target-block

        return $html;
    }

    /**
     * Render a selection group for holiday countries
     */
    protected function renderHolidayCountriesGroup($blockType, $methods, $group, $groupIndex)
    {
        $includeMethod = $group['include']['method'] ?? 'all';
        $includeValues = $group['include']['values'] ?? [];
        $excludes = $group['excludes'] ?? [];
        $groupName = $group['name'] ?? '';

        $html = '<div class="selection-group" data-group-index="' . $groupIndex . '" data-group-name="' . htmlspecialchars($groupName) . '">';

        // Group header
        $defaultGroupName = $this->transScheduleConditions('Group') . ' ' . ($groupIndex + 1);
        $html .= '<div class="group-header">';
        $html .= '<span class="group-collapse-toggle"><i class="icon-chevron-up"></i></span>';
        $html .= '<span class="group-name-wrapper">';
        $html .= '<input type="text" class="group-name-input" value="' . htmlspecialchars($groupName) . '" placeholder="' . $defaultGroupName . '" title="' . $this->transScheduleConditions('Click to name this group') . '">';
        $html .= '<span class="group-count-badge" style="display: none;"><i class="icon-spinner icon-spin"></i></span>';
        $html .= '</span>';
        $html .= '<button type="button" class="btn-remove-group" title="' . $this->transScheduleConditions('Remove group') . '">';
        $html .= '<i class="icon-trash"></i>';
        $html .= '</button>';
        $html .= '</div>';

        // Group body
        $html .= '<div class="group-body">';

        // Include section
        $html .= '<div class="group-include">';
        $html .= '<div class="section-row">';

        // Method selector - JS will create the styled dropdown trigger
        $html .= '<div class="method-selector-wrapper">';
        $html .= '<select class="include-method-select">';
        $html .= $this->renderHolidayMethodOptions($methods, $includeMethod, false);
        $html .= '</select>';
        $html .= '<span class="condition-match-count no-matches" style="display: none;"><i class="icon-eye"></i> <span class="preview-count">0</span></span>';
        $html .= '</div>';

        // Value picker
        $html .= $this->renderHolidayValuePicker('include', $methods, $includeMethod, $includeValues);

        $html .= '</div>'; // End section-row
        $html .= '</div>'; // End group-include

        // Excludes section
        $html .= '<div class="group-excludes">';
        if (!empty($excludes)) {
            foreach ($excludes as $excludeIndex => $exclude) {
                $html .= $this->renderHolidayExcludeRow($methods, $exclude, $excludeIndex);
            }
        }
        $html .= '<button type="button" class="btn-add-exclude">';
        $html .= '<i class="icon-plus"></i> ' . $this->transScheduleConditions('Add exceptions');
        $html .= '</button>';
        $html .= '</div>';

        // Group modifiers (simplified - no limit/sort for countries)
        $html .= '<div class="group-modifiers">';
        $html .= '<span class="group-preview-badge clickable" title="' . $this->transScheduleConditions('Preview results') . '">';
        $html .= '<i class="icon-eye"></i> <span class="preview-count"></span>';
        $html .= '</span>';
        $html .= '</div>';

        $html .= '</div>'; // End group-body
        $html .= '</div>'; // End selection-group

        return $html;
    }

    /**
     * Render method options for holiday country picker
     */
    protected function renderHolidayMethodOptions($methods, $selectedMethod, $excludeAll = false)
    {
        $html = '';

        // Group options by their 'group' key
        $grouped = ['_ungrouped' => []];
        foreach ($methods as $methodKey => $methodDef) {
            if ($excludeAll && $methodKey === 'all') {
                continue;
            }
            $group = $methodDef['group'] ?? '';
            if (empty($group)) {
                $grouped['_ungrouped'][] = ['key' => $methodKey, 'def' => $methodDef];
            } else {
                if (!isset($grouped[$group])) {
                    $grouped[$group] = [];
                }
                $grouped[$group][] = ['key' => $methodKey, 'def' => $methodDef];
            }
        }

        // Render ungrouped first
        foreach ($grouped['_ungrouped'] as $item) {
            $selected = ($item['key'] === $selectedMethod) ? ' selected' : '';
            $html .= '<option value="' . htmlspecialchars($item['key']) . '"';
            $html .= ' data-value-type="' . htmlspecialchars($item['def']['value_type'] ?? 'none') . '"';
            $html .= ' data-icon="' . htmlspecialchars($item['def']['icon'] ?? 'icon-asterisk') . '"';
            if (!empty($item['def']['search_entity'])) {
                $html .= ' data-search-entity="' . htmlspecialchars($item['def']['search_entity']) . '"';
            }
            if (!empty($item['def']['options'])) {
                $html .= ' data-options="' . htmlspecialchars(json_encode($item['def']['options'])) . '"';
            }
            $html .= $selected . '>' . htmlspecialchars($item['def']['label']) . '</option>';
        }

        // Render grouped with optgroups
        $groupLabels = [
            'select_by' => $this->transScheduleConditions('Select by...'),
            'filter_by' => $this->transScheduleConditions('Filter by...'),
        ];

        foreach ($grouped as $groupKey => $items) {
            if ($groupKey === '_ungrouped' || empty($items)) {
                continue;
            }

            $groupLabel = $groupLabels[$groupKey] ?? ucfirst(str_replace('_', ' ', $groupKey));
            $html .= '<optgroup label="' . htmlspecialchars($groupLabel) . '">';
            foreach ($items as $item) {
                $selected = ($item['key'] === $selectedMethod) ? ' selected' : '';
                $html .= '<option value="' . htmlspecialchars($item['key']) . '"';
                $html .= ' data-value-type="' . htmlspecialchars($item['def']['value_type'] ?? 'none') . '"';
                $html .= ' data-icon="' . htmlspecialchars($item['def']['icon'] ?? 'icon-asterisk') . '"';
                if (!empty($item['def']['search_entity'])) {
                    $html .= ' data-search-entity="' . htmlspecialchars($item['def']['search_entity']) . '"';
                }
                if (!empty($item['def']['options'])) {
                    $html .= ' data-options="' . htmlspecialchars(json_encode($item['def']['options'])) . '"';
                }
                $html .= $selected . '>' . htmlspecialchars($item['def']['label']) . '</option>';
            }
            $html .= '</optgroup>';
        }

        return $html;
    }

    /**
     * Render value picker for holiday country selection
     */
    protected function renderHolidayValuePicker($section, $methods, $selectedMethod, $values)
    {
        $methodDef = $methods[$selectedMethod] ?? [];
        $valueType = $methodDef['value_type'] ?? 'none';
        $searchEntity = $methodDef['search_entity'] ?? '';
        $pickerClass = $section . '-picker';
        $chipsClass = $section . '-chips';
        $dataClass = $section . '-values-data';

        // Don't show picker for 'none' type
        if ($valueType === 'none') {
            $html = '<div class="value-picker ' . $pickerClass . '" style="display:none;" data-search-entity="" data-value-type="none">';
            $html .= '<input type="hidden" class="' . $dataClass . '" value="[]">';
            $html .= '</div>';
            return $html;
        }

        $html = '<div class="value-picker ' . $pickerClass . '" data-search-entity="' . htmlspecialchars($searchEntity) . '" data-value-type="' . htmlspecialchars($valueType) . '">';

        switch ($valueType) {
            case 'entity_search':
                $noItemsPlaceholder = $this->transScheduleConditions('No items selected - use search below');
                $html .= '<div class="entity-chips ' . $chipsClass . '" data-placeholder="' . htmlspecialchars($noItemsPlaceholder) . '"></div>';
                $html .= '<div class="entity-search-box">';
                $html .= '<i class="icon-search entity-search-icon"></i>';
                $html .= '<input type="text" class="entity-search-input" placeholder="' . $this->transScheduleConditions('Search by name, reference, ID...') . '" autocomplete="off">';
                $html .= '<span class="search-loading" style="display:none;"><i class="icon-spinner icon-spin"></i></span>';
                $html .= '</div>';
                $html .= '<input type="hidden" class="' . $dataClass . '" value="' . htmlspecialchars(json_encode($values)) . '">';
                break;

            case 'pattern':
                $html .= '<div class="entity-chips pattern-chips" data-placeholder="' . htmlspecialchars($this->transScheduleConditions('No patterns - press Enter to add')) . '"></div>';
                $html .= '<div class="pattern-input-row">';
                $html .= '<div class="pattern-tag draft-tag" data-case-sensitive="0">';
                $html .= '<button type="button" class="btn-toggle-case" title="' . htmlspecialchars($this->transScheduleConditions('Case insensitive - click to toggle')) . '"><span class="case-icon">aa</span></button>';
                $html .= '<input type="text" class="pattern-input" value="" placeholder="' . htmlspecialchars($this->transScheduleConditions('e.g. *Europe*')) . '">';
                $html .= '<span class="pattern-match-count"></span>';
                $html .= '<button type="button" class="btn-add-pattern" title="' . htmlspecialchars($this->transScheduleConditions('Add pattern (Enter)')) . '"><i class="icon-plus"></i></button>';
                $html .= '</div>';
                $html .= '</div>';
                $html .= '<input type="hidden" class="' . $dataClass . '" value="' . htmlspecialchars(json_encode($values)) . '">';
                break;

            case 'select':
                $options = $methodDef['options'] ?? [];
                $selectedValue = is_array($values) && !empty($values[0]) ? $values[0] : (is_string($values) ? $values : '');
                $html .= '<div class="select-input-box">';
                $html .= '<select class="select-value-input">';
                foreach ($options as $optKey => $optLabel) {
                    $selected = ($selectedValue === $optKey) ? ' selected' : '';
                    $html .= '<option value="' . htmlspecialchars($optKey) . '"' . $selected . '>' . htmlspecialchars($optLabel) . '</option>';
                }
                $html .= '</select>';
                $html .= '</div>';
                $html .= '<input type="hidden" class="' . $dataClass . '" value="' . htmlspecialchars(json_encode($values)) . '">';
                break;

            default:
                $html .= '<input type="hidden" class="' . $dataClass . '" value="[]">';
                break;
        }

        $html .= '</div>';

        return $html;
    }

    /**
     * Render exclude row for holiday country selection
     */
    protected function renderHolidayExcludeRow($methods, $exclude, $excludeIndex)
    {
        $method = $exclude['method'] ?? 'specific';
        $values = $exclude['values'] ?? [];

        $html = '<div class="exclude-row" data-exclude-index="' . $excludeIndex . '">';

        // Method selector - JS will create the styled dropdown trigger
        $html .= '<div class="method-selector-wrapper">';
        $html .= '<select class="exclude-method-select">';
        $html .= $this->renderHolidayMethodOptions($methods, $method, true);
        $html .= '</select>';
        $html .= '</div>';

        // Value picker
        $html .= $this->renderHolidayValuePicker('exclude', $methods, $method, $values);

        // Remove button
        $html .= '<button type="button" class="btn-remove-exclude" title="' . $this->transScheduleConditions('Remove') . '">';
        $html .= '<i class="icon-times"></i>';
        $html .= '</button>';

        $html .= '</div>';

        return $html;
    }

    /**
     * Get selection methods for holiday country picker
     */
    protected function getHolidayCountrySelectionMethods()
    {
        return [
            'all' => [
                'label' => $this->transScheduleConditions('All countries'),
                'icon' => 'icon-asterisk',
                'value_type' => 'none',
                'group' => '',
            ],
            'specific' => [
                'label' => $this->transScheduleConditions('Specific countries'),
                'icon' => 'icon-flag',
                'value_type' => 'entity_search',
                'search_entity' => 'countries',
                'group' => 'select_by',
            ],
            'by_zone' => [
                'label' => $this->transScheduleConditions('By zone'),
                'icon' => 'icon-globe',
                'value_type' => 'entity_search',
                'search_entity' => 'zones',
                'group' => 'filter_by',
            ],
            'by_name_pattern' => [
                'label' => $this->transScheduleConditions('Name contains'),
                'icon' => 'icon-font',
                'value_type' => 'pattern',
                'group' => 'filter_by',
            ],
            'by_active_status' => [
                'label' => $this->transScheduleConditions('Status'),
                'icon' => 'icon-toggle-on',
                'value_type' => 'select',
                'options' => [
                    'active' => $this->transScheduleConditions('Active'),
                    'inactive' => $this->transScheduleConditions('Inactive'),
                ],
                'group' => 'filter_by',
            ],
        ];
    }

    /**
     * Get translations for TargetConditions JS
     */
    protected function getTargetConditionsTranslations()
    {
        return [
            'group' => $this->transScheduleConditions('Group'),
            'click_to_name' => $this->transScheduleConditions('Click to name this group'),
            'remove_group' => $this->transScheduleConditions('Remove group'),
            'no_items_selected' => $this->transScheduleConditions('No items selected - use search below'),
            'search_placeholder' => $this->transScheduleConditions('Search by name, reference, ID...'),
            'add_exceptions' => $this->transScheduleConditions('Add exceptions'),
            'preview_results' => $this->transScheduleConditions('Preview results'),
            'add_selection_group' => $this->transScheduleConditions('Add selection group'),
        ];
    }

    /**
     * Get database field definitions for schedule conditions
     * Use this when defining ObjectModel fields
     *
     * @return array Field definitions compatible with ObjectModel::$definition
     */
    protected static function getScheduleConditionsFieldDefinitions()
    {
        return [
            'schedule_enabled' => ['type' => self::TYPE_BOOL, 'validate' => 'isBool'],
            'schedule_datetime_start' => ['type' => self::TYPE_DATE, 'validate' => 'isDateOrNull'],
            'schedule_datetime_end' => ['type' => self::TYPE_DATE, 'validate' => 'isDateOrNull'],
            'schedule_weekly' => ['type' => self::TYPE_STRING, 'validate' => 'isJson', 'size' => 1024],
        ];
    }

    /**
     * Get SQL schema for schedule conditions fields
     *
     * @param string $prefix Optional column prefix
     * @return string SQL column definitions
     */
    protected static function getScheduleConditionsSqlSchema($prefix = 'schedule_')
    {
        return "
            `{$prefix}enabled` TINYINT(1) UNSIGNED NOT NULL DEFAULT 0,
            `{$prefix}datetime_start` DATETIME DEFAULT NULL,
            `{$prefix}datetime_end` DATETIME DEFAULT NULL,
            `{$prefix}weekly` TEXT DEFAULT NULL
        ";
    }
}
