<script setup>
import AdminLayout from "@/Layouts/AdminLayout.vue";
import { Head, Link, useForm, router, usePage } from "@inertiajs/vue3";
import { ref, watch, computed, onMounted, nextTick } from "vue";
import {
  ArrowLeftIcon,
  EyeIcon,
  SaveIcon,
  BoldIcon,
  ItalicIcon,
  UnderlineIcon,
  AlignLeftIcon,
  AlignCenterIcon,
  AlignRightIcon,
  ListIcon,
  ListOrderedIcon,
  ImageIcon,
  Maximize2Icon,
  CodeIcon,
  SendIcon,
  CopyIcon,
  DownloadIcon,
  Trash2Icon,
  FileTextIcon,
  SettingsIcon,
  UserIcon,
  BriefcaseIcon,
  FolderIcon,
  ActivityIcon,
  PlusCircleIcon,
} from "lucide-vue-next";
import { VueMonacoEditor } from "@guolao/vue-monaco-editor";
import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
} from "@/Components/ui/card";
import { Button } from "@/Components/ui/button";
import { Input } from "@/Components/ui/input";
import { Label } from "@/Components/ui/label";
import { Textarea } from "@/Components/ui/textarea";
import { Checkbox } from "@/Components/ui/checkbox";
import { Switch } from "@/Components/ui/switch";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/Components/ui/select";
import { Separator } from "@/Components/ui/separator";
import { Badge } from "@/Components/ui/badge";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogHeader,
  DialogTitle,
} from "@/Components/ui/dialog";
// Keep Quill CSS for nicer preview styling, but remove the Quill editor itself
import "quill/dist/quill.snow.css";

const props = defineProps({
  template: { type: Object, default: null },
  actions: { type: Array, default: () => [] },
});

const form = useForm({
  name: props.template?.name ?? "",
  key: props.template?.key ?? "",
  subject_template: props.template?.subject_template ?? "",
  html_template: props.template?.html_template ?? "",
  text_template: props.template?.text_template ?? "",
  entity_types: props.template?.entity_types ?? ["client", "contract"],
  allow_attachments: props.template?.allow_attachments ?? false,
  active: props.template?.active ?? true,
  client: props.template?.client ?? false,
  action_id: props.template?.action_id ?? null,
  decision_id: props.template?.decision_id ?? null,
});

const preview = ref({ subject: "", html: "", text: "" });
const finalHtml = ref("");
const finalAttachments = ref([]);
const showFinal = ref(false);
const finalEmbedMode = ref("base64"); // 'base64' (default) or 'hosted' for diagnostics
const sendEmbedMode = ref("base64"); // embed mode for Send Test action
const isLocalHost = computed(() => {
  if (typeof window === "undefined") return false;
  const h = window.location.hostname || "";
  return /^(localhost|127\.0\.0\.1)$/i.test(h);
});
// If preview.html is empty (e.g., because only head/styles were changed), show the body-safe content from the current source as a fallback.
const previewHtml = computed(() => {
  const html = preview.value?.html || "";
  if (html.trim() !== "") {
    return containsDocScaffold(html) ? extractBody(html) : html;
  }
  // Fallback to local content if server preview didn't provide HTML
  // We only use the advanced editor now, so just show the <body> content when available
  return extractBody(form.html_template || "");
});
const docsRaw = ref(props.template?.documents ? [...props.template.documents] : []);
const docs = computed(() =>
  (docsRaw.value ?? []).map((d) => ({
    ...d,
    url: d?.path ? `/storage/${d.path}` : null,
  }))
);
function updateLocalDoc(documentId, path, name = null, size = null) {
  if (!documentId) return;
  const idx = docsRaw.value.findIndex((d) => d.id === documentId);
  if (idx !== -1) {
    const next = { ...docsRaw.value[idx] };
    next.path = path ?? next.path;
    if (name) next.name = name;
    if (size != null) next.size = size;
    docsRaw.value.splice(idx, 1, next);
  }
}
async function removeLocalDoc(documentId) {
  const idx = docsRaw.value.findIndex((d) => d.id === documentId);
  if (idx !== -1) {
    docsRaw.value.splice(idx, 1);
  }
}
function formatSize(bytes) {
  if (!bytes && bytes !== 0) return "";
  const kb = bytes / 1024;
  if (kb < 1024) return `${kb.toFixed(1)} KB`;
  const mb = kb / 1024;
  return `${mb.toFixed(2)} MB`;
}
const debounce = (fn, ms = 500) => {
  let t;
  return (...args) => {
    clearTimeout(t);
    t = setTimeout(() => fn(...args), ms);
  };
};

// Core preview fetcher; mirrors values when creating (no ID), calls backend when editing
const fetchPreview = () => {
  if (!props.template?.id) {
    preview.value = {
      subject: form.subject_template,
      html: form.html_template,
      text: form.text_template,
    };
    return;
  }
  window.axios
    .post(route("admin.email-templates.preview", props.template.id), {
      subject: form.subject_template,
      // Always send full HTML so head/styles can be respected and inlined server-side
      html: form.html_template,
      text: form.text_template,
      activity_id: sample.value.activity_id || undefined,
      client_id: sample.value.client_id || undefined,
      case_id: sample.value.case_id || undefined,
      contract_id: sample.value.contract_id || undefined,
      extra: safeParseExtra(sample.value.extra),
    })
    .then((r) => {
      preview.value = r.data;
    });
};

const doPreview = debounce(fetchPreview, 400);

watch(
  () => [form.subject_template, form.html_template, form.text_template],
  () => doPreview(),
  { deep: true, immediate: true }
);

function submit() {
  if (props.template?.id) {
    form.put(route("admin.email-templates.update", props.template.id));
  } else {
    form.post(route("admin.email-templates.store"));
  }
}

