<template>
  <div class="cw-composer-layout">
    <!-- Left panel (settings or selectors) -->
    <div class="cw-left-panel">
      <!-- If block selected, render Settings panel -->
      <BlockSettings v-if="selectedBlockId" />
      <!-- Otherwise render Selector panel -->
      <BlockSelector v-else />
    </div>

    <!-- Center/Right Canvas Area -->
    <div class="cw-canvas-pane">
      <!-- Canvas Toolbar -->
      <EditorToolbar />

      <!-- Scrollable Canvas Wrap -->
      <div 
        class="cw-canvas-wrap" 
        :style="canvasWrapStyle"
        @click.self="selectedBlockId = null"
      >
        <!-- Canvas Body Frame -->
        <div 
          class="cw-email-frame" 
          :style="emailFrameStyle"
          :class="{ 'is-dragging': isDragging, 'is-mobile': previewDevice === 'mobile' }"
        >
          <EmailCanvas v-model="localBlocks" />
        </div>
      </div>
    </div>

    <!-- HTML Expand Modal -->
    <div v-if="showHtmlEditor" class="modal-overlay is-open" @click.self="showHtmlEditor = false">
      <div class="modal" style="max-width: 900px; width: 100%; height: 80vh; display: flex; flex-direction: column;">
        <div class="modal-header">
          <h3 class="modal-title">HTML Code Editor</h3>
          <button type="button" class="modal-close" @click="showHtmlEditor = false">✕</button>
        </div>
        <div class="modal-body" style="flex: 1; min-height: 0; padding: 0; position: relative; overflow: hidden;">
          <div class="cw-code-editor" style="height: 100%; border-radius: 0; border: none;">
            <div class="cw-code-lines" ref="modalCodeLineRef" aria-hidden="true" style="padding-top:16px;">
              <span v-for="n in htmlLineCount(htmlEditorBlock?.html)" :key="n">{{ n }}</span>
            </div>
            <textarea
              class="cw-code-textarea"
              v-model="htmlEditorBlock.html"
              spellcheck="false"
              placeholder="<!-- Raw HTML code here -->"
              @scroll="syncModalCodeScroll"
              ref="modalCodeEditorRef"
              style="padding-top:16px;"
            ></textarea>
          </div>
        </div>
        <div class="modal-footer" style="padding: 12px 16px; display: flex; justify-content: flex-end; gap: 8px; border-top: 1px solid #e5e7eb;">
          <button type="button" class="btn btn-ghost btn-sm" @click="showHtmlEditor = false">Close</button>
        </div>
      </div>
    </div>

    <!-- Test Email Modal -->
    <div v-if="showTestEmailModal" class="modal-overlay is-open" @click.self="closeTestModal">
      <div class="modal" style="max-width:420px;width:100%">
        <div class="modal-header">
          <span class="modal-title">Send a Test Email</span>
          <button type="button" class="modal-close" @click="closeTestModal">✕</button>
        </div>
        <div class="modal-body" style="padding:20px">
          <p style="font-size:13px;color:#6b7280;margin:0 0 14px">
            Send this campaign as a test to any email address to preview how it looks in an inbox.
          </p>
          <label style="font-size:12px;font-weight:600;color:#374151;display:block;margin-bottom:6px">Recipient email address</label>
          <input
            v-model="testEmailAddress"
            type="email"
            placeholder="you@example.com"
            class="cw-field-input"
            style="height:38px;font-size:13px;width:100%;box-sizing:border-box"
            @keydown.enter="doSendTestEmail"
            ref="testEmailInputRef"
          />
          <p v-if="testEmailError" style="font-size:12px;color:#dc2626;margin:6px 0 0">{{ testEmailError }}</p>
          <p v-if="testEmailSuccess" style="font-size:12px;color:#16a34a;margin:6px 0 0">{{ testEmailSuccess }}</p>
        </div>
        <div class="modal-footer" style="display:flex;justify-content:flex-end;gap:8px;padding:12px 16px;border-top:1px solid #e5e7eb">
          <button type="button" class="btn btn-ghost btn-sm" @click="closeTestModal">Cancel</button>
          <button type="button" class="btn btn-primary btn-sm" @click="doSendTestEmail" :disabled="testEmailSending">
            <svg v-if="testEmailSending" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="13" height="13" class="cw-spin">
              <path d="M12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83"/>
            </svg>
            {{ testEmailSending ? 'Sending…' : 'Send Test' }}
          </button>
        </div>
      </div>
    </div>

  </div>
