<?php
// pages/newsletter.php
require_once BEEZUI_ROOT . '/components/index.php';
require_once BEEZUI_ROOT . '/pages/layout.php';

use Components\Router as R;
use Components\ConfigStore;
use Components\Newsletter\PageConfig;
use Components\Base;

$pageConfig = PageConfig::fromRequest();
$pageKey = ($pageConfig->mode === PageConfig::MODE_AUTOMATION) ? 'trigger' : 'newsletter';
$targetContainer = \Components\Data\DataRegistry::navigation()->getTargetId($pageKey);

// Load persisted newsletter UI state for the current user
$nlUiState = ConfigStore::getNewsletterUiState($pageConfig->mode);

$viewMode = ConfigStore::getViewMode($pageKey);

// Refactor: Load Collections and Flows via hx-get components, preserving selected group
$selectedGroup = mh_get('group', '', 'string'); // slug like 'campaign-<id>' or '' (all)
$selectedListId = mh_get('list_id', 0, 'int');
$selectedScheduleType = mh_get('schedule_type', '', 'string');

// Determine initial selected slug: URL param takes priority, then persisted state,
// then mode-default (e.g., 'smart-active') to avoid loading all items by default.
$selectedSlugKey = 'selected_slug_' . $pageConfig->mode;
$persistedSlug = isset($nlUiState[$selectedSlugKey]) ? (string)$nlUiState[$selectedSlugKey] : '';
$initialSlug = $selectedGroup !== '' ? $selectedGroup : ($persistedSlug !== '' ? $persistedSlug : $pageConfig->default_smart_group);
// Build groupParam from the effective slug (not just the URL param) so that newsletter_items_list
// also receives the correct group on a reload where no URL ?group= is present.
$effectiveGroup = ($initialSlug !== '' && $initialSlug !== 'all') ? $initialSlug : '';
$groupParam = $effectiveGroup !== '' ? ['group' => $effectiveGroup] : [];
$groupParam['mode'] = $pageConfig->mode;
if ($selectedListId > 0) { $groupParam['list_id'] = $selectedListId; }
if ($selectedScheduleType !== '') { $groupParam['schedule_type'] = $selectedScheduleType; }
if (mh_get('open_id', 0, 'int') > 0) { $groupParam['open_id'] = mh_get('open_id', 0, 'int'); }
if (mh_get('highlight_step', '', 'string') !== '') { $groupParam['highlight_step'] = mh_get('highlight_step', '', 'string'); }
$initialSlugEsc = \Components\Base::h($initialSlug, false);

// Base URL for the items list (no group param); used by the collections:refresh JS listener
// and the newsletter_item:created handler to reload the list for the newly created campaign group.
$itemsListBaseUrl = \Components\Base::h($pageConfig->getBaseUrl('newsletter_items_list', ['partial' => 1]), false);
$collectionsListBaseUrl = \Components\Base::h($pageConfig->getBaseUrl('newsletter_collection_list', ['partial' => 1]), false);

ob_start();
?>

