import { useEffect, useMemo, useRef, useState } from "react";
import type { ApiSettings } from "../../types";
import { previewCampaignAttachments, type CampaignAttachmentPreviewRule } from "../../api/campaigns";
import { Button } from "@govoplan/core-webui";
import { Card } from "@govoplan/core-webui";
import { FormField } from "@govoplan/core-webui";
import { PageTitle } from "@govoplan/core-webui";
import { LoadingFrame } from "@govoplan/core-webui";
import { DismissibleAlert, SegmentedControl, i18nMessage } from "@govoplan/core-webui";
import LockedVersionNotice from "./components/LockedVersionNotice";
import VersionLine from "./components/VersionLine";
import CampaignMessagePreviewOverlay, { type CampaignMessagePreviewAttachment } from "./components/MessagePreviewOverlay";
import { TemplateFieldChipList, UndefinedPlaceholderDecisionDialog, UndefinedPlaceholderList } from "./components/TemplatePlaceholderControls";
import { useCampaignWorkspaceData } from "./hooks/useCampaignWorkspaceData";
import { useCampaignDraftEditor } from "./hooks/useCampaignDraftEditor";
import { asArray, asRecord, formatDateTime, isAuditLockedVersion } from "./utils/campaignView";
import { cloneJson, getBool, getText } from "./utils/draftEditor";
import { humanizeFieldName } from "./utils/fieldDefinitions";
import { campaignJsonForAttachmentPreview } from "./utils/templatePreviewDraft";
import { buildTemplatePreviewContext, buildUndefinedPlaceholders, extractTemplatePlaceholders, recipientAddressTemplateFieldOptions, removePlaceholderFromText, replacePlaceholderInText, renderTemplatePreviewText, uniquePlaceholders, valueToPreview, type TemplateNamespace, type UndefinedPlaceholder } from "./utils/templatePlaceholders";

type TemplateBodyMode = "text" | "html" | "both";
type BodyEditorMode = "text" | "html";
type EditorTarget = "subject" | "text" | "html";