async function fetchFinalHtml() {
  const { data } = await window.axios.post(
    route("admin.email-templates.render-final", props.template.id),
    {
      subject: form.subject_template,
      html: form.html_template,
      text: form.text_template,
      activity_id: sample.value.activity_id || undefined,
      client_id: sample.value.client_id || undefined,
      case_id: sample.value.case_id || undefined,
      contract_id: sample.value.contract_id || undefined,
      extra: safeParseExtra(sample.value.extra),
      embed: finalEmbedMode.value,
    }
  );
  finalHtml.value = data?.html || "";
  finalAttachments.value = Array.isArray(data?.attachments) ? data.attachments : [];
}

async function openFinalHtmlDialog() {
  if (!props.template?.id) {
    alert("Najprej shranite predlogo.");
    return;
  }
  try {
    await fetchFinalHtml();
    showFinal.value = true;
  } catch (e) {
    console.error("Failed to render final HTML", e);
    alert("Neuspešen prikaz končne HTML vsebine.");
  }
}

function copyFinalHtml() {
  try {
    navigator.clipboard.writeText(finalHtml.value || "");
    alert("Končni HTML je kopiran v odložišče.");
  } catch (e) {
    console.warn("Clipboard write failed", e);
  }
}

function downloadFinalHtml() {
  const blob = new Blob([finalHtml.value || ""], { type: "text/html;charset=utf-8" });
  const url = URL.createObjectURL(blob);
  const a = document.createElement("a");
  a.href = url;
  a.download = `${(form.name || "email-template").replace(/[^a-z0-9-_]+/gi, "-")}.html`;
  document.body.appendChild(a);
  a.click();
  document.body.removeChild(a);
  URL.revokeObjectURL(url);
}

onMounted(() => {
  // Show something instantly and request preview immediately
  preview.value = {
    subject: form.subject_template,
    html: form.html_template,
    text: form.text_template,
  };
  // Populate cascading selects immediately so the Client dropdown isn't empty
  loadClients();
  fetchPreview();
  // Advanced editor is the only mode
  activeField.value = "html";
  initIframeEditor();
});

// --- Variable insertion and sample entity selection ---
const subjectRef = ref(null);
const htmlSourceRef = ref(null);
const monacoEditor = ref(null);
const textRef = ref(null);
const activeField = ref("html"); // default to HTML for variable inserts
// Raw HTML editor toggle (full-document source)
const rawMode = ref(false);
// Advanced full-document editor that renders styles from <head>
const advancedMode = ref(true);
const iframeRef = ref(null);
let iframeSyncing = false;
const selectedImageSrc = ref("");
// Preview iframe ref (to render preview HTML with <head> styles applied)
const previewIframeRef = ref(null);

// Detect and handle full-document HTML so Quill doesn't wipe content
function containsDocScaffold(html) {
  if (!html || typeof html !== "string") return false;
  const h = html.toLowerCase();
  return (
    h.includes("<!doctype") ||
    h.includes("<html") ||
    h.includes("<head") ||
    h.includes("<body") ||
    h.includes("<style")
  );
}

function extractBody(html) {
  const m = /<body[^>]*>([\s\S]*?)<\/body>/i.exec(html);
  return m ? m[1] : html;
}

// Retained for compatibility, but no longer used actively
function stripDocScaffold(html) {
  return extractBody(html || "");
}

// Replace only the inner content of <body>...</body> in a full document
function replaceBody(htmlDoc, newBody) {
  if (!htmlDoc || typeof htmlDoc !== "string") return newBody || "";
  const hasBody = /<body[^>]*>[\s\S]*?<\/body>/i.test(htmlDoc);
  if (!hasBody) {
    return newBody || "";
  }
  return htmlDoc.replace(/(<body[^>]*>)[\s\S]*?(<\/body>)/i, `$1${newBody || ""}$2`);
}

// Quill/source mode removed

// Advanced mode is always on

// When HTML changes externally, reflect it into iframe (unless we're the ones syncing)
watch(
  () => form.html_template,
  async () => {
    if (iframeSyncing) return;
    await nextTick();
    writeIframeDocument();
  }
);

// Re-initialize iframe editor when switching back from Raw HTML
watch(
  () => rawMode.value,
  async (on) => {
    if (!on) {
      await nextTick();
      initIframeEditor();
    }
  }
);

function ensureFullDoc(html) {
  if (!html)
    return '<!doctype html><html><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /></head><body></body></html>';
  if (/<html[\s\S]*<\/html>/i.test(html)) return html;
  return `<!doctype html><html><head><meta charset=\"utf-8\" /><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" /></head><body>${html}</body></html>`;
}

function writeIframeDocument() {
  const iframe = iframeRef.value;
  if (!iframe) return;
  const doc = iframe.contentDocument;
  if (!doc) return;
  const html = ensureFullDoc(form.html_template || "");
  doc.open();
  doc.write(html);
  doc.close();
  try {
    doc.body.setAttribute("spellcheck", "false");
  } catch {}
}

function initIframeEditor() {
  writeIframeDocument();
  const iframe = iframeRef.value;
  if (!iframe) return;
  const doc = iframe.contentDocument;
  if (!doc) return;
  try {
    doc.designMode = "on";
  } catch {}
  // track selected image src on click
  doc.addEventListener("click", (e) => {
    const t = e.target;
    if (t && t.tagName === "IMG") {
      selectedImageSrc.value = t.getAttribute("src") || "";
    } else {
      selectedImageSrc.value = "";
    }
    // Ensure variable buttons target HTML editor
    activeField.value = "html";
  });
  const handler = debounce(() => {
    if (!advancedMode.value) return;
    try {
      iframeSyncing = true;
      const full = doc.documentElement.outerHTML;
      form.html_template = full;
    } finally {
      iframeSyncing = false;
    }
  }, 250);
  doc.addEventListener("input", handler);
  doc.addEventListener("keyup", handler);
}