</template>

<script setup>
import { ref, computed, provide, nextTick, onMounted, onUnmounted, reactive, watch } from 'vue';
import { usePage } from '@inertiajs/vue3';
import BlockSelector from './BlockSelector.vue';
import BlockSettings from './BlockSettings.vue';
import EditorToolbar from './EditorToolbar.vue';
import EmailCanvas from './EmailCanvas.vue';
import {
  makeBlock,
  defaultStyles,
  ensureBlockIds
} from './editorUtils';

const props = defineProps({
  modelValue: {
    type: Array,
    required: true
  },
  campaignId: {
    type: Number,
    required: false,
    default: null
  },
  globalSettings: {
    type: Object,
    default: () => ({})
  }
});

const emit = defineEmits(['update:modelValue']);

const localBlocks = ref([]);

// Editor active states
const selectedBlockId = ref(null);
const focusedTextId = ref(null);
const previewDevice = ref('desktop');

// History Undo/Redo stack
const historyStack = ref([]);
const historyIndex = ref(-1);
let isUndoingOrRedoing = false;
let saveTimer = null;
const isDragging = ref(false);

function onDragStart() {
  isDragging.value = true;
}

function onDragEnd() {
  isDragging.value = false;
  saveHistory();
}

function saveHistory() {
  if (isUndoingOrRedoing) return;
  const stateStr = JSON.stringify(localBlocks.value);
  if (historyIndex.value >= 0 && historyStack.value[historyIndex.value] === stateStr) {
    return;
  }
  if (historyIndex.value < historyStack.value.length - 1) {
    historyStack.value = historyStack.value.slice(0, historyIndex.value + 1);
  }
  historyStack.value.push(stateStr);
  if (historyStack.value.length > 50) {
    historyStack.value.shift();
  }
  historyIndex.value = historyStack.value.length - 1;

  // Emit updated blocks cleanly back to the parent component
  emit('update:modelValue', JSON.parse(stateStr));
}

const canUndo = computed(() => historyIndex.value > 0);
const canRedo = computed(() => historyIndex.value < historyStack.value.length - 1);

function undo() {
  if (historyIndex.value > 0) {
    isUndoingOrRedoing = true;
    historyIndex.value--;
    localBlocks.value = JSON.parse(historyStack.value[historyIndex.value]);
    selectedBlockId.value = null;
    nextTick(() => { isUndoingOrRedoing = false; });
  }
}

function redo() {
  if (historyIndex.value < historyStack.value.length - 1) {
    isUndoingOrRedoing = true;
    historyIndex.value++;
    localBlocks.value = JSON.parse(historyStack.value[historyIndex.value]);
    selectedBlockId.value = null;
    nextTick(() => { isUndoingOrRedoing = false; });
  }
}

async function clearCanvas() {
  if (await confirm('Are you sure you want to clear your layout? This will delete all blocks.')) {
    localBlocks.value = [];
    selectedBlockId.value = null;
    saveHistory();
  }
}

// Keydown Undo/Redo shortcuts listener
function handleKeyDown(e) {
  if ((e.ctrlKey || e.metaKey) && e.key === 'z') {
    e.preventDefault();
    if (e.shiftKey) redo();
    else undo();
  } else if ((e.ctrlKey || e.metaKey) && e.key === 'y') {
    e.preventDefault();
    redo();
  }
}

function isOldDefaultBlocks(blocksList) {
  if (!blocksList || blocksList.length === 0) return true;
  const headingBlock = blocksList.find(b => b.type === 'heading');
  const textBlock = blocksList.find(b => b.type === 'text');
  const buttonBlock = blocksList.find(b => b.type === 'button');
  
  const isOldHeading = headingBlock && (headingBlock.content === 'Your Heading Here' || headingBlock.content === 'Your Heading');
  const isOldText = textBlock && textBlock.content && (textBlock.content.startsWith('Welcome to your new email design') || textBlock.content.startsWith('Your text here'));
  const isOldButton = buttonBlock && (buttonBlock.text === 'Call To Action' || buttonBlock.text === 'Click Here');
  
  return !!(isOldHeading || (isOldText && isOldButton));
}