export default function TemplateDataPage({ settings, campaignId }: {settings: ApiSettings;campaignId: string;}) {
  const { data, loading, error, reload, setError } = useCampaignWorkspaceData(settings, campaignId);
  const [activeBodyEditor, setActiveBodyEditor] = useState<BodyEditorMode>("text");
  const [activeEditor, setActiveEditor] = useState<EditorTarget>("text");
  const [previewOpen, setPreviewOpen] = useState(false);
  const [previewIndex, setPreviewIndex] = useState(0);
  const [undefinedDialog, setUndefinedDialog] = useState<UndefinedPlaceholder | null>(null);
  const [attachmentPreviewRules, setAttachmentPreviewRules] = useState<CampaignAttachmentPreviewRule[]>([]);
  const [attachmentPreviewLoading, setAttachmentPreviewLoading] = useState(false);
  const [attachmentPreviewError, setAttachmentPreviewError] = useState("");
  const subjectRef = useRef<HTMLInputElement | null>(null);
  const textRef = useRef<HTMLTextAreaElement | null>(null);
  const htmlRef = useRef<HTMLTextAreaElement | null>(null);

  const version = data.currentVersion;
  const locked = isAuditLockedVersion(version, data.campaign?.current_version_id);
  const { draft, setDraft, displayDraft, dirty, saveState, localError, patch, markDirty, saveDraft } = useCampaignDraftEditor({
    settings,
    campaignId,
    version,
    locked,
    reload,
    setError,
    currentStep: "template",
    unsavedTitle: "i18n:govoplan-campaign.unsaved_template_changes.4209cdec",
    unsavedMessage: "i18n:govoplan-campaign.the_template_has_unsaved_changes_save_them_befor.89f74fc1",
    loadedLabel: (loadedVersion) => loadedVersion.autosaved_at ? `Loaded autosave ${formatDateTime(loadedVersion.autosaved_at)}` : "i18n:govoplan-campaign.loaded.6db90a0a",
    onLoaded: () => setPreviewIndex(0)
  });
  const template = asRecord(displayDraft.template);
  const templateBodyMode = normalizeTemplateBodyMode(getText(template, "body_mode", "both"));
  const visibleBodyEditor: BodyEditorMode = templateBodyMode === "html" ? "html" : templateBodyMode === "text" ? "text" : activeBodyEditor;
  const fields = useMemo(() => asArray(displayDraft.fields).map(asRecord), [displayDraft.fields]);
  const localFieldNames = useMemo(() => fields.map((field) => String(field.name || field.id || "")).filter(Boolean), [fields]);
  const globalFieldNames = useMemo(() => uniqueSorted([...localFieldNames, ...Object.keys(asRecord(displayDraft.global_values))]), [displayDraft.global_values, localFieldNames]);
  const builtInAddressNames = useMemo(() => recipientAddressTemplateFieldOptions().map((field) => field.name), []);
  const localAvailableNames = useMemo(() => new Set([...localFieldNames, ...builtInAddressNames]), [builtInAddressNames, localFieldNames]);
  const globalAvailableNames = useMemo(() => new Set(globalFieldNames), [globalFieldNames]);
  const allAvailableNames = useMemo(() => new Set([...localAvailableNames, ...globalAvailableNames]), [globalAvailableNames, localAvailableNames]);
  const localFieldOptions = useMemo(() => {
    const options = [...recipientAddressTemplateFieldOptions(), ...localFieldNames.map((name) => ({ name, label: name }))];
    return options.filter((option, index) => options.findIndex((candidate) => candidate.name === option.name) === index);
  }, [localFieldNames]);
  const globalFieldOptions = useMemo(() => globalFieldNames.map((name) => ({ name, label: name })), [globalFieldNames]);
  const entries = asRecord(displayDraft.entries);
  const inlineEntries = useMemo(() => asArray(entries.inline).map(asRecord), [entries.inline]);
  const activePreviewEntries = useMemo(
    () => inlineEntries.map((entry, sourceIndex) => ({ entry, sourceIndex: sourceIndex + 1 })).filter(({ entry }) => entry.active !== false),
    [inlineEntries]
  );
  const previewEntries = activePreviewEntries.length > 0 ? activePreviewEntries : [{ entry: {}, sourceIndex: 0 }];
  const previewSelection = previewEntries[Math.min(previewIndex, previewEntries.length - 1)] ?? previewEntries[0];
  const previewEntry = previewSelection.entry;
  const ignoreEmptyFields = getBool(asRecord(displayDraft.validation_policy), "ignore_empty_fields", false);
  const templateText = [
  getText(template, "subject"),
  templateBodyMode !== "html" ? getText(template, "text") : "",
  templateBodyMode !== "text" ? getText(template, "html") : ""].
  join("\n");
  const usedPlaceholders = useMemo(() => extractTemplatePlaceholders(templateText), [templateText]);
  const invalidNamespacePlaceholders = useMemo(() => uniquePlaceholders(usedPlaceholders.filter((field) => !field.validNamespace)), [usedPlaceholders]);
  const undefinedPlaceholders = useMemo(
    () => buildUndefinedPlaceholders(usedPlaceholders, allAvailableNames, { local: localAvailableNames, global: globalAvailableNames }),
    [usedPlaceholders, allAvailableNames, globalAvailableNames, localAvailableNames]
  );
  const previewContext = useMemo(() => buildTemplatePreviewContext(displayDraft, previewEntry), [displayDraft, previewEntry]);
  const previewSubject = renderTemplatePreviewText(getText(template, "subject"), previewContext, ignoreEmptyFields);
  const previewText = renderTemplatePreviewText(getText(template, "text"), previewContext, ignoreEmptyFields);
  const previewHtml = renderTemplatePreviewText(getText(template, "html"), previewContext, ignoreEmptyFields);
  const selectedPreviewEntryIndex = previewSelection.sourceIndex;
  const previewAttachmentRules = useMemo(
    () => attachmentPreviewRules.filter((rule) => rule.entry_index === selectedPreviewEntryIndex),
    [attachmentPreviewRules, selectedPreviewEntryIndex]
  );
  const previewAttachments = useMemo(
    () => mapResolvedAttachmentsToPreviewBoxes(previewAttachmentRules, attachmentPreviewLoading, attachmentPreviewError, displayDraft),
    [attachmentPreviewError, attachmentPreviewLoading, displayDraft, previewAttachmentRules]
  );


  useEffect(() => {
    if (previewIndex >= previewEntries.length) setPreviewIndex(Math.max(0, previewEntries.length - 1));
  }, [previewIndex, previewEntries.length]);

  useEffect(() => {
    if (templateBodyMode === "text" && activeBodyEditor !== "text") setActiveBodyEditor("text");
    if (templateBodyMode === "html" && activeBodyEditor !== "html") setActiveBodyEditor("html");
    if (activeEditor !== "subject" && activeEditor !== visibleBodyEditor) setActiveEditor(visibleBodyEditor);
  }, [activeBodyEditor, activeEditor, templateBodyMode, visibleBodyEditor]);

  useEffect(() => {
    if (!previewOpen || !version?.id || !draft) return;
    let cancelled = false;
    setAttachmentPreviewLoading(true);
    setAttachmentPreviewError("");
    const handle = window.setTimeout(() => {
      void previewCampaignAttachments(settings, campaignId, version.id, {
        include_unmatched: false,
        campaign_json: campaignJsonForAttachmentPreview(displayDraft)
      }).
      then((response) => {
        if (!cancelled) setAttachmentPreviewRules(response.rules);
      }).
      catch((reason: unknown) => {
        if (!cancelled) {
          setAttachmentPreviewRules([]);
          setAttachmentPreviewError(reason instanceof Error ? reason.message : String(reason));
        }
      }).
      finally(() => {
        if (!cancelled) setAttachmentPreviewLoading(false);
      });
    }, 120);
    return () => {
      cancelled = true;
      window.clearTimeout(handle);
    };
  }, [campaignId, displayDraft, draft, previewOpen, settings.apiBaseUrl, settings.apiKey, settings.accessToken, version?.id]);


  function patchTemplateText(target: EditorTarget, value: string) {
    patch(["template", target], value);
  }

  function patchTemplateBodyMode(mode: TemplateBodyMode) {
    if (locked) return;
    patch(["template", "body_mode"], mode);
    if (mode !== "both") {
      setActiveBodyEditor(mode);
      if (activeEditor !== "subject") setActiveEditor(mode);
    }
  }

  function insertPlaceholder(namespace: TemplateNamespace, name: string) {
    if (locked) return;
    const target = activeEditor === "subject" ? "subject" : visibleBodyEditor;
    const element = target === "subject" ? subjectRef.current : target === "html" ? htmlRef.current : textRef.current;
    const token = `{{${namespace}:${name}}}`;
    const currentText = getText(template, target);
    const start = element?.selectionStart ?? currentText.length;
    const end = element?.selectionEnd ?? currentText.length;
    const nextText = `${currentText.slice(0, start)}${token}${currentText.slice(end)}`;
    patchTemplateText(target, nextText);
    window.requestAnimationFrame(() => {
      element?.focus();
      const cursor = start + token.length;
      element?.setSelectionRange(cursor, cursor);
    });
  }

  function addUndefinedField(field: UndefinedPlaceholder) {
    if (!draft || locked || !field.name) return;
    const existingFields = asArray(draft.fields).map(asRecord);
    const alreadyDefined = existingFields.some((item) => String(item.name || item.id || "") === field.name);
    if (!alreadyDefined) {
      patch(["fields"], [
      ...existingFields,
      {
        name: field.name,
        label: humanizeFieldName(field.name),
        type: "string",
        required: false,
        can_override: true
      }]
      );
    }
    setUndefinedDialog(null);
  }

  function removePlaceholder(field: UndefinedPlaceholder) {
    if (locked) return;
    setDraft((current) => {
      const next = cloneJson(current ?? {});
      const nextTemplate = { ...asRecord(next.template) };
      nextTemplate.subject = removePlaceholderFromText(getText(nextTemplate, "subject"), field.raw);
      nextTemplate.text = removePlaceholderFromText(getText(nextTemplate, "text"), field.raw);
      nextTemplate.html = removePlaceholderFromText(getText(nextTemplate, "html"), field.raw);
      next.template = nextTemplate;
      return next;
    });
    markDirty();
    setUndefinedDialog(null);
  }

  function replacePlaceholder(field: UndefinedPlaceholder, namespace: TemplateNamespace, name: string) {
    if (locked) return;
    const replacement = `{{${namespace}:${name}}}`;
    setDraft((current) => {
      const next = cloneJson(current ?? {});
      const nextTemplate = { ...asRecord(next.template) };
      nextTemplate.subject = replacePlaceholderInText(getText(nextTemplate, "subject"), field.raw, replacement);
      nextTemplate.text = replacePlaceholderInText(getText(nextTemplate, "text"), field.raw, replacement);
      nextTemplate.html = replacePlaceholderInText(getText(nextTemplate, "html"), field.raw, replacement);
      next.template = nextTemplate;
      return next;
    });
    markDirty();
    setUndefinedDialog(null);
  }


  return (
    <div className="content-pad workspace-data-page">
      <div className="page-heading split workspace-heading">
        <div>
          <PageTitle loading={loading}>i18n:govoplan-campaign.template.3ec1ae06</PageTitle>
          <VersionLine version={version} versions={data.versions} status={saveState} />
        </div>
        <div className="button-row compact-actions">
          <Button disabled>i18n:govoplan-campaign.manage_templates.23688071</Button>
          <Button onClick={reload} disabled={loading}>i18n:govoplan-campaign.reload.cce71553</Button>
          <Button variant="primary" onClick={() => saveDraft("manual")} disabled={!dirty || locked || !draft}>i18n:govoplan-campaign.save.efc007a3</Button>
        </div>
      </div>

      {error && <DismissibleAlert tone="danger" resetKey={error} floating>{error}</DismissibleAlert>}
      {localError && <DismissibleAlert tone="danger" resetKey={localError} floating>{localError}</DismissibleAlert>}
      {locked && <LockedVersionNotice settings={settings} campaignId={campaignId} version={version} currentVersionId={data.campaign?.current_version_id} reload={reload} message="i18n:govoplan-campaign.this_page_is_read_only_for_the_selected_version.dacf5743" />}

      <LoadingFrame loading={loading || !draft} label="i18n:govoplan-campaign.loading_campaign_draft.1cf47e50">
        <>
          <div className="dashboard-grid template-editor-grid">
            <Card title="i18n:govoplan-campaign.editable_template.5e747a1e" actions={<Button onClick={() => setPreviewOpen(true)}>i18n:govoplan-campaign.preview.f1fbb2b4</Button>}>
              <div className="form-grid">
                <FormField label="i18n:govoplan-campaign.subject.8d183dbd">
                  <input
                    ref={subjectRef}
                    value={getText(template, "subject")}
                    disabled={locked}
                    onFocus={() => setActiveEditor("subject")}
                    onChange={(event) => patchTemplateText("subject", event.target.value)} />
                  
                </FormField>
                <FormField label="i18n:govoplan-campaign.message_body_format.5fec42d2">
                  <SegmentedControl
                    className="template-body-mode"
                    size="content"
                    width="inline"
                    ariaLabel="i18n:govoplan-campaign.message_body_format.5fec42d2"
                    value={templateBodyMode}
                    disabled={locked}
                    onChange={patchTemplateBodyMode}
                    options={[
                      { id: "text", label: "i18n:govoplan-campaign.text_only.9ccbd022" },
                      { id: "html", label: "i18n:govoplan-campaign.html_only.1c4fbcb1" },
                      { id: "both", label: "i18n:govoplan-campaign.both.1f469838" }
                    ]}
                  />
                </FormField>
                {templateBodyMode === "both" &&
                <SegmentedControl
                  className="template-body-mode template-editor-mode"
                  size="content"
                  width="inline"
                  ariaLabel="i18n:govoplan-campaign.body_editor.8615dd7e"
                  value={visibleBodyEditor}
                  onChange={(mode) => {setActiveBodyEditor(mode);setActiveEditor(mode);}}
                  options={[
                    { id: "text", label: "i18n:govoplan-campaign.plain_text.9580fcbc" },
                    { id: "html", label: "i18n:govoplan-campaign.html.9f738ce8" }
                  ]}
                />
                }
                {visibleBodyEditor === "text" &&
                <FormField label="i18n:govoplan-campaign.plain_text_body.030a0da0">
                    <textarea
                    ref={textRef}
                    rows={16}
                    value={getText(template, "text")}
                    disabled={locked}
                    onFocus={() => {setActiveBodyEditor("text");setActiveEditor("text");}}
                    onChange={(event) => patchTemplateText("text", event.target.value)} />
                  
                  </FormField>
                }
                {visibleBodyEditor === "html" &&
                <FormField label="i18n:govoplan-campaign.html_body.77b5ba37">
                    <textarea
                    ref={htmlRef}
                    rows={16}
                    value={getText(template, "html")}
                    disabled={locked}
                    onFocus={() => {setActiveBodyEditor("html");setActiveEditor("html");}}
                    onChange={(event) => patchTemplateText("html", event.target.value)} />
                  
                  </FormField>
                }
                <div className="button-row template-editor-actions">
                  <Button disabled>i18n:govoplan-campaign.load_from_library.327ada7c</Button>
                  <Button disabled>i18n:govoplan-campaign.save_to_library.396649bf</Button>
                </div>
              </div>
            </Card>

            <div className="template-side-stack">
              <Card title="i18n:govoplan-campaign.fields.e8b68527">
                {invalidNamespacePlaceholders.length > 0 &&
                <DismissibleAlert tone="warning" resetKey={invalidNamespacePlaceholders.map((field) => field.namespace || field.raw).join(",")}>i18n:govoplan-campaign.undefined_placeholder_namespace_detected.2ef5c282 {invalidNamespacePlaceholders.map((field) => field.namespace || field.raw).join(", ")}.</DismissibleAlert>
                }
                {usedPlaceholders.length === 0 && <p className="muted">i18n:govoplan-campaign.no_template_placeholders_detected_yet.56bba9d1</p>}
                <p className="muted small-note">i18n:govoplan-campaign.click_a_field_to_insert_it_at_the_current_cursor.643aa7bc</p>

                <h3 className="section-mini-heading">i18n:govoplan-campaign.global_fields.07f84ea4</h3>
                <TemplateFieldChipList
                  namespace="global"
                  fields={globalFieldOptions}
                  usedPlaceholders={usedPlaceholders}
                  empty="i18n:govoplan-campaign.no_campaign_fields_or_global_values_defined.3888623d"
                  onInsert={insertPlaceholder} />
                

                <h3 className="section-mini-heading">i18n:govoplan-campaign.local_fields.c81bb4de</h3>
                <p className="muted small-note">i18n:govoplan-campaign.address_fields_use_the_effective_merged_or_overr.d6930da6 <code>i18n:govoplan-campaign.to_2.8c1db0c7</code> or <code>i18n:govoplan-campaign.to_2_email.5ad61c1a</code> i18n:govoplan-campaign.for_a_specific_additional_address.1199883f</p>
                <TemplateFieldChipList
                  namespace="local"
                  fields={localFieldOptions}
                  usedPlaceholders={usedPlaceholders}
                  empty="i18n:govoplan-campaign.no_campaign_fields_defined.8c2ea4b2"
                  onInsert={insertPlaceholder} />
                

                <h3 className="section-mini-heading">i18n:govoplan-campaign.used_in_template_but_undefined.57b5f3da</h3>
                <UndefinedPlaceholderList items={undefinedPlaceholders} onSelect={setUndefinedDialog} />
              </Card>
            </div>
          </div>

        </>
      </LoadingFrame>

      {previewOpen &&
      <CampaignMessagePreviewOverlay
        title="i18n:govoplan-campaign.template_preview.ea0aa8b2"
        bodyMode={visibleBodyEditor}
        subject={previewSubject}
        text={templateBodyMode === "html" ? null : previewText}
        html={templateBodyMode === "text" ? null : previewHtml}
        metaItems={templatePreviewMetaItems(previewContext)}
        recipientLabel={activePreviewEntries.length > 0 ? recipientLabel(previewEntry, previewSelection.sourceIndex - 1) : "i18n:govoplan-campaign.global_preview.f81f09b2"}
        recipientNote={activePreviewEntries.length > 0 ? `${Math.min(previewIndex, previewEntries.length - 1) + 1} of ${previewEntries.length}` : inlineEntries.length > 0 ? "i18n:govoplan-campaign.no_recipient_preview_is_available.9e93a97d" : "i18n:govoplan-campaign.no_inline_recipients_are_available_yet.e405bacb"}
        attachments={previewAttachments}
        navigation={{
          index: Math.min(previewIndex, previewEntries.length - 1),
          total: previewEntries.length,
          onFirst: () => setPreviewIndex(0),
          onPrevious: () => setPreviewIndex((value) => Math.max(0, value - 1)),
          onNext: () => setPreviewIndex((value) => Math.min(previewEntries.length - 1, value + 1)),
          onLast: () => setPreviewIndex(previewEntries.length - 1)
        }}
        onClose={() => setPreviewOpen(false)} />

      }

      <UndefinedPlaceholderDecisionDialog
        field={undefinedDialog}
        contextLabel="template"
        removeLabel="i18n:govoplan-campaign.remove_from_template.5fb2827b"
        onCancel={() => setUndefinedDialog(null)}
        onRemove={removePlaceholder}
        onReplace={replacePlaceholder}
        onAddField={addUndefinedField}
        localFields={localFieldOptions}
        globalFields={globalFieldOptions} />
      
    </div>);

}