function writePreviewDocument() {
  const iframe = previewIframeRef.value;
  if (!iframe) return;
  const doc = iframe.contentDocument;
  if (!doc) return;
  const html = ensureFullDoc(preview.value?.html || form.html_template || "");
  doc.open();
  doc.write(html);
  doc.close();
}

function iframeExec(command, value = null) {
  const iframe = iframeRef.value;
  if (!iframe) return;
  const doc = iframe.contentDocument;
  if (!doc) return;
  try {
    doc.body.focus();
  } catch {}
  try {
    doc.execCommand(command, false, value);
  } catch (e) {
    console.warn("execCommand failed", command, e);
  }
}

async function iframeInsertImage() {
  const input = document.createElement("input");
  input.type = "file";
  input.accept = "image/*";
  input.onchange = async () => {
    const file = input.files?.[0];
    if (!file) return;
    const data = new FormData();
    data.append("file", file);
    try {
      const { data: res } = await window.axios.post(
        route("admin.email-templates.upload-image"),
        data,
        { headers: { "Content-Type": "multipart/form-data" } }
      );
      const url = res?.url;
      const documentId = res?.document_id;
      if (url) {
        iframeExec("insertImage", url);
      }
    } catch (e) {
      console.error("Image upload failed", e);
    }
  };
  input.click();
}

async function iframeReplaceSelectedImage() {
  if (!props.template?.id) {
    alert("Najprej shranite predlogo, nato zamenjajte sliko.");
    return;
  }
  if (!selectedImageSrc.value) {
    alert("Najprej kliknite na sliko v dokumentu, ki jo želite zamenjati.");
    return;
  }
  const input = document.createElement("input");
  input.type = "file";
  input.accept = "image/*";
  input.onchange = async () => {
    const file = input.files?.[0];
    if (!file) return;
    const data = new FormData();
    data.append("file", file);
    data.append("current_src", selectedImageSrc.value);
    try {
      const { data: res } = await window.axios.post(
        route("admin.email-templates.replace-image", props.template.id),
        data,
        { headers: { "Content-Type": "multipart/form-data" } }
      );
      const url = res?.url;
      if (url) {
        // Replace src in the iframe document
        const iframe = iframeRef.value;
        const doc = iframe?.contentDocument;
        if (doc) {
          // Update only the selected image if possible, else do a global replace
          const imgs = Array.from(doc.querySelectorAll("img"));
          const img = imgs.find(
            (im) => (im.getAttribute("src") || "") === selectedImageSrc.value
          );
          if (img) {
            img.setAttribute("src", url);
          } else {
            doc.body.innerHTML = doc.body.innerHTML.replaceAll(
              selectedImageSrc.value,
              url
            );
          }
          // Sync back to the model
          iframeSyncing = true;
          form.html_template = doc.documentElement.outerHTML;
          iframeSyncing = false;
          selectedImageSrc.value = url;
        }
        if (documentId && res?.path) {
          updateLocalDoc(documentId, res.path, null, res?.size ?? null);
        }
      }
    } catch (e) {
      console.error("Replace image failed", e);
    }
  };
  input.click();
}

function setActive(field) {
  activeField.value = field;
}

async function deleteAttachedImage(doc) {
  if (!props.template?.id) return;
  if (!doc?.id) return;
  const confirmed = window.confirm(
    "Odstranim to sliko iz predloge? Datoteka bo izbrisana."
  );
  if (!confirmed) return;
  try {
    await window.axios.delete(
      route("admin.email-templates.images.delete", {
        emailTemplate: props.template.id,
        document: doc.id,
      })
    );
    await removeLocalDoc(doc.id);
    // After deletion, scrub or replace references in current HTML
    tryReplaceOrRemoveDeletedImageReferences(doc);
  } catch (e) {
    console.error("Delete image failed", e);
    alert("Brisanje slike ni uspelo.");
  }
}

function tryReplaceOrRemoveDeletedImageReferences(deletedDoc) {
  const deletedPath = deletedDoc?.path || "";
  if (!deletedPath) return;
  const targetRel = "/storage/" + deletedPath.replace(/^\/+/, "");

  // Helper: does an <img> src match the deleted doc path (relative or absolute)?
  const srcMatches = (src) => {
    if (!src) return false;
    try {
      // Absolute URL: compare its pathname
      const u = new URL(src, window.location.origin);
      return u.pathname === targetRel;
    } catch {
      // Relative path string
      if (src === targetRel) return true;
      // Also accept raw disk path variant (unlikely in HTML)
      if (src.replace(/^\/+/, "") === targetRel.replace(/^\/+/, "")) return true;
      return false;
    }
  };

  // Choose a replacement doc based on <img alt> when possible; else, if only one image remains, use that.
  const pickReplacement = (altText) => {
    const remaining = (docsRaw.value || []).slice();
    if (!remaining.length) return null;
    const norm = (s) => (s || "").toString().toLowerCase();
    const stem = (name) =>
      (name || "")
        .toString()
        .toLowerCase()
        .replace(/\.[^.]+$/, "");
    const simplify = (s) => norm(s).replace(/[^a-z0-9]+/g, "");

    if (altText) {
      const altKey = simplify(altText);
      // exact name stem match (name, file_name, original_name)
      const exact = remaining.find((d) => {
        const candidates = [d.name, d.file_name, d.original_name].map(stem);
        return candidates.some(
          (c) => simplify(c) === altKey || norm(c) === norm(altText)
        );
      });
      if (exact) return exact;
      // relaxed contains on simplified stems
      const relaxed = remaining.find((d) => {
        const candidates = [d.name, d.file_name, d.original_name].map(stem).map(simplify);
        return candidates.some((c) => c && altKey && c.includes(altKey));
      });
      if (relaxed) return relaxed;
    }
    if (remaining.length === 1) return remaining[0];
    return null;
  };

  const replaceInDocument = (docEl) => {
    if (!docEl) return false;
    let changed = false;
    const imgs = Array.from(docEl.querySelectorAll("img"));
    imgs.forEach((img) => {
      const src = img.getAttribute("src");
      if (!srcMatches(src)) return;
      const alt = img.getAttribute("alt") || "";
      const replacement = pickReplacement(alt);
      if (replacement && replacement.path) {
        img.setAttribute("src", "/storage/" + replacement.path.replace(/^\/+/, ""));
      } else {
        // No replacement – remove the image tag entirely
        img.parentNode && img.parentNode.removeChild(img);
      }
      changed = true;
    });
    return changed;
  };

  if (!rawMode.value) {
    // Advanced iframe editor
    const iframe = iframeRef.value;
    const doc = iframe?.contentDocument;
    if (doc && doc.documentElement) {
      const changed = replaceInDocument(doc);
      if (changed) {
        iframeSyncing = true;
        form.html_template = doc.documentElement.outerHTML;
        iframeSyncing = false;
      }
    }
  } else {
    // Raw mode: parse and mutate via DOMParser
    const html = form.html_template || "";
    const full = ensureFullDoc(html);
    const parser = new DOMParser();
    const parsed = parser.parseFromString(full, "text/html");
    const changed = replaceInDocument(parsed);
    if (changed) {
      form.html_template = parsed.documentElement.outerHTML;
    }
  }
}