watch(() => props.modelValue, (newVal) => {
  if (!newVal || newVal.length === 0 || isOldDefaultBlocks(newVal)) {
    localBlocks.value = createDefaultTemplate();
    ensureBodyBlock();
  } else {
    const currentHist = historyStack.value[historyIndex.value];
    if (currentHist !== JSON.stringify(newVal)) {
      localBlocks.value = newVal.map(b => ensureBlockIds(b, props.globalSettings));
      ensureBodyBlock();
      saveHistory();
    }
  }
}, { deep: true });

onMounted(() => {
  if (props.modelValue.length === 0 || isOldDefaultBlocks(props.modelValue) || (props.modelValue.length === 1 && props.modelValue[0].type === 'footer')) {
    localBlocks.value = createDefaultTemplate();
  } else {
    // Ensure all blocks have styles and properties populated
    localBlocks.value = props.modelValue.map(b => ensureBlockIds(b, props.globalSettings));
  }
  ensureBodyBlock();
  historyStack.value = [JSON.stringify(localBlocks.value)];
  historyIndex.value = 0;
  // Emit initial normalized value back to parent
  emit('update:modelValue', localBlocks.value);
  window.addEventListener('keydown', handleKeyDown);
});

onUnmounted(() => {
  window.removeEventListener('keydown', handleKeyDown);
});

function createDefaultTemplate() {
  const mk = (type, extra = {}) => {
    const { styles, ...rest } = extra;
    return reactive({
      id: crypto.randomUUID(), type, styles: { ...defaultStyles(type), ...(styles || {}) }, ...rest,
    });
  };
  
  const brandName = props.globalSettings?.business?.name || import.meta.env.VITE_APP_NAME || 'Your Brand';
  const hasLogo = !!(props.globalSettings?.business?.logo);
  const logoSrc = props.globalSettings?.business?.logo;
  const logoType = hasLogo ? 'image' : 'text';
  
  return [
    mk('spacer', { styles: { height: 10, bgColor: '' } }),
    mk('logo', {
      logoType: logoType, brandText: brandName, src: logoSrc, alt: brandName, link: '',
      styles: { textAlign: 'center', color: '#4f46e5', fontSize: 24, fontWeight: 'bold', paddingTop: 32, paddingBottom: 16, bgColor: '' }
    }),
    mk('heading', {
      content: 'Welcome to our community!',
      styles: { textAlign: 'center', fontSize: 26, color: '#111827', paddingTop: 8, paddingBottom: 8, bgColor: '' }
    }),
    mk('text', {
      content: 'We are thrilled to have you on board. Get ready for exciting updates, exclusive offers, and behind-the-scenes content delivered straight to your inbox.',
      styles: { textAlign: 'center', color: '#4b5563', fontSize: 16, lineHeight: 1.6, paddingLeft: 40, paddingRight: 40, paddingBottom: 24, bgColor: '' }
    }),
    mk('button', {
      text: 'Explore Features',
      href: '#', linkType: 'url', linkTarget: '', linkTooltip: '',
      styles: { textAlign: 'center', backgroundColor: '#4f46e5', textColor: '#ffffff', fontSize: 15, borderRadius: 6, paddingTop: 14, paddingBottom: 14, paddingLeft: 28, paddingRight: 28, bgColor: '', blockAlign: 'center' }
    }),
    mk('divider', { styles: { dividerThickness: 1, borderColor: '#e5e7eb', bgColor: '', paddingLeft: 0, paddingRight: 0 } }),
    mk('social', {
      links: [
        { id: crypto.randomUUID(), platform: 'facebook', url: '#' },
        { id: crypto.randomUUID(), platform: 'twitter', url: '#' },
        { id: crypto.randomUUID(), platform: 'instagram', url: '#' }
      ],
      iconSize: 'medium', iconShape: 'circle', iconTheme: 'colored', spaceBetween: 12,
      styles: { textAlign: 'center', paddingTop: 24, paddingBottom: 16, bgColor: '' }
    }),
    mk('footer', {
      content: props.globalSettings?.email?.footer_notice || "You're receiving this email because you opted in at our website.",
      copyright: props.globalSettings?.email?.footer_copyright || ("© " + new Date().getFullYear() + " " + brandName + " · All rights reserved"),
      showUnsubscribe: true, showPrivacy: true,
      styles: { textAlign: 'center', fontSize: 12, color: '#9ca3af', bgColor: '', paddingTop: 12, paddingBottom: 12 }
    }),
    mk('spacer', { styles: { height: 10, bgColor: '' } }),
  ];
}