function mapResolvedAttachmentsToPreviewBoxes(
rules: CampaignAttachmentPreviewRule[],
loading: boolean,
error: string,
draft: Record<string, unknown>)
: CampaignMessagePreviewAttachment[] {
  if (loading) {
    return [{
      filename: i18nMessage("i18n:govoplan-campaign.resolving_attachment_patterns.87d7d21b"),
      detail: i18nMessage("i18n:govoplan-campaign.managed_files_are_being_checked_for_this_recipie.489ecefd")
    }];
  }
  if (error) {
    return [{ filename: i18nMessage("i18n:govoplan-campaign.attachment_preview_unavailable.62211756"), detail: error }];
  }
  return rules.flatMap((rule) => {
    const zipProtection = zipProtectionForRule(rule, draft);
    const detailParts = [
    rule.source === "global" ? i18nMessage("i18n:govoplan-campaign.global.5f1184f7") : i18nMessage("i18n:govoplan-campaign.recipient.90343260"),
    rule.label,
    rule.required ? i18nMessage("i18n:govoplan-campaign.required.eed6bfb4") : i18nMessage("i18n:govoplan-campaign.optional.0c6c4102"),
    rule.pattern].
    filter(Boolean);
    const detail = detailParts.join(" · ");
    const fallbackArchiveLabel = i18nMessage("i18n:govoplan-campaign.recipient_attachments_zip.79d436c7");
    if (rule.matches.length > 0) {
      return rule.matches.map((match) => ({
        filename: match.filename || match.display_path,
        label: rule.label,
        detail: i18nMessage("i18n:govoplan-campaign.value_value.a8618e4a", { value0: detail, value1: match.display_path ? ` · ${match.display_path}` : "" }),
        contentType: match.content_type,
        sizeBytes: match.size_bytes,
        archiveGroup: rule.zip_included ? rule.zip_filename || "recipient-attachments.zip" : null,
        archiveLabel: rule.zip_included ? rule.zip_filename || fallbackArchiveLabel : null,
        protected: zipProtection.protected,
        protectionNote: zipProtection.note
      }));
    }
    const pattern = rule.pattern || i18nMessage("i18n:govoplan-campaign.attachment_pattern.3540c952");
    return [{
      filename: i18nMessage("i18n:govoplan-campaign.no_file_matched_value", { value0: pattern }),
      label: rule.label,
      detail: i18nMessage("i18n:govoplan-campaign.value_value.a8618e4a", { value0: detail, value1: rule.status !== "ok" ? ` · ${rule.status}` : "" }),
      archiveGroup: rule.zip_included ? rule.zip_filename || "recipient-attachments.zip" : null,
      archiveLabel: rule.zip_included ? rule.zip_filename || fallbackArchiveLabel : null,
      protected: zipProtection.protected,
      protectionNote: zipProtection.note
    }];
  });
}