function insertAtCursor(el, value, modelGetter, modelSetter) {
  if (!el) return;
  const start = el.selectionStart ?? 0;
  const end = el.selectionEnd ?? 0;
  const current = modelGetter();
  const next = current.slice(0, start) + value + current.slice(end);
  modelSetter(next);
  // restore caret after inserted value
  requestAnimationFrame(() => {
    el.focus();
    const pos = start + value.length;
    try {
      el.setSelectionRange(pos, pos);
    } catch {}
  });
}

function insertPlaceholder(token) {
  const content = `{{ ${token} }}`;
  if (activeField.value === "subject" && subjectRef.value) {
    insertAtCursor(
      subjectRef.value,
      content,
      () => form.subject_template,
      (v) => (form.subject_template = v)
    );
  } else if (activeField.value === "html") {
    // If editing raw source, insert at caret into Monaco editor
    if (rawMode.value && monacoEditor.value) {
      const editor = monacoEditor.value;
      const position = editor.getPosition();
      const range = {
        startLineNumber: position.lineNumber,
        startColumn: position.column,
        endLineNumber: position.lineNumber,
        endColumn: position.column,
      };
      editor.executeEdits("", [
        {
          range: range,
          text: content,
          forceMoveMarkers: true,
        },
      ]);
      editor.focus();
      return;
    }
    // Otherwise, insert into the iframe at caret position
    // Insert into the iframe at caret position without rewriting the document
    const iframe = iframeRef.value;
    const doc = iframe?.contentDocument;
    if (doc) {
      const sel = doc.getSelection();
      if (sel && sel.rangeCount > 0) {
        const range = sel.getRangeAt(0);
        range.deleteContents();
        const node = doc.createTextNode(content);
        range.insertNode(node);
        // place caret after inserted node
        range.setStartAfter(node);
        range.collapse(true);
        sel.removeAllRanges();
        sel.addRange(range);
      } else {
        doc.body.appendChild(doc.createTextNode(content));
      }
      // Sync back to model
      iframeSyncing = true;
      form.html_template = doc.documentElement.outerHTML;
      iframeSyncing = false;
    } else {
      // last resort
      form.html_template = (form.html_template || "") + content;
    }
  } else if (activeField.value === "text" && textRef.value) {
    insertAtCursor(
      textRef.value,
      content,
      () => form.text_template,
      (v) => (form.text_template = v)
    );
  }
}

// Quill handlers removed; image actions handled by iframe toolbar

const placeholderGroups = computed(() => {
  const groups = [];
  const want = new Set(form.entity_types || []);
  const add = (key, label, tokens) => groups.push({ key, label, tokens });
  if (want.has("person")) {
    add("person", "Person", [
      "person.first_name",
      "person.last_name",
      "person.full_name",
      "person.email",
      "person.phone",
    ]);
  }
  if (want.has("client")) {
    add("client", "Client", ["client.id", "client.uuid", "client.person.full_name"]);
  }
  if (want.has("client_case")) {
    add("case", "Case", [
      "case.id",
      "case.uuid",
      "case.reference",
      "case.person.full_name",
    ]);
  }
  if (want.has("contract")) {
    add("contract", "Contract", [
      "contract.id",
      "contract.uuid",
      "contract.reference",
      "contract.account.balance_amount",
      "contract.account.initial_amount",
      "contract.meta.some_key",
    ]);
  }
  // Activity placeholders (always useful if template references workflow actions/decisions)
  add("activity", "Activity", [
    "activity.id",
    "activity.note",
    "activity.due_date",
    "activity.amount",
    "activity.action.name",
    "activity.decision.name",
  ]);
  // Extra is always useful for ad-hoc data
  add("extra", "Extra", ["extra.some_key"]);
  // Profile signature tokens (resolved from the active mail profile at send time)
  add("profile", "Profil / Podpis", [
    "profile.signature.ime",
    "profile.signature.naziv",
    "profile.signature.telefon",
    "profile.signature.email",
  ]);
  return groups;
});

// Sample entity selection for preview
const sample = ref({
  client_id: "",
  case_id: "",
  contract_id: "",
  activity_id: "",
  extra: "",
});

// Cascading select options
const clients = ref([]);
const cases = ref([]);
const contracts = ref([]);

async function loadClients() {
  const { data } = await window.axios.get(route("admin.email-templates.data.clients"));
  clients.value = data;
}
async function loadCases(clientId) {
  if (!clientId) {
    cases.value = [];
    return;
  }
  const { data } = await window.axios.get(
    route("admin.email-templates.data.cases", clientId)
  );
  cases.value = data;
}
async function loadContracts(caseId) {
  if (!caseId) {
    contracts.value = [];
    return;
  }
  const { data } = await window.axios.get(
    route("admin.email-templates.data.contracts", caseId)
  );
  contracts.value = data;
}