// Block lookups & selection
function findBlockById(id) {
  for (const b of localBlocks.value) {
    if (b.id === id) return b;
    if (b.type === 'column') {
      for (const col of b.columns) {
        const found = col.blocks.find(nb => nb.id === id);
        if (found) return found;
      }
    }
  }
  return null;
}

const selectedBlock = computed(() => findBlockById(selectedBlockId.value));

const bodyBlock = computed(() => {
  return localBlocks.value.find(b => b.type === 'body') || {
    bgColor: '#f3f4f6',
    bgImage: '',
    bgPattern: '',
    contentBgColor: '#ffffff',
    contentBgImage: '',
    contentWidth: 600
  };
});

const canvasWrapStyle = computed(() => {
  return {
    backgroundColor: bodyBlock.value.bgColor || '#f3f4f6',
  };
});

const emailFrameStyle = computed(() => {
  const styles = {
    backgroundColor: bodyBlock.value.contentBgColor || '#ffffff',
    maxWidth: `${bodyBlock.value.contentWidth || 600}px`
  };
  
  if (bodyBlock.value.bgImage) {
    styles.backgroundImage = `url(${bodyBlock.value.bgImage})`;
    styles.backgroundRepeat = 'repeat';
    styles.backgroundSize = 'auto';
  } else if (bodyBlock.value.bgPattern) {
    if (bodyBlock.value.bgPattern === 'dots') {
      styles.backgroundImage = 'radial-gradient(rgba(0,0,0,0.1) 1px, transparent 1px)';
      styles.backgroundSize = '16px 16px';
    } else if (bodyBlock.value.bgPattern === 'grid') {
      styles.backgroundImage = 'linear-gradient(rgba(0,0,0,0.04) 1px, transparent 1px), linear-gradient(90deg, rgba(0,0,0,0.04) 1px, transparent 1px)';
      styles.backgroundSize = '20px 20px';
    } else if (bodyBlock.value.bgPattern === 'stripes') {
      styles.backgroundImage = 'repeating-linear-gradient(45deg, rgba(0,0,0,0.02) 0px, rgba(0,0,0,0.02) 1px, transparent 1px, transparent 10px)';
    } else if (bodyBlock.value.bgPattern === 'abstract') {
      styles.backgroundImage = 'linear-gradient(45deg, rgba(0,0,0,0.015) 25%, transparent 25%), linear-gradient(-45deg, rgba(0,0,0,0.015) 25%, transparent 25%)';
      styles.backgroundSize = '30px 30px';
    }
  }
  
  return styles;
});

function ensureBodyBlock() {
  const hasBody = localBlocks.value.some(b => b.type === 'body');
  if (!hasBody) {
    localBlocks.value.unshift({
      id: 'email-body-settings',
      type: 'body',
      bgColor: '#f3f4f6',
      bgImage: '',
      bgPattern: '',
      contentBgColor: '#ffffff',
      contentBgImage: '',
      contentWidth: 600
    });
  }
}

function selectBlock(id) {
  selectedBlockId.value = id;
}