<?php
ob_start();
?>
{
  mode: '<?= $pageConfig->mode; ?>',
  selectedSlug: '<?= $initialSlugEsc; ?>',
  viewMode: '<?= \Components\Base::h($viewMode); ?>',
  itemsListBaseUrl: '<?= $itemsListBaseUrl; ?>',
  collectionsListBaseUrl: '<?= $collectionsListBaseUrl; ?>',
  init() {
    // Sync with global store if present
    if (this.mode === 'automation') {
       if (window.Alpine && Alpine.store('trigger')) {
           this.viewMode = Alpine.store('trigger').viewMode;
           this.$watch('$store.trigger.viewMode', v => { this.viewMode = v; });
       }
    } else {
       if (window.Alpine && Alpine.store('newsletter')) {
           this.viewMode = Alpine.store('newsletter').viewMode;
           this.$watch('$store.newsletter.viewMode', v => { this.viewMode = v; });
       }
    }

    // Check if there is a pending openKey for this page in the parent app-main scope
    if (typeof this.active !== 'undefined' && this.active === '<?= $pageKey ?>' && this.openKey) {
        this.selectedSlug = this.openKey;
    }

    document.body.addEventListener('<?= $pageConfig->getEventName('newsletter_item:new:preselected'); ?>', (ev) => {
      const listId = ev.detail && ev.detail.list_id ? ev.detail.list_id : null;
      if (!listId) return;
      const campaignId = ev.detail && ev.detail.campaign_id ? ev.detail.campaign_id : 0;
      let templateId = ev.detail && typeof ev.detail.template_id !== 'undefined' ? ev.detail.template_id : '';
      if (templateId === null || templateId === 'null' || templateId === 'undefined') {
          templateId = '';
      }

      let url = '';
      if (templateId !== '') {
        url = '<?= \Components\Base::h(R::url('newsletter_item_modal', ['partial' => 1, 'mode' => 'new', 'page_mode' => $pageConfig->mode]), false); ?>';
        url += '&template_id=' + encodeURIComponent(templateId);
      } else {
        url = '<?= \Components\Base::h(R::url('newsletter_template_selection_modal', ['partial' => 1, 'mode' => 'new', 'page_mode' => $pageConfig->mode]), false); ?>';
      }

      if (campaignId > 0) {
          url += '&newsletter_campaign_id=' + encodeURIComponent(campaignId);
      }
      url += '&newsletter_list_id=' + encodeURIComponent(listId);

      var m = document.getElementById('config-modal');
      if (m) {
          // If the modal was in iframe mode (e.g. legacy segmentation), switch back to body mode
          m.removeAttribute('data-url');
          // Reset modal size to standard 5xl for the creation dialog
          m.setAttribute('data-size', '5xl');
          if (typeof m.showModal === 'function' && !m.open) {
              m.showModal();
          }
      }

      htmx.ajax('GET', url, {
        target: '#config-modal-body',
        swap: 'innerHTML',
      });
    });
    document.body.addEventListener('<?= $pageConfig->getEventName('newsletter_item:created'); ?>', (ev) => {
      const id = ev.detail && ev.detail.id ? ev.detail.id : null;
      if (!id) return;
      const campaignId = ev.detail && ev.detail.campaign_id ? ev.detail.campaign_id : null;
      const slug = campaignId ? ('campaign-' + campaignId) : null;
      if (slug) {
          // Set the selected slug so the sidebar highlights the correct collection
          this.selectedSlug = slug;
          // Reload the items list filtered to the newly created campaign group
          htmx.ajax('GET', this.itemsListBaseUrl + '&group=' + encodeURIComponent(slug), {
            target: '#<?= $pageConfig->getTargetId('items-list'); ?>',
            swap: 'outerHTML',
          });
          // Refresh the collections list to update item counts; the declarative hx-trigger on
          // campaigns-list also fires for this event, so this explicit call ensures
          // the refreshed list reflects the new selectedSlug highlight immediately.
          htmx.ajax('GET', this.collectionsListBaseUrl + '&group=' + encodeURIComponent(slug), {
            target: '#<?= $pageConfig->getTargetId('campaigns-list'); ?>',
            swap: 'outerHTML',
          });
      }
    });
    window.addEventListener('mb:open-item', (ev) => {
      const targetMode = ev.detail && ev.detail.page_mode ? ev.detail.page_mode : null;
      if (targetMode && targetMode !== '<?= $pageConfig->mode ?>') return;

      const key = ev.detail && ev.detail.key ? ev.detail.key : null;
      const group = ev.detail && ev.detail.group ? ev.detail.group : null;
      if (group || key) {
          const slug = group || key;
          this.selectedSlug = slug;

          const itemsTarget = '#<?= $pageConfig->getTargetId('items-list'); ?>';
          const collectionsTarget = '#<?= $pageConfig->getTargetId('campaigns-list'); ?>';

          // Reload the items list filtered to the selected group
          if (document.querySelector(itemsTarget)) {
              let url = this.itemsListBaseUrl + '&group=' + encodeURIComponent(slug);
              if (ev.detail.params) {
                  for (const [k, v] of Object.entries(ev.detail.params)) {
                      if (k !== 'group') url += '&' + k + '=' + encodeURIComponent(v);
                  }
              }
              htmx.ajax('GET', url, {
                target: itemsTarget,
                swap: 'outerHTML',
              });
          }
          // Refresh the collections list to reflect the highlight
          if (document.querySelector(collectionsTarget)) {
              htmx.ajax('GET', this.collectionsListBaseUrl + '&group=' + encodeURIComponent(slug), {
                target: collectionsTarget,
                swap: 'outerHTML',
              });
          }
      }
    });
  }
}
<?php
$xDataNewsletter = ob_get_clean();
?>
<div class="" x-data="<?= \Components\Base::h($xDataNewsletter, false); ?>">
  <script>
    // Initialize Alpine store for Newsletter page (used by global toggle and view synchronization)
    (function () {
        try {
            var viewModeSeed = <?= json_encode($viewMode); ?>;
            var pageMode = <?= json_encode($pageConfig->mode); ?>;
            function ensureNewsletterStore() {
                try {
                    if (!window.Alpine) return;
                    // Only create 'newsletter' store if not in automation mode (which uses 'trigger' store)
                    if (pageMode !== 'automation' && !Alpine.store('newsletter')) {
                        Alpine.store('newsletter', {
                            viewMode: viewModeSeed
                        });
                    }
                } catch (e) {}
            }
            if (window.Alpine && typeof Alpine.store === 'function') {
                ensureNewsletterStore();
            } else {
                document.addEventListener('alpine:init', ensureNewsletterStore, { once: true });
            }
        } catch (e) {}
    })();
  </script>
  <?php
  $pageKey = 'newsletter'; // keep $pageKey scoped for layout
  // Persisted sidebar settings (server-side defaults, overridden client-side on init)
  $persistedWidth     = isset($nlUiState['sidebar_width']) ? (int)$nlUiState['sidebar_width'] : 300;
  $persistedCollapsed = !empty($nlUiState['sidebar_collapsed']) ? 'true' : 'false';

  if ($persistedWidth < 280) { $persistedWidth = 300; }
  if ($persistedWidth > 448) { $persistedWidth = 448; }

  $refreshUrl = R::url('newsletter_collection_list', array_merge(['partial' => 1], $groupParam));
  $savedGroupParam = $groupParam; // newsletter_collection_list.php overwrites $groupParam via mh_get()
  ob_start();
  $isNewsletterPageInclude = true;
  require BEEZUI_ROOT . '/pages/components/newsletter_collection_list.php';
  unset($isNewsletterPageInclude);
  $collectionsInner = ob_get_clean();
  $groupParam = $savedGroupParam; // restore effective group so lines below use the persisted slug
  // Extract only the inner content (without the outer HTMX-trigger wrapper) for the overlay.
  // This prevents a duplicate #newsletter-campaigns-list element with live hx-trigger attributes
  // from being placed inside the overlay, which would cause double-refresh requests on events.
  // Use markers for clean extraction.
  $_innerStart = strpos($collectionsInner, '<!-- inner-start -->');
  $_innerEnd   = strpos($collectionsInner, '<!-- inner-end -->');
  if ($_innerStart !== false && $_innerEnd !== false && $_innerEnd > $_innerStart) {
      $collectionsOverlayInner = substr($collectionsInner, $_innerStart, $_innerEnd - $_innerStart);
  } else {
      $collectionsOverlayInner = $collectionsInner; // fallback
  }
  unset($_innerStart, $_innerEnd);

  // Extracted: New Collection button (moved out of the component for flat structure)
  $newCollectionBtn = \Components\Button::render(mh_lng('UI_NEW', 'New'), [
          'variant' => 'ghost',
          'size' => 'sm',
          'icon' => \Components\Base::SVG_PLUS,
          'iconPosition' => 'front',

          'attrs' => [
          'command' => 'show-modal',
          'commandfor' => 'config-modal',
          'data-title' => mh_lng('UI_COLLECTIONS_NEW_TITLE', 'New Collection'),
          'data-size' => 'xl',
          'hx-get' => \Components\Router::url('newsletter_collection_modal', ['partial' => 1, 'mode' => 'new', 'page_mode' => $pageConfig->mode]),
          'hx-target' => '#config-modal-body',
          'hx-swap' => 'innerHTML',
          'data-no-global-loader' => '1',
          'data-no-local-loader' => '1',
      ],
  ]);

  // Save URL for async persistence
  $saveStateUrl = $pageConfig->getBaseUrl('newsletter_ui_state_save', ['partial' => 1]);

  // Page toolbar: New Flow button — rendered in outer Alpine scope (my-6) so it can read selectedSlug
      $newFlowBaseUrl = $pageConfig->getBaseUrl('newsletter_audience_selection_modal', ['partial' => 1, 'step' => 'existing']);
  $newFlowBtn = \Components\Button::render($pageConfig->new_button_label, [
      'icon' => \Components\Base::SVG_PLUS,
      'iconPosition' => 'front',
      'size' => 'md',
      'variant' => 'secondary',
      'attrs' => [
          'command' => 'show-modal',
          'commandfor' => 'config-modal',
          'data-title' => $pageConfig->creation_modal_title,
          'data-size' => '5xl',
          'hx-get' => $newFlowBaseUrl,
          'hx-target' => '#config-modal-body',
          'hx-swap' => 'innerHTML',
          'hx-push-url' => 'false',
          'data-no-global-loader' => 'true',
//          ':disabled' => "!selectedSlug.startsWith('campaign-')",
//          ':class' => "!selectedSlug.startsWith('campaign-') ? 'opacity-40 cursor-not-allowed pointer-events-none' : ''",
          ':hx-vals' => "(function(){ var m = selectedSlug.match(/^campaign-(\\d+)$/); return m ? JSON.stringify({ newsletter_campaign_id: parseInt(m[1]) }) : '{}' })()",
      ],
  ]);
  if ($pageConfig->mode == 'newsletter') {
      $viewModeToggle = \Components\Ui\FlowHelpers::renderGlobalToggle($pageKey);

      echo \Components\Ui\PageHeader::render($pageConfig->title, [
          'subtitle' => $pageConfig->subtitle,
          'center' => $viewModeToggle,
          'right' => '<div class="flex gap-2 items-center">' . $newFlowBtn . '</div>',
      ]);
  }
  ?>

  <div id="<?= $pageConfig->getTargetId('layout'); ?>"
       x-cloak
       class="relative flex items-stretch my-6"
       :class="collapsed ? 'gap-0' : 'gap-4'"
       x-data="<?= Base::h('
        {
         width: ' . $persistedWidth . ',
         collapsed: ' . $persistedCollapsed . ',
         min: 300,
         max: 448,
         dragging: false,
         mode: \'' . $pageConfig->mode . '\',
         startX: 0,
         startW: 0,
         saveUrl: \'' . \Components\Base::h($saveStateUrl, false) . '\',
         ddOpen: false,
         saveTimer: null,
         clamp(v){ return Math.max(this.min, Math.min(this.max, v)); },
         persistState(patch) {
           // Map mode-specific fields
           const mapped = {};
           for (const [k, v] of Object.entries(patch)) {
             if (k === \'selected_slug\') {
               mapped[\'selected_slug_\' + this.mode] = v;
             } else {
               mapped[k] = v;
             }
           }
           const body = new URLSearchParams({ state_patch: JSON.stringify(mapped) });
           fetch(this.saveUrl, { method: \'POST\', headers: { \'Content-Type\': \'application/x-www-form-urlencoded\', \'X-Requested-With\': \'XMLHttpRequest\' }, body: body.toString() }).catch(()=>{});
         },
         setWidth(w){
           this.width = this.clamp(w);
           clearTimeout(this.saveTimer);
           this.saveTimer = setTimeout(() => { this.persistState({ sidebar_width: this.width }); }, 500);
         },
         toggleCollapse(){
           this.collapsed = !this.collapsed;
           this.ddOpen = false;
           this.persistState({ sidebar_collapsed: this.collapsed });
         },
         startDrag(e){ if (this.collapsed) return; this.dragging = true; this.startX = e.clientX; this.startW = this.$refs.sidebar.getBoundingClientRect().width;
           const onMove = (ev)=>{ if(!this.dragging) return; const dx = ev.clientX - this.startX; this.setWidth(this.startW + dx); };
           const onUp = ()=>{ this.dragging=false; window.removeEventListener(\'mousemove\', onMove); window.removeEventListener(\'mouseup\', onUp); };
           window.addEventListener(\'mousemove\', onMove); window.addEventListener(\'mouseup\', onUp);
         },
         init(){
           // Server already provided width/collapsed; watch selectedSlug changes to persist
           this.$watch(\'selectedSlug\', (slug) => { this.persistState({ selected_slug: slug }); });
         }
       }
      ', false); ?>">

      <!-- No floating control anymore; controls are now inline:
           - When expanded: button is rendered beside the Collections title (left)
           - When collapsed: control pill appears inside the items header (header_left slot) -->
      <!-- Sidebar wrapper with resizable/collapsible width -->
      <aside id="<?= $pageConfig->getTargetId('sidebar'); ?>" x-ref="sidebar" class="shrink-0 overflow-hidden transition-[width] h-full flex flex-col"
             :class="[
                collapsed ? 'ease-out opacity-70 duration-300' : 'ease-out-back-sm duration-400',
                dragging ? '!duration-0' : ''
             ]"
             :style="collapsed ? 'width:0px' : `width:${width}px`">
         <div class="h-full flex flex-col shrink-0" :style="`width:${width}px`">
             <div class="h-full flex flex-col rounded-2xl border border-divider bg-elevated overflow-hidden">
                 <div class="px-3 pt-3 pb-2 flex items-center justify-between shrink-0">
                     <div class="flex items-center gap-2 [&_svg]:size-5">
                         <!-- Toggle button inline with Collections title when expanded -->
                         <button type="button"
                                 x-show="!collapsed"
                                 @click="toggleCollapse()"
                                 class="inline-flex items-center justify-center p-1.5 hover:bg-white/70 focus:outline-none text-secondary/70 hover:text-secondary"
                                 :aria-pressed="(!collapsed).toString()"
                                 title="Hide collections">
                             <?= \Components\Base::SVG_PANEL_CLOSE; ?>
                         </button>
                         <h4 class="text-sm font-semibold text-primary"><?= \Components\Base::h(mh_lng('UI_COLLECTIONS', 'Collections')); ?></h4>
                     </div>
                     <?= $newCollectionBtn; ?>
                 </div>
                 <div class="px-2 pb-3 flex-1 overflow-y-auto">
                    <?= $collectionsInner; ?>
                 </div>
             </div>
         </div>
      </aside>

      <!-- Vertical resizer handle -->
      <div id="<?= $pageConfig->getTargetId('resizer'); ?>"
           class="relative group flex w-2 cursor-col-resize justify-center z-10 select-none"
           x-cloak
           x-data="{
                handleTop: 250,
                updateHandle() {
                    const scroller = document.getElementById('app-shell-main-content');
                    if (!scroller) return;
                    const scrollerRect = scroller.getBoundingClientRect();
                    const containerRect = this.$el.getBoundingClientRect();
                    const viewportCenter = scrollerRect.top + (scrollerRect.height / 2);
                    // Position once relative to the top of the container, so it scrolls with the page
                    // but appears centered when the page is at the top.
                    const containerTopAtTop = containerRect.top + scroller.scrollTop;
                    this.handleTop = Math.max(44, Math.min(containerRect.height - 44, viewportCenter - containerTopAtTop));
                }
           }"
           x-init="
                updateHandle();
                window.addEventListener('resize', () => updateHandle(), { passive: true });
                $watch('collapsed', () => setTimeout(() => updateHandle(), 400));

                if (window.ResizeObserver) {
                   new ResizeObserver(() => updateHandle()).observe($el);
                }
           "
           :class="[
                collapsed ? '-ml-4.75 mr-2.75' : '-ml-1 -mr-1',
                dragging ? '!duration-0' : ''
           ]"
           @mousedown="startDrag"
           @click.prevent="collapsed && toggleCollapse()"
           @dblclick.prevent="toggleCollapse()"
           title="Drag to resize; double-click to collapse/expand">
          <div class="absolute z-10 flex h-22 w-1.25 shrink-0 rounded-lg bg-divider -translate-y-1/2 pointer-events-none"
               :style="{ top: handleTop + 'px' }"></div>
      </div>
      <!-- Main content (flows) -->
      <div class="flex-1 min-w-0">
          <div id="<?= $pageConfig->getTargetId('items-panel'); ?>" class="relative h-full">
              <?= \Components\Base::loaderOverlay($pageConfig->getTargetId('loading-items'), 'z-100 rounded-2xl'); ?>
              <script>
                (function(){
                  try {
                    if(window.MBLoader){
                      MBLoader.bindHtmxOverlay('<?= $pageConfig->getTargetId('items-panel'); ?>', '<?= $pageConfig->getTargetId('loading-items'); ?>', 500, function(evt) {
                        var detail = evt.detail;
                        var path = (detail.pathInfo ? detail.pathInfo.requestPath : '') || (detail.requestConfig ? detail.requestConfig.path : '');
                        return (detail.target && detail.target.id === '<?= $pageConfig->getTargetId('items-list'); ?>') || (path && path.indexOf('newsletter_items_list') !== -1);
                      });
                    }
                  } catch (e) { /* no-op */ }
                })();
              </script>
              <div id="<?= $pageConfig->getTargetId('items-list'); ?>"
                   class="h-full"
                   hx-get="<?= $pageConfig->getBaseUrl('newsletter_items_list', array_merge(['partial' => 1], $groupParam)); ?>"
                   hx-trigger="load, <?= $pageConfig->getEventName('timeframe:updated'); ?> from:body"
                   hx-swap="outerHTML"
                   hx-on:htmx:afterSwap="htmx.trigger(document.body, '<?= $pageConfig->getEventName('campaigns:refresh'); ?>')"
              >
                  <div class="relative h-full">
                      <?= \Components\Base::loaderOverlay($pageConfig->getTargetId('loading-items-initial'), 'z-10 rounded-2xl', '', false); ?>
                  </div>
              </div>
          </div>
      </div>
      <!-- Collections overlay (for collapsed state) -->
      <?php
      // Pre-render dropdown-style collections menu and allow HTMX-based refresh on navigation
      // Ensure we don't duplicate IDs: we render only the inner list here.
      ?>
          <div id="<?= $pageConfig->getTargetId('collections-overlay'); ?>"
               x-show="ddOpen" x-transition x-cloak
               @click.outside="ddOpen=false"
               class="absolute left-0 top-14 w-80 max-h-[70vh] overflow-auto rounded-2xl border border-divider bg-elevated shadow-xl p-3 z-50">
              <div id="<?= $pageConfig->getTargetId('collections-overlay-inner'); ?>"
                   @click="if ($event.target.closest('[data-slug]')) { ddOpen=false }"
              >
                  <?= $collectionsOverlayInner; ?>
              </div>
            </div>
  </div>

</div>


<?php
$content = ob_get_clean();

if (isset($isNewsletterInclude) && $isNewsletterInclude) {
    return $content;
}

if (mh_get('partial', 0, 'int')) {
    echo $content;
    exit;
}

echo layout($pageKey, $content);