watch(
  () => sample.value.client_id,
  (v) => {
    sample.value.case_id = "";
    sample.value.contract_id = "";
    loadCases(v);
    doPreview();
  }
);
watch(
  () => sample.value.case_id,
  (v) => {
    sample.value.contract_id = "";
    loadContracts(v);
    doPreview();
  }
);
watch(
  () => sample.value.contract_id,
  () => doPreview()
);
watch(
  () => sample.value.activity_id,
  () => doPreview()
);

function applySample() {
  fetchPreview();
  loadClients();
}

function safeParseExtra(input) {
  if (!input || typeof input !== "string") return undefined;
  try {
    const parsed = JSON.parse(input);
    return typeof parsed === "object" && parsed !== null ? parsed : undefined;
  } catch {
    return undefined;
  }
}

function sendTest() {
  if (!props.template?.id) {
    alert("Najprej shranite predlogo, nato pošljite test.");
    return;
  }
  if (!sample.value.to) {
    alert("Vnesite ciljni email naslov.");
    return;
  }
  const payload = {
    subject: form.subject_template,
    html: form.html_template,
    text: form.text_template,
    activity_id: sample.value.activity_id || undefined,
    client_id: sample.value.client_id || undefined,
    person_id: sample.value.person_id || undefined,
    case_id: sample.value.case_id || undefined,
    contract_id: sample.value.contract_id || undefined,
    extra: safeParseExtra(sample.value.extra),
    to: sample.value.to,
    embed: sendEmbedMode.value,
  };

  // Small helper for simple notifications without reloading
  const notify = (message, _type = "info") => {
    if (!message) {
      return;
    }
    // Replace with your app's toast if available
    alert(message);
  };

  router.post(route("admin.email-templates.send-test", props.template.id), payload, {
    preserveScroll: true,
    preserveState: true,
    onSuccess: () => {
      try {
        const page = usePage();
        const flash = page?.props?.flash ?? {};
        if (flash.success) {
          notify(flash.success, "success");
          return;
        }
        if (flash.error) {
          notify(flash.error, "error");
          return;
        }
      } catch {}
      notify("Testni e-poštni naslov je bil poslan.", "success");
      // Slight UX tweak: controller now queues the email
      // (flash success message from backend reflects 'queued')
    },
    onError: () => {
      // Validation errors trigger onError; controller may also set flash('error') on redirect
      try {
        const page = usePage();
        const flash = page?.props?.flash ?? {};
        if (flash.error) {
          notify(flash.error, "error");
          return;
        }
      } catch {}
      notify(
        "Pri pošiljanju testnega e-poštnega sporočila je prišlo do napake.",
        "error"
      );
    },
  });
}

// Keep preview iframe in sync with server-rendered preview
watch(
  () => preview.value?.html,
  async () => {
    await nextTick();
    writePreviewDocument();
  }
);
</script>