function duplicateBlock(id) {
  const block = findBlockById(id);
  if (block && block.type === 'footer') return;

  function cloneBlock(b) {
    const cloned = JSON.parse(JSON.stringify(b));
    cloned.id = crypto.randomUUID();
    if (cloned.type === 'column' && cloned.columns) {
      cloned.columns = cloned.columns.map(col => {
        const newCol = { ...col, id: crypto.randomUUID() };
        if (col.blocks) {
          newCol.blocks = col.blocks.map(cloneBlock);
        } else {
          newCol.blocks = [];
        }
        return newCol;
      });
    }
    return reactive(cloned);
  }

  const idx = localBlocks.value.findIndex(b => b.id === id);
  if (idx >= 0) {
    const cloned = cloneBlock(localBlocks.value[idx]);
    localBlocks.value.splice(idx + 1, 0, cloned);
    saveHistory();
    return;
  }

  for (const b of localBlocks.value) {
    if (b.type === 'column' && b.columns) {
      for (const col of b.columns) {
        const ni = col.blocks.findIndex(nb => nb.id === id);
        if (ni >= 0) {
          const cloned = cloneBlock(col.blocks[ni]);
          col.blocks.splice(ni + 1, 0, cloned);
          saveHistory();
          return;
        }
      }
    }
  }
}

function deleteBlock(id) {
  const idx = localBlocks.value.findIndex(b => b.id === id);
  if (idx >= 0) { 
    localBlocks.value.splice(idx, 1); 
  } else {
    for (const b of localBlocks.value) {
      if (b.type === 'column') {
        for (const col of b.columns) {
          const ni = col.blocks.findIndex(nb => nb.id === id);
          if (ni >= 0) { col.blocks.splice(ni, 1); break; }
        }
      }
    }
  }
  if (selectedBlockId.value === id) selectedBlockId.value = null;
  saveHistory();
}

function updateContent(id, value) {
  const block = findBlockById(id);
  if (block) block.content = value;
}

// Text selection and focus
function onTextBlur(block, event) {
  focusedTextId.value = null;
  block.content = event.target.innerText || '';
  saveHistory();
}

function getListHtml(content) {
  const lines = (content || '').split('\n');
  if (lines.length === 0 || (lines.length === 1 && !lines[0])) {
    return '<li>&nbsp;</li>';
  }
  return lines.map(line => `<li>${line || '&nbsp;'}</li>`).join('');
}

function onListBlur(block, event) {
  focusedTextId.value = null;
  const lis = event.target.querySelectorAll('li');
  if (lis.length > 0) {
    block.content = Array.from(lis).map(li => {
      let text = li.innerText || li.textContent || '';
      if (text === '\n') text = '';
      return text;
    }).join('\n');
  } else {
    block.content = event.target.innerText || event.target.textContent || '';
  }
  saveHistory();
}

function onListInput(block, event) {
  const lis = event.target.querySelectorAll('li');
  if (lis.length > 0) {
    const lines = Array.from(lis).map(li => {
      let text = li.innerText || li.textContent || '';
      if (text === '\n') text = '';
      return text;
    });
    block.content = lines.join('\n');
  } else {
    block.content = event.target.innerText || event.target.textContent || '';
  }
}

function focusText(id) {
  focusedTextId.value = id;
  const block = findBlockById(id);
  if (block) {
    nextTick(() => {
      const el = document.querySelector(`.eb-text-editable-${id}`);
      if (el) {
        if (block.listType === 'bullet' || block.listType === 'numbered') {
          el.innerHTML = getListHtml(block.content);
        } else {
          el.innerText = block.content || '';
        }
        el.focus();
        // Move cursor to end
        const range = document.createRange();
        const sel = window.getSelection();
        range.selectNodeContents(el);
        range.collapse(false);
        sel.removeAllRanges();
        sel.addRange(range);
      }
    });
  }
}

function onColumnBlockAdded(col) {
  if (col.blocks.length > 0) {
    selectedBlockId.value = col.blocks[col.blocks.length - 1].id;
  }
  saveHistory();
}

function onBlockAdded() {
  if (localBlocks.value.length > 0) {
    const last = localBlocks.value[localBlocks.value.length - 1];
    selectedBlockId.value = last.id;
  }
  saveHistory();
}

function handleDrop(e) {
  // VueDraggable handles drop.
}

// HTML editor expand modal state
const showHtmlEditor = ref(false);
const htmlEditorBlock = ref(null);
const modalCodeLineRef = ref(null);
const modalCodeEditorRef = ref(null);

