<?php
/**
 * Plugin Name: APN Scheduled CTA
 * Description: Scheduled CTAs that auto-switch based on competition phase, with shortcodes for dynamic competition data
 * Version: 1.1.0
 * Author: APNetwork
 * Network: true
 */

if (!defined('ABSPATH')) {
    exit;
}

class APN_Scheduled_CTA {

    const MAIN_SITE_ID = 1;

    /** Phase slugs and labels */
    const PHASES = [
        'early_bird'        => 'Early Bird Entry',
        'regular'           => 'Regular Entry',
        'late'              => 'Late Entry',
        'upcoming'          => 'Upcoming Competition',
        'winner_anticipation' => 'Winner Anticipation',
        'winners_announced' => 'Winners Announced',
        'next_anticipation' => 'Next Competition Anticipation',
    ];

    private static $instance = null;

    /** @var array|null Cached competition data from main site */
    private $cached_competition_data = null;

    /** @var string|null Cached resolved phase */
    private $cached_phase = null;

    public static function get_instance() {
        if (null === self::$instance) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    private function __construct() {
        add_action('acf/init', [$this, 'register_cta_fields'], 20);
        add_action('init', [$this, 'register_shortcodes']);
        add_action('init', [$this, 'register_block']);
        add_action('enqueue_block_editor_assets', [$this, 'enqueue_editor_assets']);
        add_action('wp_enqueue_scripts', [$this, 'enqueue_frontend_styles']);
    }

    // =========================================================================
    //  Competition Data Helper
    // =========================================================================

    /**
     * Get competition data needed by shortcodes.
     * Returns competition_id and year_index (always row 0 = latest year).
     *
     * @return array|null ['competition_id' => int, 'year_index' => int] or null
     */
    private function get_competition_data() {
        if ($this->cached_competition_data !== null) {
            return $this->cached_competition_data ?: null;
        }

        if (!class_exists('APN_Competition_Sync')) {
            $this->cached_competition_data = false;
            return null;
        }

        $competition_id = APN_Competition_Sync::get_instance()->get_competition_for_current_site();
        if (!$competition_id) {
            $this->cached_competition_data = false;
            return null;
        }

        $this->cached_competition_data = [
            'competition_id' => $competition_id,
            'year_index' => 0, // Always use latest year (row 0)
        ];

        return $this->cached_competition_data;
    }

    // =========================================================================
    //  Phase Determination (Activation Date Based)
    // =========================================================================

    /**
     * Determine the active phase by resolving activation date shortcodes.
     *
     * For each phase tab, the user sets an "Activation Date" field (which can
     * contain shortcodes like [early_bird_deadline]). We resolve all of them,
     * discard any that are in the future, and pick the most recent past/current
     * date. That phase wins.
     *
     * @param string|null $override Phase slug to force, or null/'' for auto.
     * @return string The active phase slug.
     */
    public function determine_current_phase($override = null) {
        // If a specific phase is requested, use it
        if ($override && $override !== 'auto' && isset(self::PHASES[$override])) {
            return $override;
        }

        if ($this->cached_phase !== null) {
            return $this->cached_phase;
        }

        $today = current_time('Y-m-d');
        $best_phase = 'next_anticipation';
        $best_date = null;

        foreach (self::PHASES as $slug => $label) {
            $activation_raw = get_option("options_cta_{$slug}_activation_date", '');
            if (empty($activation_raw)) {
                continue;
            }

            // Resolve shortcodes in the activation date
            $activation_resolved = do_shortcode($activation_raw);

            // Try to parse as a date
            $timestamp = strtotime($activation_resolved);
            if ($timestamp === false) {
                continue; // "TBD" or unparseable — skip
            }

            $activation_date = date('Y-m-d', $timestamp);

            // Only consider dates that are today or in the past
            if ($activation_date > $today) {
                continue;
            }

            // Pick the most recent activation date
            if ($best_date === null || $activation_date > $best_date) {
                $best_date = $activation_date;
                $best_phase = $slug;
            }
        }

        $this->cached_phase = $best_phase;
        return $best_phase;
    }

    // =========================================================================
    //  ACF Fields
    // =========================================================================

    public function register_cta_fields() {
        if (get_current_blog_id() === self::MAIN_SITE_ID) {
            return;
        }

        if (!function_exists('acf_add_local_field_group')) {
            return;
        }

        if (class_exists('APN_Competition_Sync')) {
            $competition_id = APN_Competition_Sync::get_instance()->get_competition_for_current_site();
            if (!$competition_id) {
                return;
            }
        }

        $date_instructions = 'Date shortcode for when this phase activates (e.g., [next_year_start], [early_bird_deadline]). Phase with most recent past/current activation date wins.';

        $fields = [];

        // Shortcode reference at top
        $fields[] = [
            'key' => 'field_apn_cta_shortcode_ref',
            'label' => 'Shortcode Reference',
            'type' => 'message',
            'message' => $this->get_shortcode_reference_html(),
            'esc_html' => 0,
        ];

        foreach (self::PHASES as $slug => $label) {
            // Tab
            $fields[] = [
                'key' => "field_apn_cta_tab_{$slug}",
                'label' => $label,
                'type' => 'tab',
            ];

            // Activation Date
            $fields[] = [
                'key' => "field_apn_cta_{$slug}_activation_date",
                'label' => 'Activation Date',
                'name' => "cta_{$slug}_activation_date",
                'type' => 'text',
                'instructions' => $date_instructions,
                'placeholder' => 'e.g., [next_year_start] or [early_bird_deadline] or January 1, 2026',
            ];

            // Primary CTA (left column)
            $fields[] = [
                'key' => "field_apn_cta_{$slug}_primary_headline",
                'label' => 'Primary CTA Headline',
                'name' => "cta_{$slug}_primary_headline",
                'type' => 'text',
                'wrapper' => ['width' => '50'],
            ];
            $fields[] = [
                'key' => "field_apn_cta_{$slug}_secondary_headline",
                'label' => 'Secondary CTA Headline',
                'name' => "cta_{$slug}_secondary_headline",
                'type' => 'text',
                'wrapper' => ['width' => '50'],
            ];
            $fields[] = [
                'key' => "field_apn_cta_{$slug}_primary_subheading",
                'label' => 'Primary CTA Subheading',
                'name' => "cta_{$slug}_primary_subheading",
                'type' => 'text',
                'instructions' => 'Shown in CTA Box style',
                'wrapper' => ['width' => '50'],
            ];
            $fields[] = [
                'key' => "field_apn_cta_{$slug}_secondary_subheading",
                'label' => 'Secondary CTA Subheading',
                'name' => "cta_{$slug}_secondary_subheading",
                'type' => 'text',
                'instructions' => 'Shown in CTA Box style',
                'wrapper' => ['width' => '50'],
            ];
            $fields[] = [
                'key' => "field_apn_cta_{$slug}_primary_link",
                'label' => 'Primary CTA Link',
                'name' => "cta_{$slug}_primary_link",
                'type' => 'text',
                'instructions' => 'URL or shortcode: [entry_link], [entry_page], [entry_pdf]',
                'wrapper' => ['width' => '50'],
            ];
            $fields[] = [
                'key' => "field_apn_cta_{$slug}_secondary_link",
                'label' => 'Secondary CTA Link',
                'name' => "cta_{$slug}_secondary_link",
                'type' => 'text',
                'instructions' => 'URL or shortcode: [entry_link], [entry_page], [entry_pdf]',
                'wrapper' => ['width' => '50'],
            ];
        }

        acf_add_local_field_group([
            'key' => 'group_apn_scheduled_ctas',
            'title' => 'Scheduled CTAs',
            'fields' => $fields,
            'location' => [
                [
                    [
                        'param' => 'options_page',
                        'operator' => '==',
                        'value' => 'apn-competition-settings',
                    ],
                ],
            ],
            'menu_order' => 20,
            'position' => 'normal',
            'style' => 'default',
            'label_placement' => 'top',
            'instruction_placement' => 'label',
        ]);
    }

    /**
     * HTML for the shortcode reference shown in ACF and the editor sidebar.
     */
    private function get_shortcode_reference_html() {
        return '<details style="background:#f9f9f9;border:1px solid #ddd;border-radius:4px;padding:10px 14px;margin-bottom:4px;">
<summary style="cursor:pointer;font-weight:600;color:#1e1e1e;user-select:none;">Click to expand shortcode reference</summary>
<div style="margin-top:10px;font-size:12.5px;line-height:1.7;">
<strong style="color:#1e1e1e;">Text</strong>
<table style="width:100%;border-collapse:collapse;margin:4px 0 12px;">
<tr><td style="padding:2px 8px;font-family:monospace;color:#d63638;white-space:nowrap;">[competition_name]</td><td style="padding:2px 8px;">Competition name</td></tr>
<tr><td style="padding:2px 8px;font-family:monospace;color:#d63638;white-space:nowrap;">[abbreviation]</td><td style="padding:2px 8px;">Short abbreviation (e.g., NYIBC)</td></tr>
<tr><td style="padding:2px 8px;font-family:monospace;color:#d63638;white-space:nowrap;">[competition_year]</td><td style="padding:2px 8px;">Latest year (e.g., 2026)</td></tr>
<tr><td style="padding:2px 8px;font-family:monospace;color:#d63638;white-space:nowrap;">[nth_annual]</td><td style="padding:2px 8px;">e.g., "15th Annual"</td></tr>
<tr><td style="padding:2px 8px;font-family:monospace;color:#d63638;white-space:nowrap;">[early_bird_price]</td><td style="padding:2px 8px;">Early bird price or "TBD"</td></tr>
<tr><td style="padding:2px 8px;font-family:monospace;color:#d63638;white-space:nowrap;">[regular_price]</td><td style="padding:2px 8px;">Regular price or "TBD"</td></tr>
<tr><td style="padding:2px 8px;font-family:monospace;color:#d63638;white-space:nowrap;">[late_price]</td><td style="padding:2px 8px;">Late price or "TBD"</td></tr>
<tr><td style="padding:2px 8px;font-family:monospace;color:#d63638;white-space:nowrap;">[comp_date_text]</td><td style="padding:2px 8px;">Competition date text or start date or "TBD"</td></tr>
<tr><td style="padding:2px 8px;font-family:monospace;color:#d63638;white-space:nowrap;">[winner_announcement_text]</td><td style="padding:2px 8px;">Announcement text or "Winner Announcement: [date]"</td></tr>
<tr><td style="padding:2px 8px;font-family:monospace;color:#d63638;white-space:nowrap;">[entry_notes]</td><td style="padding:2px 8px;">Entry notes for current year</td></tr>
</table>
<strong style="color:#1e1e1e;">URLs</strong>
<table style="width:100%;border-collapse:collapse;margin:4px 0 12px;">
<tr><td style="padding:2px 8px;font-family:monospace;color:#d63638;white-space:nowrap;">[entry_page]</td><td style="padding:2px 8px;">Entry page (year override or default)</td></tr>
<tr><td style="padding:2px 8px;font-family:monospace;color:#d63638;white-space:nowrap;">[entry_link]</td><td style="padding:2px 8px;">Direct entry link (year override or default)</td></tr>
<tr><td style="padding:2px 8px;font-family:monospace;color:#d63638;white-space:nowrap;">[entry_pdf]</td><td style="padding:2px 8px;">Entry PDF link or "#"</td></tr>
</table>
<strong style="color:#1e1e1e;">Dates</strong> <em>(return formatted date or "TBD")</em>
<table style="width:100%;border-collapse:collapse;margin:4px 0 0;">
<tr><td style="padding:2px 8px;font-family:monospace;color:#d63638;white-space:nowrap;">[early_bird_deadline]</td><td style="padding:2px 8px;">Early bird deadline</td></tr>
<tr><td style="padding:2px 8px;font-family:monospace;color:#d63638;white-space:nowrap;">[regular_deadline]</td><td style="padding:2px 8px;">Regular deadline</td></tr>
<tr><td style="padding:2px 8px;font-family:monospace;color:#d63638;white-space:nowrap;">[late_deadline]</td><td style="padding:2px 8px;">Late deadline</td></tr>
<tr><td style="padding:2px 8px;font-family:monospace;color:#d63638;white-space:nowrap;">[delivery_deadline]</td><td style="padding:2px 8px;">Product delivery deadline</td></tr>
<tr><td style="padding:2px 8px;font-family:monospace;color:#d63638;white-space:nowrap;">[payment_deadline]</td><td style="padding:2px 8px;">Payment deadline</td></tr>
<tr><td style="padding:2px 8px;font-family:monospace;color:#d63638;white-space:nowrap;">[competition_start]</td><td style="padding:2px 8px;">Competition start date</td></tr>
<tr><td style="padding:2px 8px;font-family:monospace;color:#d63638;white-space:nowrap;">[competition_end]</td><td style="padding:2px 8px;">Competition end date</td></tr>
<tr><td style="padding:2px 8px;font-family:monospace;color:#d63638;white-space:nowrap;">[winner_announcement_date]</td><td style="padding:2px 8px;">Winner announcement date</td></tr>
<tr><td style="padding:2px 8px;font-family:monospace;color:#d63638;white-space:nowrap;">[next_year_start]</td><td style="padding:2px 8px;">Jan 1 of next year</td></tr>
</table>
</div>
</details>';
    }

    // =========================================================================
    //  Shortcodes
    // =========================================================================

    public function register_shortcodes() {
        $shortcodes = [
            // Return strings
            'competition_name',
            'abbreviation',
            'competition_year',
            'nth_annual',
            'early_bird_price',
            'regular_price',
            'late_price',
            'comp_date_text',
            'winner_announcement_text',
            'entry_notes',
            // Return URLs
            'entry_page',
            'entry_link',
            'entry_pdf',
            // Return dates
            'early_bird_deadline',
            'regular_deadline',
            'late_deadline',
            'delivery_deadline',
            'payment_deadline',
            'competition_start',
            'competition_end',
            'winner_announcement_date',
            'next_year_start',
        ];

        foreach ($shortcodes as $tag) {
            add_shortcode($tag, [$this, 'shortcode_handler']);
        }
    }

    /**
     * Universal shortcode handler. Resolves competition data from the latest year.
     */
    public function shortcode_handler($atts, $content, $tag) {
        if (get_current_blog_id() === self::MAIN_SITE_ID) {
            return '';
        }

        // [next_year_start] doesn't need competition data
        if ($tag === 'next_year_start') {
            $next_year = (int) current_time('Y') + 1;
            return date_i18n('F j, Y', strtotime("{$next_year}-01-01"));
        }

        $data = $this->get_competition_data();
        if (!$data) {
            return '';
        }

        $competition_id = $data['competition_id'];
        $year_index = $data['year_index'];

        switch_to_blog(self::MAIN_SITE_ID);

        $prefix = "years_{$year_index}_";
        $value = '';

        switch ($tag) {
            // --- Return Strings ---

            case 'competition_name':
                $post = get_post($competition_id);
                $value = $post ? $post->post_title : '';
                break;

            case 'abbreviation':
                $value = get_post_meta($competition_id, 'abbreviation', true) ?: '';
                break;

            case 'competition_year':
                $value = get_post_meta($competition_id, $prefix . 'year', true) ?: '';
                break;

            case 'nth_annual':
                $years_count = (int) get_post_meta($competition_id, 'years', true);
                $value = $years_count > 0 ? $this->number_to_ordinal($years_count) . ' Annual' : '';
                break;

            case 'early_bird_price':
                $raw = get_post_meta($competition_id, $prefix . 'entry_price_early', true);
                $value = $raw ? '$' . number_format((float) $raw, 0) : 'TBD';
                break;

            case 'regular_price':
                $raw = get_post_meta($competition_id, $prefix . 'entry_price_regular', true);
                $value = $raw ? '$' . number_format((float) $raw, 0) : 'TBD';
                break;

            case 'late_price':
                $raw = get_post_meta($competition_id, $prefix . 'entry_price_late', true);
                $value = $raw ? '$' . number_format((float) $raw, 0) : 'TBD';
                break;

            case 'comp_date_text':
                $text = get_post_meta($competition_id, $prefix . 'competition_date_text', true);
                if ($text) {
                    $value = $text;
                } else {
                    $raw = get_post_meta($competition_id, $prefix . 'competition_date_start', true);
                    $value = $raw ? date_i18n('F j, Y', strtotime($raw)) : 'TBD';
                }
                break;

            case 'winner_announcement_text':
                $text = get_post_meta($competition_id, $prefix . 'winner_announcement_text', true);
                if ($text) {
                    $value = $text;
                } else {
                    $raw = get_post_meta($competition_id, $prefix . 'winner_announcement_date', true);
                    $value = $raw ? 'Winner Announcement: ' . date_i18n('F j, Y', strtotime($raw)) : 'TBD';
                }
                break;

            case 'entry_notes':
                $value = get_post_meta($competition_id, $prefix . 'entry_notes', true) ?: '';
                break;

            // --- Return URLs ---

            case 'entry_page':
                $override = get_post_meta($competition_id, $prefix . 'entry_page_override', true);
                $value = $override ?: get_post_meta($competition_id, 'default_entry_page', true);
                $value = $value ?: '#';
                break;

            case 'entry_link':
                $override = get_post_meta($competition_id, $prefix . 'entry_link_override', true);
                $value = $override ?: get_post_meta($competition_id, 'default_entry_link', true);
                $value = $value ?: '#';
                break;

            case 'entry_pdf':
                $attachment_id = get_post_meta($competition_id, $prefix . 'entry_pdf', true);
                $value = $attachment_id ? wp_get_attachment_url($attachment_id) : '#';
                break;

            // --- Return Dates ---

            case 'early_bird_deadline':
                $raw = get_post_meta($competition_id, $prefix . 'entry_date_early', true);
                $value = $raw ? date_i18n('F j, Y', strtotime($raw)) : 'TBD';
                break;

            case 'regular_deadline':
                $raw = get_post_meta($competition_id, $prefix . 'entry_date_regular', true);
                $value = $raw ? date_i18n('F j, Y', strtotime($raw)) : 'TBD';
                break;

            case 'late_deadline':
                $raw = get_post_meta($competition_id, $prefix . 'entry_date_late', true);
                $value = $raw ? date_i18n('F j, Y', strtotime($raw)) : 'TBD';
                break;

            case 'delivery_deadline':
                $raw = get_post_meta($competition_id, $prefix . 'product_delivery_deadline', true);
                $value = $raw ? date_i18n('F j, Y', strtotime($raw)) : 'TBD';
                break;

            case 'payment_deadline':
                $raw = get_post_meta($competition_id, $prefix . 'payment_deadline', true);
                $value = $raw ? date_i18n('F j, Y', strtotime($raw)) : 'TBD';
                break;

            case 'competition_start':
                $raw = get_post_meta($competition_id, $prefix . 'competition_date_start', true);
                $value = $raw ? date_i18n('F j, Y', strtotime($raw)) : 'TBD';
                break;

            case 'competition_end':
                $raw = get_post_meta($competition_id, $prefix . 'competition_date_end', true);
                $value = $raw ? date_i18n('F j, Y', strtotime($raw)) : 'TBD';
                break;

            case 'winner_announcement_date':
                $raw = get_post_meta($competition_id, $prefix . 'winner_announcement_date', true);
                $value = $raw ? date_i18n('F j, Y', strtotime($raw)) : 'TBD';
                break;
        }

        restore_current_blog();

        return $value;
    }

    /**
     * Convert number to ordinal (1st, 2nd, 3rd, 11th, 21st, etc.)
     */
    private function number_to_ordinal($number) {
        $ends = ['th', 'st', 'nd', 'rd', 'th', 'th', 'th', 'th', 'th', 'th'];
        if (($number % 100) >= 11 && ($number % 100) <= 13) {
            return $number . 'th';
        }
        return $number . $ends[$number % 10];
    }

    // =========================================================================
    //  Gutenberg Block
    // =========================================================================

    public function register_block() {
        register_block_type('apn/scheduled-cta', [
            'render_callback' => [$this, 'render_block'],
            'attributes' => [
                'ctaType' => [
                    'type' => 'string',
                    'default' => 'primary',
                ],
                'ctaStyle' => [
                    'type' => 'string',
                    'default' => 'button',
                ],
                'phaseOverride' => [
                    'type' => 'string',
                    'default' => 'auto',
                ],
            ],
        ]);
    }

    public function enqueue_editor_assets() {
        wp_register_script(
            'apn-scheduled-cta-editor',
            false,
            ['wp-blocks', 'wp-element', 'wp-block-editor', 'wp-components', 'wp-server-side-render', 'wp-plugins', 'wp-edit-post'],
            '1.1.0'
        );
        wp_enqueue_script('apn-scheduled-cta-editor');
        wp_add_inline_script('apn-scheduled-cta-editor', $this->get_editor_script());

        wp_add_inline_style('wp-edit-blocks', $this->get_editor_styles() . "\n" . $this->get_frontend_styles());
    }

    public function enqueue_frontend_styles() {
        wp_register_style('apn-scheduled-cta-style', false, [], '1.1.0');
        wp_enqueue_style('apn-scheduled-cta-style');
        wp_add_inline_style('apn-scheduled-cta-style', $this->get_frontend_styles());
    }

    /**
     * Render the Scheduled CTA block.
     */
    public function render_block($attributes) {
        $cta_type = isset($attributes['ctaType']) ? $attributes['ctaType'] : 'primary';
        $cta_style = isset($attributes['ctaStyle']) ? $attributes['ctaStyle'] : 'button';
        $phase_override = isset($attributes['phaseOverride']) ? $attributes['phaseOverride'] : 'auto';

        // Determine current phase (respects override)
        $phase = $this->determine_current_phase($phase_override);
        $phase_label = isset(self::PHASES[$phase]) ? self::PHASES[$phase] : $phase;

        // Read CTA fields from child site options
        $headline   = get_option("options_cta_{$phase}_{$cta_type}_headline", '');
        $subheading = get_option("options_cta_{$phase}_{$cta_type}_subheading", '');
        $link       = get_option("options_cta_{$phase}_{$cta_type}_link", '');

        // Process shortcodes
        $headline   = do_shortcode($headline);
        $subheading = do_shortcode($subheading);
        $link       = do_shortcode($link);

        if (empty($headline) && empty($subheading)) {
            if (defined('REST_REQUEST') && REST_REQUEST) {
                return '<div class="apn-cta apn-cta--empty">'
                    . '<span class="dashicons dashicons-megaphone"></span> '
                    . 'No ' . esc_html($cta_type) . ' CTA set for <strong>' . esc_html($phase_label) . '</strong> phase. '
                    . 'Configure in Competition Settings &rarr; Scheduled CTAs.'
                    . '</div>';
            }
            return '';
        }

        $link = esc_url($link);
        $is_editor = defined('REST_REQUEST') && REST_REQUEST;

        if ($cta_style === 'cta-box') {
            return $this->render_cta_box($headline, $subheading, $link, $cta_type, $is_editor);
        }

        return $this->render_button($headline, $link, $cta_type, $is_editor);
    }

    private function render_button($headline, $link, $cta_type, $is_editor = false) {
        $class = 'apn-cta apn-cta--button apn-cta--' . esc_attr($cta_type);
        if (!$link || $is_editor) {
            return '<span class="' . $class . '">' . esc_html($headline) . '</span>';
        }
        return '<a href="' . $link . '" class="' . $class . '">' . esc_html($headline) . '</a>';
    }

    private function render_cta_box($headline, $subheading, $link, $cta_type, $is_editor = false) {
        $class = 'apn-cta apn-cta--box apn-cta--' . esc_attr($cta_type);
        $inner = '';
        if ($headline) {
            $inner .= '<span class="apn-cta__headline">' . esc_html($headline) . '</span>';
        }
        if ($subheading) {
            $inner .= '<span class="apn-cta__subheading">' . esc_html($subheading) . '</span>';
        }

        if (!$link || $is_editor) {
            return '<div class="' . $class . '">' . $inner . '</div>';
        }
        return '<a href="' . $link . '" class="' . $class . '">' . $inner . '</a>';
    }

    // =========================================================================
    //  Editor JavaScript
    // =========================================================================

    private function get_editor_script() {
        $phases_json = json_encode(self::PHASES);

        return <<<JS
(function(wp) {
    var registerBlockType = wp.blocks.registerBlockType;
    var el = wp.element.createElement;
    var Fragment = wp.element.Fragment;
    var InspectorControls = (wp.blockEditor || wp.editor).InspectorControls;
    var PanelBody = wp.components.PanelBody;
    var SelectControl = wp.components.SelectControl;
    var ServerSideRender = wp.serverSideRender;

    var phases = {$phases_json};
    var phaseOptions = [{ value: 'auto', label: 'Autoselect (based on activation dates)' }];
    Object.keys(phases).forEach(function(slug) {
        phaseOptions.push({ value: slug, label: phases[slug] });
    });

    registerBlockType('apn/scheduled-cta', {
        title: 'Scheduled CTA',
        icon: 'megaphone',
        category: 'widgets',
        description: 'A CTA button or box that automatically changes based on the competition phase.',
        attributes: {
            ctaType: { type: 'string', default: 'primary' },
            ctaStyle: { type: 'string', default: 'button' },
            phaseOverride: { type: 'string', default: 'auto' },
        },

        edit: function(props) {
            var attributes = props.attributes;
            var setAttributes = props.setAttributes;

            var inspectorPanel = el(InspectorControls, {},
                el(PanelBody, { title: 'CTA Settings', initialOpen: true },
                    el(SelectControl, {
                        label: 'CTA Type',
                        value: attributes.ctaType,
                        options: [
                            { value: 'primary', label: 'Primary' },
                            { value: 'secondary', label: 'Secondary' },
                        ],
                        onChange: function(value) {
                            setAttributes({ ctaType: value });
                        },
                    }),
                    el(SelectControl, {
                        label: 'Style',
                        value: attributes.ctaStyle,
                        options: [
                            { value: 'button', label: 'Button' },
                            { value: 'cta-box', label: 'CTA Box (with subheading)' },
                        ],
                        onChange: function(value) {
                            setAttributes({ ctaStyle: value });
                        },
                    }),
                    el(SelectControl, {
                        label: 'Phase',
                        help: 'Override for testing. "Autoselect" uses activation dates to pick the current phase.',
                        value: attributes.phaseOverride,
                        options: phaseOptions,
                        onChange: function(value) {
                            setAttributes({ phaseOverride: value });
                        },
                    })
                )
            );

            return el(Fragment, {},
                inspectorPanel,
                el(ServerSideRender, {
                    block: 'apn/scheduled-cta',
                    attributes: attributes,
                })
            );
        },

        save: function() {
            return null;
        },
    });

    // Sidebar plugin: Shortcode Reference panel in the editor
    if (wp.plugins && wp.editPost) {
        var registerPlugin = wp.plugins.registerPlugin;
        var PluginSidebar = wp.editPost.PluginSidebar;
        var PluginSidebarMoreMenuItem = wp.editPost.PluginSidebarMoreMenuItem;

        var refRows = [
            { cat: 'Text', items: [
                ['[competition_name]', 'Competition name'],
                ['[abbreviation]', 'e.g., NYIBC'],
                ['[competition_year]', 'Latest year (e.g., 2026)'],
                ['[nth_annual]', 'e.g., "15th Annual"'],
                ['[early_bird_price]', 'Early bird price or "TBD"'],
                ['[regular_price]', 'Regular price or "TBD"'],
                ['[late_price]', 'Late price or "TBD"'],
                ['[comp_date_text]', 'Competition date text'],
                ['[winner_announcement_text]', 'Announcement text'],
                ['[entry_notes]', 'Entry notes'],
            ]},
            { cat: 'URLs', items: [
                ['[entry_page]', 'Entry page URL'],
                ['[entry_link]', 'Direct entry link'],
                ['[entry_pdf]', 'Entry PDF link'],
            ]},
            { cat: 'Dates', items: [
                ['[early_bird_deadline]', 'Early bird deadline'],
                ['[regular_deadline]', 'Regular deadline'],
                ['[late_deadline]', 'Late deadline'],
                ['[delivery_deadline]', 'Delivery deadline'],
                ['[payment_deadline]', 'Payment deadline'],
                ['[competition_start]', 'Competition start'],
                ['[competition_end]', 'Competition end'],
                ['[winner_announcement_date]', 'Winner announcement date'],
                ['[next_year_start]', 'Jan 1 of next year'],
            ]},
        ];

        var sidebarContent = refRows.map(function(group) {
            return el(PanelBody, { title: group.cat, initialOpen: true, key: group.cat },
                group.items.map(function(item) {
                    return el('div', {
                        key: item[0],
                        style: { display: 'flex', justifyContent: 'space-between', padding: '4px 0', borderBottom: '1px solid #f0f0f0', fontSize: '12.5px' }
                    },
                        el('code', { style: { color: '#d63638', fontSize: '11.5px', userSelect: 'all', cursor: 'pointer' } }, item[0]),
                        el('span', { style: { color: '#757575', marginLeft: '8px', textAlign: 'right' } }, item[1])
                    );
                })
            );
        });

        registerPlugin('apn-shortcode-reference', {
            icon: 'shortcode',
            render: function() {
                return el(Fragment, {},
                    el(PluginSidebarMoreMenuItem, { target: 'apn-shortcode-reference' }, 'Shortcode Reference'),
                    el(PluginSidebar, {
                        name: 'apn-shortcode-reference',
                        title: 'Shortcode Reference',
                        icon: 'shortcode',
                    }, sidebarContent)
                );
            },
        });
    }
})(window.wp);
JS;
    }

    // =========================================================================
    //  Styles
    // =========================================================================

    private function get_editor_styles() {
        return <<<CSS
.apn-cta--empty {
    padding: 16px 20px;
    background: #f0f0f0;
    border: 1px dashed #999;
    border-radius: 6px;
    color: #666;
    font-size: 13px;
    text-align: center;
}
.apn-cta--empty .dashicons {
    vertical-align: middle;
    margin-right: 4px;
}
CSS;
    }

    private function get_frontend_styles() {
        return <<<CSS
/* =============================================
   APN Scheduled CTA — Button Style
   ============================================= */
.apn-cta--button {
    display: inline-block;
    padding: 14px 32px;
    font-size: 16px;
    font-weight: 600;
    font-family: inherit;
    text-decoration: none;
    text-align: center;
    border-radius: 6px;
    cursor: pointer;
    transition: background-color 0.2s ease, transform 0.1s ease, box-shadow 0.2s ease;
    line-height: 1.4;
}
.apn-cta--button:hover {
    transform: translateY(-1px);
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
    text-decoration: none;
}
.apn-cta--button.apn-cta--primary {
    background-color: var(--global-palette1, #cc772d);
    color: #ffffff;
}
.apn-cta--button.apn-cta--primary:hover {
    background-color: var(--global-palette2, #874d1a);
    color: #ffffff;
}
.apn-cta--button.apn-cta--secondary {
    background-color: transparent;
    color: var(--global-palette1, #cc772d);
    border: 2px solid var(--global-palette1, #cc772d);
}
.apn-cta--button.apn-cta--secondary:hover {
    background-color: var(--global-palette1, #cc772d);
    color: #ffffff;
}

/* =============================================
   APN Scheduled CTA — Box Style
   ============================================= */
.apn-cta--box {
    display: flex;
    flex-direction: column;
    padding: 20px 28px;
    border-radius: 8px;
    text-decoration: none;
    cursor: pointer;
    transition: transform 0.2s ease, box-shadow 0.2s ease;
    text-align: center;
}
.apn-cta--box:hover {
    transform: translateY(-2px);
    box-shadow: 0 6px 20px rgba(0, 0, 0, 0.12);
    text-decoration: none;
}
.apn-cta--box.apn-cta--primary {
    background-color: var(--global-palette1, #cc772d);
    color: #ffffff;
}
.apn-cta--box.apn-cta--secondary {
    background-color: var(--global-palette9, #ffffff);
    color: var(--global-palette3, #1a202c);
    border: 2px solid var(--global-palette1, #cc772d);
}
.apn-cta__headline {
    font-size: 18px;
    font-weight: 700;
    line-height: 1.3;
    margin-bottom: 4px;
}
.apn-cta--box.apn-cta--secondary .apn-cta__headline {
    color: var(--global-palette1, #cc772d);
}
.apn-cta__subheading {
    font-size: 14px;
    font-weight: 400;
    line-height: 1.4;
    opacity: 0.85;
}
CSS;
    }
}

// Initialize
APN_Scheduled_CTA::get_instance();