<template>
  <AdminLayout :title="props.template ? 'Uredi predlogo' : 'Nova predloga'">
    <Head :title="props.template ? 'Uredi predlogo' : 'Nova predloga'" />

    <Card class="mb-6">
      <CardHeader>
        <div class="flex items-start justify-between">
          <div class="flex items-start gap-3">
            <div
              class="inline-flex items-center justify-center h-10 w-10 rounded-lg bg-primary/10 text-primary"
            >
              <FileTextIcon class="h-5 w-5" />
            </div>
            <div>
              <CardTitle>{{
                props.template ? "Uredi predlogo" : "Nova predloga"
              }}</CardTitle>
              <CardDescription> Konfiguracija e-poštne predloge </CardDescription>
            </div>
          </div>
          <div class="flex items-center gap-2">
            <Button variant="outline" size="sm" as-child>
              <Link :href="route('admin.email-templates.index')">
                <ArrowLeftIcon class="h-4 w-4" />
                Nazaj
              </Link>
            </Button>
            <Button @click="submit" :disabled="form.processing" size="sm">
              <SaveIcon class="h-4 w-4" />
              Shrani
            </Button>
          </div>
        </div>
      </CardHeader>
    </Card>

    <div class="space-y-6">
      <!-- Editor card -->
      <Card>
        <CardHeader>
          <div class="flex items-center gap-2">
            <SettingsIcon class="h-5 w-5" />
            <CardTitle class="text-base">Osnovna nastavitve</CardTitle>
          </div>
        </CardHeader>
        <CardContent class="space-y-4">
          <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
            <div class="space-y-2">
              <Label for="name">Ime</Label>
              <Input
                id="name"
                v-model="form.name"
                :class="{ 'border-destructive': form.errors.name }"
              />
              <span v-if="form.errors.name" class="text-sm text-destructive">{{
                form.errors.name
              }}</span>
            </div>
            <div class="space-y-2">
              <Label for="key">Ključ</Label>
              <Input
                id="key"
                v-model="form.key"
                :class="{ 'border-destructive': form.errors.key }"
              />
              <span v-if="form.errors.key" class="text-sm text-destructive">{{
                form.errors.key
              }}</span>
            </div>
          </div>

          <div class="space-y-2">
            <Label for="entity_types">Tipi entitet</Label>
            <div class="flex flex-wrap gap-3">
              <div
                v-for="et in ['person', 'client', 'client_case', 'contract']"
                :key="et"
                class="flex items-center gap-2"
              >
                <Checkbox
                  :id="'entity-' + et"
                  :default-value="form.entity_types.includes(et)"
                  @update:model-value="
                    (val) => {
                      if (val) {
                        if (!form.entity_types.includes(et)) form.entity_types.push(et);
                      } else {
                        form.entity_types = form.entity_types.filter((x) => x !== et);
                      }
                    }
                  "
                />
                <Label :for="'entity-' + et" class="font-normal cursor-pointer">
                  {{ et }}
                </Label>
              </div>
            </div>
          </div>

          <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
            <div class="flex items-center gap-2">
              <Switch
                id="allow_attachments"
                :default-value="form.allow_attachments"
                @update:model-value="(val) => (form.allow_attachments = val)"
              />
              <Label for="allow_attachments" class="font-normal cursor-pointer"
                >Allow attachments</Label
              >
            </div>
            <div class="flex items-center gap-2">
              <Switch
                id="active"
                :default-value="form.active"
                @update:model-value="(val) => (form.active = val)"
              />
              <Label for="active" class="font-normal cursor-pointer">Aktivno</Label>
            </div>
            <div class="flex items-center gap-2">
              <Switch
                id="client"
                :default-value="form.client"
                @update:model-value="(val) => (form.client = val)"
              />
              <Label for="client" class="font-normal cursor-pointer">Samo za stranke</Label>
            </div>
          </div>

          <!-- Activity after send: action + decision -->
          <div>
            <Label class="mb-2 block">Aktivnost po pošiljanju</Label>
            <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
              <div class="space-y-2">
                <Label for="action_id">Akcija</Label>
                <Select v-model="form.action_id" @update:model-value="(val) => { form.action_id = val; form.decision_id = null; }">
                  <SelectTrigger id="action_id">
                    <SelectValue placeholder="Brez" />
                  </SelectTrigger>
                  <SelectContent>
                    <SelectItem :value="null">Brez</SelectItem>
                    <SelectItem v-for="a in props.actions" :key="a.id" :value="a.id">{{ a.name }}</SelectItem>
                  </SelectContent>
                </Select>
              </div>
              <div class="space-y-2">
                <Label for="decision_id">Odločitev</Label>
                <Select v-model="form.decision_id" :disabled="!form.action_id">
                  <SelectTrigger id="decision_id">
                    <SelectValue placeholder="Brez" />
                  </SelectTrigger>
                  <SelectContent>
                    <SelectItem :value="null">Brez</SelectItem>
                    <SelectItem
                      v-for="d in props.actions?.find((x) => x.id === form.action_id)?.decisions || []"
                      :key="d.id"
                      :value="d.id"
                    >{{ d.name }}</SelectItem>
                  </SelectContent>
                </Select>
              </div>
            </div>
          </div>

          <Separator />

          <div class="space-y-2">
            <Label for="subject">Zadeva</Label>
            <Input
              id="subject"
              ref="subjectRef"
              v-model="form.subject_template"
              @focus="setActive('subject')"
              :class="{ 'border-destructive': form.errors.subject_template }"
            />
            <span v-if="form.errors.subject_template" class="text-sm text-destructive">{{
              form.errors.subject_template
            }}</span>
          </div>

          <Separator />

          <div class="space-y-2">
            <div class="flex items-center justify-between">
              <Label>HTML vsebina</Label>
              <Button size="sm" variant="outline" @click="rawMode = !rawMode">
                <CodeIcon class="h-4 w-4 mr-2" />
                {{ rawMode ? "Vizualni urednik" : "HTML izvorna koda" }}
              </Button>
            </div>

            <!-- Raw HTML source mode with Monaco Editor -->
            <div
              v-if="rawMode"
              class="border rounded-md overflow-hidden"
              style="min-height: 600px"
            >
              <VueMonacoEditor
                v-model:value="form.html_template"
                language="html"
                :options="{
                  theme: 'vs-dark',
                  minimap: { enabled: false },
                  fontSize: 16,
                  lineHeight: 24,
                  lineNumbers: 'on',
                  wordWrap: 'on',
                  automaticLayout: true,
                  scrollBeyondLastLine: false,
                  formatOnPaste: true,
                  formatOnType: true,
                  padding: { top: 16, bottom: 16 },
                }"
                height="600px"
                @mount="
                  (editor) => {
                    monacoEditor = editor;
                    setActive('html');
                  }
                "
              />
            </div>

            <!-- Visual iframe editor -->
            <div v-else class="space-y-2">
              <div
                class="flex flex-wrap items-center gap-1 p-2 bg-muted rounded-md border"
              >
                <Button
                  size="sm"
                  variant="ghost"
                  @click="iframeExec('bold')"
                  title="Bold"
                >
                  <BoldIcon class="h-4 w-4" />
                </Button>
                <Button
                  size="sm"
                  variant="ghost"
                  @click="iframeExec('italic')"
                  title="Italic"
                >
                  <ItalicIcon class="h-4 w-4" />
                </Button>
                <Button
                  size="sm"
                  variant="ghost"
                  @click="iframeExec('underline')"
                  title="Underline"
                >
                  <UnderlineIcon class="h-4 w-4" />
                </Button>
                <Separator orientation="vertical" class="h-6" />
                <Button
                  size="sm"
                  variant="ghost"
                  @click="iframeExec('justifyLeft')"
                  title="Align Left"
                >
                  <AlignLeftIcon class="h-4 w-4" />
                </Button>
                <Button
                  size="sm"
                  variant="ghost"
                  @click="iframeExec('justifyCenter')"
                  title="Align Center"
                >
                  <AlignCenterIcon class="h-4 w-4" />
                </Button>
                <Button
                  size="sm"
                  variant="ghost"
                  @click="iframeExec('justifyRight')"
                  title="Align Right"
                >
                  <AlignRightIcon class="h-4 w-4" />
                </Button>
                <Separator orientation="vertical" class="h-6" />
                <Button
                  size="sm"
                  variant="ghost"
                  @click="iframeExec('insertUnorderedList')"
                  title="Bullet List"
                >
                  <ListIcon class="h-4 w-4" />
                </Button>
                <Button
                  size="sm"
                  variant="ghost"
                  @click="iframeExec('insertOrderedList')"
                  title="Numbered List"
                >
                  <ListOrderedIcon class="h-4 w-4" />
                </Button>
                <Separator orientation="vertical" class="h-6" />
                <Button
                  size="sm"
                  variant="ghost"
                  @click="iframeInsertImage"
                  title="Insert Image"
                >
                  <ImageIcon class="h-4 w-4" />
                </Button>
                <Button
                  v-if="selectedImageSrc"
                  size="sm"
                  variant="ghost"
                  @click="iframeReplaceSelectedImage"
                  title="Replace selected image"
                >
                  <ImageIcon class="h-4 w-4" />
                  <span class="ml-1 text-xs">Zamenjaj</span>
                </Button>
              </div>
              <iframe
                ref="iframeRef"
                class="w-full border rounded-md bg-white"
                style="min-height: 400px"
                @click="setActive('html')"
              />
            </div>
          </div>

          <div class="space-y-2">
            <Label for="text">Besedilna vsebina</Label>
            <Textarea
              id="text"
              ref="textRef"
              v-model="form.text_template"
              @focus="setActive('text')"
              rows="6"
            />
          </div>

          <Separator />

          <div class="space-y-3">
            <Label>Spremenljivke</Label>
            <div class="space-y-2">
              <div v-for="group in placeholderGroups" :key="group.key" class="space-y-2">
                <div class="text-sm font-medium text-muted-foreground">
                  {{ group.label }}
                </div>
                <div class="flex flex-wrap gap-2">
                  <Button
                    v-for="token in group.tokens"
                    :key="token"
                    size="sm"
                    variant="outline"
                    @click="insertPlaceholder(token)"
                    class="font-mono text-xs"
                  >
                    <PlusCircleIcon class="h-3 w-3 mr-1" />
                    {{ token }}
                  </Button>
                </div>
              </div>

              <!-- Special tokens -->
              <div class="space-y-2">
                <div class="text-sm font-medium text-muted-foreground">Posebni žetoni</div>
                <p class="text-xs text-muted-foreground">
                  <code class="font-mono">&#123;&#123; body_text &#125;&#125;</code> — pri pošiljanju ga nadomesti besedilo, ki ga vnese pošiljatelj.
                </p>
                <div class="flex flex-wrap gap-2">
                  <Button
                    size="sm"
                    variant="outline"
                    @click="insertPlaceholder('body_text')"
                    class="font-mono text-xs"
                  >
                    <PlusCircleIcon class="h-3 w-3 mr-1" />
                    body_text
                  </Button>
                </div>
              </div>
            </div>
          </div>
        </CardContent>
      </Card>

      <!-- Preview card -->
      <Card>
        <CardHeader>
          <div class="flex items-center gap-2">
            <EyeIcon class="h-5 w-5" />
            <CardTitle class="text-base">Predogled</CardTitle>
          </div>
        </CardHeader>
        <CardContent class="space-y-4">
          <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-3">
            <div class="space-y-2">
              <Label for="sample_client" class="flex items-center gap-1">
                <UserIcon class="h-3 w-3" />
                Stranka
              </Label>
              <Select v-model="sample.client_id">
                <SelectTrigger id="sample_client">
                  <SelectValue placeholder="Izberi stranko" />
                </SelectTrigger>
                <SelectContent>
                  <SelectItem :value="null">Brez</SelectItem>
                  <SelectItem v-for="c in clients" :key="c.id" :value="c.id">
                    {{ c.person?.first_name }} {{ c.person?.last_name }}
                  </SelectItem>
                </SelectContent>
              </Select>
            </div>

            <div class="space-y-2">
              <Label for="sample_case" class="flex items-center gap-1">
                <FolderIcon class="h-3 w-3" />
                Zadeva
              </Label>
              <Select v-model="sample.case_id" :disabled="!sample.client_id">
                <SelectTrigger id="sample_case">
                  <SelectValue placeholder="Izberi zadevo" />
                </SelectTrigger>
                <SelectContent>
                  <SelectItem :value="null">Brez</SelectItem>
                  <SelectItem v-for="cs in cases" :key="cs.id" :value="cs.id">
                    {{ cs.reference || cs.id }}
                  </SelectItem>
                </SelectContent>
              </Select>
            </div>

            <div class="space-y-2">
              <Label for="sample_contract" class="flex items-center gap-1">
                <BriefcaseIcon class="h-3 w-3" />
                Pogodba
              </Label>
              <Select v-model="sample.contract_id" :disabled="!sample.case_id">
                <SelectTrigger id="sample_contract">
                  <SelectValue placeholder="Izberi pogodbo" />
                </SelectTrigger>
                <SelectContent>
                  <SelectItem :value="null">Brez</SelectItem>
                  <SelectItem v-for="ct in contracts" :key="ct.id" :value="ct.id">
                    {{ ct.reference || ct.id }}
                  </SelectItem>
                </SelectContent>
              </Select>
            </div>

            <div class="space-y-2">
              <Label for="sample_activity" class="flex items-center gap-1">
                <ActivityIcon class="h-3 w-3" />
                Aktivnost
              </Label>
              <Input id="sample_activity" v-model="sample.activity_id" placeholder="ID" />
            </div>
          </div>

          <div class="space-y-2">
            <Label for="sample_extra">Dodatni podatki (JSON)</Label>
            <Textarea
              id="sample_extra"
              v-model="sample.extra"
              placeholder='{ "key": "value" }'
              rows="2"
              class="font-mono text-xs"
            />
          </div>

          <div class="flex items-center gap-2">
            <Button size="sm" @click="applySample">
              <EyeIcon class="h-4 w-4 mr-2" />
              Osveži predogled
            </Button>
            <Button
              v-if="props.template?.id"
              size="sm"
              variant="outline"
              @click="openFinalHtmlDialog"
            >
              <Maximize2Icon class="h-4 w-4 mr-2" />
              Končni HTML
            </Button>
          </div>

          <Separator />

          <div class="space-y-3">
            <div class="space-y-1">
              <Label class="text-sm">Zadeva</Label>
              <div class="text-sm p-2 bg-muted rounded">
                {{ preview.subject || "(prazno)" }}
              </div>
            </div>

            <div class="space-y-1">
              <Label class="text-sm">HTML</Label>
              <iframe
                ref="previewIframeRef"
                class="w-full border rounded-md bg-white"
                style="min-height: 320px"
              />
            </div>

            <div class="space-y-1">
              <Label class="text-sm">Besedilo</Label>
              <pre class="text-xs whitespace-pre-wrap bg-muted p-3 rounded-md">{{
                preview.text || "(prazno)"
              }}</pre>
            </div>
          </div>

          <Separator />

          <div class="space-y-3">
            <Label>Pošlji testno sporočilo</Label>
            <div class="flex gap-2">
              <Input
                v-model="sample.to"
                placeholder="Email naslov prejemnika"
                type="email"
                class="flex-1"
              />
              <Button @click="sendTest" :disabled="!props.template?.id || !sample.to">
                <SendIcon class="h-4 w-4 mr-2" />
                Pošlji
              </Button>
            </div>
          </div>
        </CardContent>
      </Card>

      <!-- Manage images panel -->
      <Card>
        <CardHeader>
          <div class="flex items-center gap-2">
            <ImageIcon class="h-5 w-5" />
            <CardTitle class="text-base">Upravljanje slik</CardTitle>
          </div>
        </CardHeader>
        <CardContent>
          <div v-if="docs.length === 0" class="text-sm text-muted-foreground py-4">
            Še ni naloženih slik.
          </div>
          <div v-else class="grid grid-cols-2 md:grid-cols-4 gap-4">
            <div
              v-for="doc in docs"
              :key="doc.id"
              class="relative group border rounded-lg p-2 hover:bg-muted/50 transition-colors"
            >
              <div class="aspect-video bg-muted rounded overflow-hidden mb-2">
                <img
                  v-if="doc.url"
                  :src="doc.url"
                  :alt="doc.name || 'Image'"
                  class="w-full h-full object-cover"
                />
              </div>
              <div class="text-xs truncate mb-1" :title="doc.name">{{ doc.name }}</div>
              <div class="text-xs text-muted-foreground">{{ formatSize(doc.size) }}</div>
              <Button
                size="sm"
                variant="destructive"
                class="absolute top-2 right-2 opacity-0 group-hover:opacity-100 transition-opacity"
                @click="deleteAttachedImage(doc)"
              >
                <Trash2Icon class="h-3 w-3" />
              </Button>
            </div>
          </div>
        </CardContent>
      </Card>
    </div>
  </AdminLayout>

  <!-- Final HTML dialog -->
  <Dialog :open="showFinal" @update:open="(val) => (showFinal = val)">
    <DialogContent class="max-w-5xl max-h-[84vh] flex flex-col">
      <DialogHeader>
        <DialogTitle>Končni HTML</DialogTitle>
        <DialogDescription>
          Popolnoma upodobljena e-poštna vsebina z vdelanimi slikami
        </DialogDescription>
      </DialogHeader>
      <div class="flex-1 overflow-auto space-y-3 p-4">
        <div class="flex items-center justify-between">
          <div class="flex items-center gap-2">
            <Label for="embed-mode" class="text-sm">Način vdelanih slik:</Label>
            <Select v-model="finalEmbedMode" @update:model-value="fetchFinalHtml">
              <SelectTrigger id="embed-mode" class="w-[160px]">
                <SelectValue />
              </SelectTrigger>
              <SelectContent>
                <SelectItem value="base64">base64 (privzeto)</SelectItem>
                <SelectItem value="hosted">hosted (povezava)</SelectItem>
              </SelectContent>
            </Select>
          </div>
          <div class="flex items-center gap-2">
            <Button size="sm" variant="outline" @click="copyFinalHtml">
              <CopyIcon class="h-4 w-4 mr-2" />
              Kopiraj
            </Button>
            <Button size="sm" variant="outline" @click="downloadFinalHtml">
              <DownloadIcon class="h-4 w-4 mr-2" />
              Prenesi
            </Button>
          </div>
        </div>

        <div v-if="finalAttachments.length > 0" class="space-y-2">
          <Label class="text-sm">Priponke</Label>
          <div class="space-y-1">
            <div
              v-for="(att, idx) in finalAttachments"
              :key="idx"
              class="text-xs p-2 bg-muted rounded flex items-center justify-between"
            >
              <span class="truncate">{{ att.filename }}</span>
              <Badge variant="outline" class="ml-2">{{ formatSize(att.size) }}</Badge>
            </div>
          </div>
        </div>

        <div class="space-y-2">
          <Label class="text-sm">Predogled</Label>
          <iframe
            :srcdoc="finalHtml"
            class="w-full border rounded-md bg-white"
            style="min-height: 400px"
          />
        </div>

        <div class="space-y-2">
          <Label class="text-sm">Izvorna koda</Label>
          <Textarea
            :model-value="finalHtml"
            readonly
            rows="12"
            class="font-mono text-xs"
          />
        </div>
      </div>
    </DialogContent>
  </Dialog>
</template>

<style scoped>
.input {
  width: 100%;
  border-radius: 0.375rem;
  border: 1px solid #d1d5db;
  padding: 0.5rem 0.75rem;
  font-size: 0.875rem;
  line-height: 1.25rem;
}
.input:focus {
  outline: 2px solid transparent;
  outline-offset: 2px;
  border-color: #6366f1;
  box-shadow: 0 0 0 1px #6366f1;
}
.label {
  display: block;
  font-size: 0.65rem;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: #6b7280;
  margin-bottom: 0.25rem;
}
</style>