function openHtmlEditor(block) {
  htmlEditorBlock.value = block;
  showHtmlEditor.value = true;
}

function htmlLineCount(html) {
  const lines = (html || '').split('\n').length;
  return Array.from({ length: Math.max(lines, 1) }, (_, i) => i + 1);
}

function syncModalCodeScroll(e) {
  if (modalCodeLineRef.value) modalCodeLineRef.value.scrollTop = e.target.scrollTop;
}

// Test email modal state
const showTestEmailModal = ref(false);
const testEmailAddress = ref('');
const testEmailSending = ref(false);
const testEmailError = ref('');
const testEmailSuccess = ref('');
const testEmailInputRef = ref(null);

function openTestEmailModal() {
  testEmailError.value = '';
  testEmailSuccess.value = '';
  showTestEmailModal.value = true;
  nextTick(() => testEmailInputRef.value?.focus());
}

function closeTestModal() {
  showTestEmailModal.value = false;
  testEmailError.value = '';
  testEmailSuccess.value = '';
}

async function doSendTestEmail() {
  testEmailError.value = '';
  testEmailSuccess.value = '';

  const email = testEmailAddress.value.trim();
  if (!email) {
    testEmailError.value = 'Please enter a recipient email address.';
    return;
  }

  testEmailSending.value = true;
  try {
    await window.axios.post(route('campaigns.send-test', props.campaignId), { email, blocks: localBlocks.value });
    testEmailSuccess.value = `Test email sent to ${email}`;
  } catch (err) {
    testEmailError.value = err.response?.data?.message ?? 'Failed to send test email. Please check your mail settings.';
  } finally {
    testEmailSending.value = false;
  }
}

// Share state down to child elements
provide('editorState', {
  blocks: localBlocks,
  selectedBlockId,
  selectedBlock,
  focusedTextId,
  previewDevice,
  isDragging,
  showHtmlEditor,
  htmlEditorBlock,
  showTestEmailModal,
  testEmailAddress,
  testEmailSending,
  testEmailError,
  testEmailSuccess,
  canUndo,
  canRedo,
  selectBlock,
  duplicateBlock,
  deleteBlock,
  updateContent,
  focusText,
  onTextBlur,
  onListBlur,
  onListInput,
  onColumnBlockAdded,
  onBlockAdded,
  handleDrop,
  onDragStart,
  onDragEnd,
  undo,
  redo,
  clearCanvas,
  saveHistory,
  makeBlock,
  openHtmlEditor,
  openTestEmailModal,
  getListHtml
});

</script>

<style scoped>
.cw-composer-layout {
    display: flex;
    height: 100%;
    width: 100%;
    overflow: hidden;
    background: var(--bg-surface);
    min-height: 560px;

    @media (max-width: 1024px) {
        flex-direction: column;
        overflow-y: auto;
        height: auto;
    }
}

.cw-left-panel {
    width: 300px;
    flex-shrink: 0;
    background: var(--bg-surface);
    border-right: 1px solid var(--border-color);
    display: flex;
    flex-direction: column;
    height: 100%;
    overflow: hidden;

    @media (max-width: 1024px) {
        width: 100%;
        border-right: none;
        border-bottom: 1px solid var(--border-color);
        max-height: 380px;
        overflow-y: auto;
    }
}

.cw-canvas-pane {
    flex: 1;
    display: flex;
    flex-direction: column;
    height: 100%;
    overflow: hidden;
    min-width: 0;

    @media (max-width: 1024px) {
        height: auto;
        overflow: visible;
    }
}

.cw-canvas-wrap {
    flex: 1;
    overflow-y: auto;
    background: var(--bg-page);
    padding: 36px 56px 36px;
    display: flex;
    justify-content: center;
    align-items: flex-start;

    @media (max-width: 768px) {
        padding: 16px 12px;
    }
}

.cw-email-frame {
    width: 100%;
    max-width: 600px;
    background: var(--bg-surface);
    min-height: 200px;
    box-shadow: 0 2px 16px rgba(0,0,0,0.12);
    border-radius: 4px;
    transition: max-width 0.25s ease;
}

.cw-email-frame.is-mobile {
    max-width: 400px;
}
</style>