function templatePreviewMetaItems(context: Record<string, string>) {
  return [
  { label: "i18n:govoplan-campaign.from.3f66052a", value: context["local:from"] || null },
  { label: "i18n:govoplan-campaign.to.ae79ea1e", value: context["local:all_to"] || null },
  { label: "i18n:govoplan-campaign.reply_to.c1733667", value: context["local:all_reply_to"] || null },
  { label: "i18n:govoplan-campaign.cc.1fd6a880", value: context["local:all_cc"] || null },
  { label: "i18n:govoplan-campaign.bcc.8431acad", value: context["local:all_bcc"] || null }];

}

function zipProtectionForRule(rule: CampaignAttachmentPreviewRule, draft: Record<string, unknown>): {protected: boolean;note: string | null;} {
  if (!rule.zip_included) return { protected: false, note: null };
  const zipConfig = asRecord(asRecord(draft.attachments).zip);
  const archives = asArray(zipConfig.archives).map(asRecord);
  const archive = archives.find((item) => {
    const id = getText(item, "id");
    const name = getText(item, "name", getText(item, "filename_template"));
    return rule.zip_archive_id && id === rule.zip_archive_id || rule.zip_filename && name === rule.zip_filename;
  }) ?? archives.find((item) => getBool(item, "standard")) ?? archives[0];
  if (!archive) return { protected: false, note: null };
  const legacyMode = getText(archive, "password_mode");
  const protectedArchive = getBool(archive, "password_enabled", ["direct", "field", "template"].includes(legacyMode));
  if (!protectedArchive) return { protected: false, note: null };
  const field = getText(archive, "password_field");
  const scope = getText(archive, "password_scope") === "global" ? "global" : "local";
  const method = getText(archive, "method", "aes") === "zip_standard" ? "i18n:govoplan-campaign.zipcrypto.03bf7fb4" : "i18n:govoplan-campaign.aes.41f215a6";
  const source = field ? i18nMessage("i18n:govoplan-campaign.scope_field_value", { value0: humanizeScope(scope), value1: field }) : "";
  return {
    protected: true,
    note: source ?
    i18nMessage("i18n:govoplan-campaign.value_encryption_value", { value0: source, value1: method }) :
    i18nMessage("i18n:govoplan-campaign.encryption_value", { value0: method })
  };
}

function humanizeScope(scope: string): string {
  return scope === "global" ? "i18n:govoplan-campaign.global.5f1184f7" : "i18n:govoplan-campaign.local.dc99d54d";
}

function recipientLabel(entry: Record<string, unknown>, index: number): string {
  const name = valueToPreview(entry.name).trim();
  const email = valueToPreview(entry.email).trim();
  if (name && email) return `${name} <${email}>`;
  if (name) return name;
  if (email) return email;
  return i18nMessage("i18n:govoplan-campaign.recipient_value.d0233fb6", { value0: index + 1 });
}

function normalizeTemplateBodyMode(value: string): TemplateBodyMode {
  if (value === "text" || value === "html" || value === "both") return value;
  return "both";
}

function uniqueSorted(values: string[]): string[] {
  return [...new Set(values.map((value) => value.trim()).filter(Boolean))].sort();
}
