import { useCallback, useEffect, useMemo, useState } from "react";
import {
  Archive,
  Boxes,
  Building2,
  Inbox,
  Pencil,
  Plus,
  RefreshCw,
  Rocket,
  Save,
  Trash2
} from "lucide-react";
import {
  AdminPageLayout,
  Button,
  ConfirmDialog,
  Dialog,
  FormField,
  IconButton,
  SegmentedControl,
  SelectionList,
  SelectionListItem,
  StatusBadge,
  ToggleSwitch,
  type ApiSettings
} from "@govoplan/core-webui";
import {
  archivePostbox,
  createExactPostbox,
  createPostboxTemplate,
  listAdminPostboxes,
  listPostboxOrganizationTargets,
  listPostboxTemplates,
  materializePostboxTemplate,
  publishPostboxTemplate,
  retirePostboxTemplate,
  revisePostboxTemplate,
  type PostboxDirectoryItem,
  type PostboxExactCreatePayload,
  type PostboxOrganizationFunction,
  type PostboxOrganizationUnit,
  type PostboxTemplate,
  type PostboxTemplateCreatePayload,
  type PostboxTemplateRevisionPayload
} from "../../api/postbox";


type AdminMode = "templates" | "postboxes";
type TemplateDraft = PostboxTemplateCreatePayload & { templateId: string };
type ExactDraft = PostboxExactCreatePayload;
type MaterializeDraft = {
  templateId: string;
  organization_unit_id: string;
  function_id: string;
  context_key: string;
};

const templateDefaults = (): TemplateDraft => ({
  templateId: "",
  slug: "",
  name: "",
  description: "",
  function_type_id: null,
  scope_kind: "tenant",
  scope_id: null,
  name_pattern: "{unit_name} / {function_name}",
  address_pattern: "{template_slug}.{unit_slug}.{function_slug}",
  classification: "internal",
  allow_vacant_delivery: true
});

const exactDefaults = (): ExactDraft => ({
  name: "",
  description: "",
  organization_unit_id: "",
  function_id: "",
  address_key: "",
  classification: "internal"
});

export default function PostboxAdminPanel({
  settings,
  canManageBindings,
  canManageTemplates
}: {
  settings: ApiSettings;
  canManageBindings: boolean;
  canManageTemplates: boolean;
}) {
  const [mode, setMode] = useState<AdminMode>(
    canManageTemplates ? "templates" : "postboxes"
  );
  const [templates, setTemplates] = useState<PostboxTemplate[]>([]);
  const [postboxes, setPostboxes] = useState<PostboxDirectoryItem[]>([]);
  const [units, setUnits] = useState<PostboxOrganizationUnit[]>([]);
  const [selectedTemplateId, setSelectedTemplateId] = useState("");
  const [selectedPostboxId, setSelectedPostboxId] = useState("");
  const [loading, setLoading] = useState(true);
  const [busy, setBusy] = useState(false);
  const [error, setError] = useState("");
  const [success, setSuccess] = useState("");
  const [templateDialogOpen, setTemplateDialogOpen] = useState(false);
  const [templateDraft, setTemplateDraft] = useState<TemplateDraft>(templateDefaults);
  const [exactDialogOpen, setExactDialogOpen] = useState(false);
  const [exactDraft, setExactDraft] = useState<ExactDraft>(exactDefaults);
  const [materializeDialogOpen, setMaterializeDialogOpen] = useState(false);
  const [materializeDraft, setMaterializeDraft] = useState<MaterializeDraft>({
    templateId: "",
    organization_unit_id: "",
    function_id: "",
    context_key: ""
  });
  const [archiveTarget, setArchiveTarget] = useState<PostboxDirectoryItem | null>(null);

  const selectedTemplate = useMemo(
    () => templates.find((template) => template.id === selectedTemplateId) ?? templates[0] ?? null,
    [templates, selectedTemplateId]
  );
  const selectedPostbox = useMemo(
    () => postboxes.find((postbox) => postbox.id === selectedPostboxId) ?? postboxes[0] ?? null,
    [postboxes, selectedPostboxId]
  );
  const functionTypes = useMemo(() => {
    const values = new Map<string, string>();
    for (const unit of units) {
      for (const fn of unit.functions) {
        if (fn.function_type_id && !values.has(fn.function_type_id)) {
          values.set(fn.function_type_id, fn.name);
        }
      }
    }
    return [...values].map(([id, name]) => ({ id, name }));
  }, [units]);
  const unitTypes = useMemo(() => {
    const values = new Map<string, string>();
    for (const unit of units) {
      if (unit.unit_type_id && !values.has(unit.unit_type_id)) {
        values.set(unit.unit_type_id, unit.name);
      }
    }
    return [...values].map(([id, example]) => ({ id, example }));
  }, [units]);

  const load = useCallback(async () => {
    setLoading(true);
    setError("");
    try {
      const [nextTemplates, nextPostboxes, nextUnits] = await Promise.all([
        canManageTemplates ? listPostboxTemplates(settings) : Promise.resolve([]),
        canManageBindings ? listAdminPostboxes(settings) : Promise.resolve([]),
        listPostboxOrganizationTargets(settings)
      ]);
      setTemplates(nextTemplates);
      setPostboxes(nextPostboxes);
      setUnits(nextUnits);
      setSelectedTemplateId((current) =>
        current && nextTemplates.some((template) => template.id === current)
          ? current
          : nextTemplates[0]?.id ?? ""
      );
      setSelectedPostboxId((current) =>
        current && nextPostboxes.some((postbox) => postbox.id === current)
          ? current
          : nextPostboxes[0]?.id ?? ""
      );
    } catch (loadError) {
      setError(errorMessage(loadError));
    } finally {
      setLoading(false);
    }
  }, [canManageBindings, canManageTemplates, settings]);

  useEffect(() => {
    void load();
  }, [load]);

  function openNewTemplate() {
    setTemplateDraft(templateDefaults());
    setTemplateDialogOpen(true);
  }

  function openTemplateRevision(template: PostboxTemplate) {
    const revision = currentRevision(template);
    if (!revision) return;
    setTemplateDraft({
      templateId: template.id,
      slug: template.slug,
      name: template.name,
      description: template.description || "",
      function_type_id: revision.function_type_id ?? null,
      scope_kind: revision.scope_kind,
      scope_id: revision.scope_id ?? null,
      name_pattern: revision.name_pattern,
      address_pattern: revision.address_pattern,
      classification: revision.classification,
      allow_vacant_delivery: revision.allow_vacant_delivery
    });
    setTemplateDialogOpen(true);
  }

  async function saveTemplate() {
    setBusy(true);
    setError("");
    setSuccess("");
    try {
      if (templateDraft.templateId) {
        await revisePostboxTemplate(
          settings,
          templateDraft.templateId,
          revisionPayload(templateDraft)
        );
        setSuccess("A new immutable template revision was created.");
      } else {
        await createPostboxTemplate(settings, {
          slug: templateDraft.slug,
          name: templateDraft.name,
          description: templateDraft.description || null,
          ...revisionPayload(templateDraft)
        });
        setSuccess("Postbox template created as a draft.");
      }
      setTemplateDialogOpen(false);
      await load();
    } catch (actionError) {
      setError(errorMessage(actionError));
    } finally {
      setBusy(false);
    }
  }

  async function publishSelected() {
    if (!selectedTemplate) return;
    setBusy(true);
    setError("");
    setSuccess("");
    try {
      await publishPostboxTemplate(
        settings,
        selectedTemplate.id,
        selectedTemplate.current_revision
      );
      setSuccess(`Published revision ${selectedTemplate.current_revision}.`);
      await load();
    } catch (actionError) {
      setError(errorMessage(actionError));
    } finally {
      setBusy(false);
    }
  }

  async function retireSelected() {
    if (!selectedTemplate) return;
    setBusy(true);
    setError("");
    setSuccess("");
    try {
      await retirePostboxTemplate(settings, selectedTemplate.id);
      setSuccess("Postbox template retired. Existing addresses remain durable.");
      await load();
    } catch (actionError) {
      setError(errorMessage(actionError));
    } finally {
      setBusy(false);
    }
  }

  function openExact() {
    const unit = units.find((item) => item.functions.length);
    setExactDraft({
      ...exactDefaults(),
      organization_unit_id: unit?.id ?? "",
      function_id: unit?.functions[0]?.id ?? ""
    });
    setExactDialogOpen(true);
  }

  async function saveExact() {
    setBusy(true);
    setError("");
    setSuccess("");
    try {
      await createExactPostbox(settings, {
        ...exactDraft,
        description: exactDraft.description || null,
        address_key: exactDraft.address_key || null
      });
      setExactDialogOpen(false);
      setSuccess("Exact function-bound Postbox created.");
      await load();
    } catch (actionError) {
      setError(errorMessage(actionError));
    } finally {
      setBusy(false);
    }
  }

  function openMaterialize(template: PostboxTemplate) {
    const revision = currentRevision(template);
    const compatible = compatibleTargets(units, revision?.function_type_id);
    const unit = compatible[0];
    setMaterializeDraft({
      templateId: template.id,
      organization_unit_id: unit?.id ?? "",
      function_id: unit?.functions[0]?.id ?? "",
      context_key: ""
    });
    setMaterializeDialogOpen(true);
  }

  async function materialize() {
    setBusy(true);
    setError("");
    setSuccess("");
    try {
      await materializePostboxTemplate(settings, materializeDraft.templateId, {
        organization_unit_id: materializeDraft.organization_unit_id,
        function_id: materializeDraft.function_id,
        context_key: materializeDraft.context_key || null
      });
      setMaterializeDialogOpen(false);
      setSuccess("Stable Postbox address resolved and materialized.");
      await load();
    } catch (actionError) {
      setError(errorMessage(actionError));
    } finally {
      setBusy(false);
    }
  }

  async function confirmArchive() {
    if (!archiveTarget) return;
    setBusy(true);
    setError("");
    setSuccess("");
    try {
      await archivePostbox(settings, archiveTarget.id);
      setSuccess("Postbox archived. Messages and delivery evidence were retained.");
      setArchiveTarget(null);
      await load();
    } catch (actionError) {
      setError(errorMessage(actionError));
    } finally {
      setBusy(false);
    }
  }

  return (
    <AdminPageLayout
      title="Postboxes"
      description="Manage durable organization-function addresses and reusable templates."
      loading={loading}
      error={error}
      success={success}
      className="postbox-admin-page"
      actions={
        <>
          <IconButton
            label="Refresh"
            icon={<RefreshCw size={16} />}
            onClick={() => void load()}
            disabled={busy}
          />
          {mode === "templates" && canManageTemplates ? (
            <Button variant="primary" onClick={openNewTemplate}>
              <Plus size={16} /> New template
            </Button>
          ) : null}
          {mode === "postboxes" && canManageBindings ? (
            <Button variant="primary" onClick={openExact}>
              <Plus size={16} /> Exact postbox
            </Button>
          ) : null}
        </>
      }
    >
      <SegmentedControl
        value={mode}
        onChange={(value) => setMode(value as AdminMode)}
        options={[
          ...(canManageTemplates ? [{ id: "templates", label: "Templates" }] : []),
          ...(canManageBindings ? [{ id: "postboxes", label: "Postboxes" }] : [])
        ]}
        ariaLabel="Postbox administration section"
      />
      {mode === "templates" ? (
        <TemplateWorkspace
          templates={templates}
          selected={selectedTemplate}
          onSelect={setSelectedTemplateId}
          onRevise={openTemplateRevision}
          onPublish={() => void publishSelected()}
          onRetire={() => void retireSelected()}
          onMaterialize={openMaterialize}
          busy={busy}
          canManageBindings={canManageBindings}
        />
      ) : (
        <PostboxWorkspace
          postboxes={postboxes}
          selected={selectedPostbox}
          onSelect={setSelectedPostboxId}
          onArchive={setArchiveTarget}
          busy={busy}
        />
      )}

      <TemplateDialog
        open={templateDialogOpen}
        draft={templateDraft}
        units={units}
        functionTypes={functionTypes}
        unitTypes={unitTypes}
        busy={busy}
        onChange={setTemplateDraft}
        onClose={() => setTemplateDialogOpen(false)}
        onSave={() => void saveTemplate()}
      />
      <ExactPostboxDialog
        open={exactDialogOpen}
        draft={exactDraft}
        units={units}
        busy={busy}
        onChange={setExactDraft}
        onClose={() => setExactDialogOpen(false)}
        onSave={() => void saveExact()}
      />
      <MaterializeDialog
        open={materializeDialogOpen}
        draft={materializeDraft}
        template={templates.find((item) => item.id === materializeDraft.templateId) ?? null}
        units={units}
        busy={busy}
        onChange={setMaterializeDraft}
        onClose={() => setMaterializeDialogOpen(false)}
        onSave={() => void materialize()}
      />
      <ConfirmDialog
        open={Boolean(archiveTarget)}
        title="Archive Postbox"
        message={
          archiveTarget
            ? `Archive "${archiveTarget.name}"? Its messages and delivery evidence remain retained, but the address stops accepting new delivery.`
            : ""
        }
        confirmLabel="Archive"
        tone="danger"
        busy={busy}
        onConfirm={() => void confirmArchive()}
        onCancel={() => setArchiveTarget(null)}
      />
    </AdminPageLayout>
  );
}

function TemplateWorkspace({
  templates,
  selected,
  onSelect,
  onRevise,
  onPublish,
  onRetire,
  onMaterialize,
  busy,
  canManageBindings
}: {
  templates: PostboxTemplate[];
  selected: PostboxTemplate | null;
  onSelect: (id: string) => void;
  onRevise: (template: PostboxTemplate) => void;
  onPublish: () => void;
  onRetire: () => void;
  onMaterialize: (template: PostboxTemplate) => void;
  busy: boolean;
  canManageBindings: boolean;
}) {
  const revision = selected ? currentRevision(selected) : null;
  return (
    <div className="postbox-admin-workspace">
      <aside className="postbox-admin-list">
        {!templates.length ? <p className="postbox-note">No Postbox templates.</p> : null}
        {templates.length ? (
          <SelectionList label="Postbox templates">
            {templates.map((template) => (
              <SelectionListItem
                key={template.id}
                selected={selected?.id === template.id}
                onClick={() => onSelect(template.id)}
              >
                <span className="postbox-item-title">
                  <strong>{template.name}</strong>
                  <StatusBadge status={template.status} />
                </span>
                <span className="postbox-item-context">
                  {template.slug} · revision {template.current_revision}
                </span>
              </SelectionListItem>
            ))}
          </SelectionList>
        ) : null}
      </aside>
      <section className="postbox-admin-detail">
        {selected && revision ? (
          <>
            <div className="postbox-admin-detail-heading">
              <div>
                <span className="postbox-detail-kicker">Template</span>
                <h2>{selected.name}</h2>
                <p>{selected.description || "No description."}</p>
              </div>
              <div className="button-row compact-actions">
                <Button onClick={() => onRevise(selected)} disabled={busy || selected.status === "retired"}>
                  <Pencil size={16} /> New revision
                </Button>
                <Button onClick={onPublish} disabled={busy || selected.status === "retired" || Boolean(revision.published_at)}>
                  <Save size={16} /> Publish
                </Button>
                {canManageBindings ? (
                  <Button onClick={() => onMaterialize(selected)} disabled={busy || selected.status !== "published"}>
                    <Rocket size={16} /> Resolve address
                  </Button>
                ) : null}
                <Button variant="danger" onClick={onRetire} disabled={busy || selected.status === "retired"}>
                  <Trash2 size={16} /> Retire
                </Button>
              </div>
            </div>
            <dl className="postbox-admin-properties">
              <div><dt>Revision</dt><dd>{revision.revision}{revision.published_at ? " · published" : " · draft"}</dd></div>
              <div><dt>Function type</dt><dd>{revision.function_type_id || "Any function type"}</dd></div>
              <div><dt>Scope</dt><dd>{revision.scope_kind}{revision.scope_id ? ` · ${revision.scope_id}` : ""}</dd></div>
              <div><dt>Classification</dt><dd>{revision.classification}</dd></div>
              <div><dt>Vacant delivery</dt><dd>{revision.allow_vacant_delivery ? "Accepted" : "Blocked"}</dd></div>
              <div><dt>Encryption</dt><dd>{revision.encryption_profile}</dd></div>
              <div><dt>Name pattern</dt><dd>{revision.name_pattern}</dd></div>
              <div><dt>Address pattern</dt><dd>{revision.address_pattern}</dd></div>
            </dl>
            <div className="postbox-revision-history">
              <h3>Immutable revisions</h3>
              {selected.revisions.map((item) => (
                <div key={item.id}>
                  <strong>Revision {item.revision}</strong>
                  <span>{item.classification} · {item.scope_kind}</span>
                  <StatusBadge
                    status={item.published_at ? "published" : "draft"}
                    label={item.published_at ? "Published" : "Draft"}
                  />
                </div>
              ))}
            </div>
          </>
        ) : (
          <div className="postbox-empty">
            <Boxes size={24} />
            <strong>Select a template</strong>
            <p>Published revisions lazily resolve stable unit-specific addresses.</p>
          </div>
        )}
      </section>
    </div>
  );
}

function PostboxWorkspace({
  postboxes,
  selected,
  onSelect,
  onArchive,
  busy
}: {
  postboxes: PostboxDirectoryItem[];
  selected: PostboxDirectoryItem | null;
  onSelect: (id: string) => void;
  onArchive: (postbox: PostboxDirectoryItem) => void;
  busy: boolean;
}) {
  return (
    <div className="postbox-admin-workspace">
      <aside className="postbox-admin-list">
        {!postboxes.length ? <p className="postbox-note">No materialized Postboxes.</p> : null}
        {postboxes.length ? (
          <SelectionList label="Materialized Postboxes">
            {postboxes.map((postbox) => (
              <SelectionListItem
                key={postbox.id}
                selected={selected?.id === postbox.id}
                onClick={() => onSelect(postbox.id)}
              >
                <span className="postbox-item-title">
                  <strong>{postbox.name}</strong>
                  <StatusBadge status={postbox.status} />
                </span>
                <span className="postbox-item-context">
                  {postbox.organization_unit_name} · {postbox.function_name}
                </span>
              </SelectionListItem>
            ))}
          </SelectionList>
        ) : null}
      </aside>
      <section className="postbox-admin-detail">
        {selected ? (
          <>
            <div className="postbox-admin-detail-heading">
              <div>
                <span className="postbox-detail-kicker">Postbox</span>
                <h2>{selected.name}</h2>
                <p>{selected.address}</p>
              </div>
              <Button
                variant="danger"
                onClick={() => onArchive(selected)}
                disabled={busy || selected.status !== "active"}
              >
                <Archive size={16} /> Archive
              </Button>
            </div>
            <dl className="postbox-admin-properties">
              <div><dt>Organization unit</dt><dd>{selected.organization_unit_name || "None"}</dd></div>
              <div><dt>Function</dt><dd>{selected.function_name || "None"}</dd></div>
              <div><dt>Address key</dt><dd>{selected.address_key}</dd></div>
              <div><dt>Classification</dt><dd>{selected.classification}</dd></div>
              <div><dt>Current holders</dt><dd>{selected.holder_count}</dd></div>
              <div><dt>Vacancy</dt><dd>{selected.vacant ? "Vacant" : "Staffed"}</dd></div>
              <div><dt>Context</dt><dd>{selected.context_key || "None"}</dd></div>
              <div><dt>Template revision</dt><dd>{selected.template_revision_id || "Exact Postbox"}</dd></div>
            </dl>
          </>
        ) : (
          <div className="postbox-empty">
            <Inbox size={24} />
            <strong>Select a Postbox</strong>
            <p>Materialized Postboxes remain durable through vacancy and reassignment.</p>
          </div>
        )}
      </section>
    </div>
  );
}

function TemplateDialog({
  open,
  draft,
  units,
  functionTypes,
  unitTypes,
  busy,
  onChange,
  onClose,
  onSave
}: {
  open: boolean;
  draft: TemplateDraft;
  units: PostboxOrganizationUnit[];
  functionTypes: Array<{ id: string; name: string }>;
  unitTypes: Array<{ id: string; example: string }>;
  busy: boolean;
  onChange: (draft: TemplateDraft) => void;
  onClose: () => void;
  onSave: () => void;
}) {
  const isRevision = Boolean(draft.templateId);
  const scopeOptions = draft.scope_kind === "unit_type"
    ? unitTypes.map((item) => ({ id: item.id, label: `${item.id} (${item.example})` }))
    : units.map((unit) => ({ id: unit.id, label: unit.name }));
  const valid =
    draft.name.trim() &&
    draft.slug.trim() &&
    draft.name_pattern.trim() &&
    draft.address_pattern.trim() &&
    (draft.scope_kind === "tenant" || Boolean(draft.scope_id));
  return (
    <Dialog
      open={open}
      title={isRevision ? "Create template revision" : "New Postbox template"}
      className="postbox-dialog postbox-template-dialog"
      onClose={onClose}
      closeDisabled={busy}
      footer={
        <div className="button-row compact-actions">
          <Button onClick={onClose} disabled={busy}>Cancel</Button>
          <Button variant="primary" onClick={onSave} disabled={busy || !valid}>
            {isRevision ? "Create revision" : "Create draft"}
          </Button>
        </div>
      }
    >
      <div className="postbox-form-grid two-columns">
        <FormField label="Name">
          <input
            value={draft.name}
            disabled={isRevision}
            onChange={(event) => onChange({ ...draft, name: event.target.value })}
          />
        </FormField>
        <FormField label="Slug">
          <input
            value={draft.slug}
            disabled={isRevision}
            onChange={(event) => onChange({ ...draft, slug: event.target.value })}
          />
        </FormField>
        <FormField label="Description">
          <input
            value={draft.description || ""}
            disabled={isRevision}
            onChange={(event) => onChange({ ...draft, description: event.target.value })}
          />
        </FormField>
        <FormField label="Function type">
          <select
            value={draft.function_type_id || ""}
            onChange={(event) => onChange({
              ...draft,
              function_type_id: event.target.value || null
            })}
          >
            <option value="">Any function type</option>
            {functionTypes.map((item) => (
              <option key={item.id} value={item.id}>{item.name} · {item.id}</option>
            ))}
          </select>
        </FormField>
        <FormField label="Scope">
          <select
            value={draft.scope_kind}
            onChange={(event) => {
              const scope_kind = event.target.value as TemplateDraft["scope_kind"];
              onChange({
                ...draft,
                scope_kind,
                scope_id: scope_kind === "tenant" ? null : ""
              });
            }}
          >
            <option value="tenant">Tenant</option>
            <option value="unit">One unit</option>
            <option value="subtree">Unit subtree</option>
            <option value="unit_type">Unit type</option>
          </select>
        </FormField>
        {draft.scope_kind !== "tenant" ? (
          <FormField label="Scope target">
            <select
              value={draft.scope_id || ""}
              onChange={(event) => onChange({ ...draft, scope_id: event.target.value || null })}
            >
              <option value="">Select target</option>
              {scopeOptions.map((item) => (
                <option key={item.id} value={item.id}>{item.label}</option>
              ))}
            </select>
          </FormField>
        ) : <div />}
        <FormField label="Name pattern">
          <input
            value={draft.name_pattern}
            onChange={(event) => onChange({ ...draft, name_pattern: event.target.value })}
          />
        </FormField>
        <FormField label="Address pattern">
          <input
            value={draft.address_pattern}
            onChange={(event) => onChange({ ...draft, address_pattern: event.target.value })}
          />
        </FormField>
        <FormField label="Classification">
          <input
            value={draft.classification}
            onChange={(event) => onChange({ ...draft, classification: event.target.value })}
          />
        </FormField>
        <div className="postbox-toggle-field">
          <ToggleSwitch
            label="Accept delivery while vacant"
            checked={draft.allow_vacant_delivery}
            onChange={(checked) => onChange({ ...draft, allow_vacant_delivery: checked })}
          />
        </div>
      </div>
      <p className="postbox-form-note">
        Available pattern variables include template, unit, function, and optional context names or slugs. Published revisions are immutable.
      </p>
    </Dialog>
  );
}

function ExactPostboxDialog({
  open,
  draft,
  units,
  busy,
  onChange,
  onClose,
  onSave
}: {
  open: boolean;
  draft: ExactDraft;
  units: PostboxOrganizationUnit[];
  busy: boolean;
  onChange: (draft: ExactDraft) => void;
  onClose: () => void;
  onSave: () => void;
}) {
  const unit = units.find((item) => item.id === draft.organization_unit_id);
  return (
    <Dialog
      open={open}
      title="New exact Postbox"
      className="postbox-dialog"
      onClose={onClose}
      closeDisabled={busy}
      footer={
        <div className="button-row compact-actions">
          <Button onClick={onClose} disabled={busy}>Cancel</Button>
          <Button
            variant="primary"
            onClick={onSave}
            disabled={busy || !draft.name.trim() || !draft.organization_unit_id || !draft.function_id}
          >
            Create Postbox
          </Button>
        </div>
      }
    >
      <div className="postbox-form-grid two-columns">
        <FormField label="Name">
          <input value={draft.name} onChange={(event) => onChange({ ...draft, name: event.target.value })} />
        </FormField>
        <FormField label="Address key">
          <input value={draft.address_key || ""} placeholder="Generated when empty" onChange={(event) => onChange({ ...draft, address_key: event.target.value })} />
        </FormField>
        <FormField label="Organization unit">
          <select
            value={draft.organization_unit_id}
            onChange={(event) => {
              const nextUnit = units.find((item) => item.id === event.target.value);
              onChange({
                ...draft,
                organization_unit_id: event.target.value,
                function_id: nextUnit?.functions[0]?.id ?? ""
              });
            }}
          >
            <option value="">Select unit</option>
            {units.filter((item) => item.functions.length).map((item) => (
              <option key={item.id} value={item.id}>{item.name}</option>
            ))}
          </select>
        </FormField>
        <FormField label="Function">
          <select value={draft.function_id} onChange={(event) => onChange({ ...draft, function_id: event.target.value })}>
            <option value="">Select function</option>
            {(unit?.functions || []).map((fn) => (
              <option key={fn.id} value={fn.id}>{fn.name}</option>
            ))}
          </select>
        </FormField>
        <FormField label="Classification">
          <input value={draft.classification} onChange={(event) => onChange({ ...draft, classification: event.target.value })} />
        </FormField>
        <FormField label="Description">
          <input value={draft.description || ""} onChange={(event) => onChange({ ...draft, description: event.target.value })} />
        </FormField>
      </div>
    </Dialog>
  );
}

function MaterializeDialog({
  open,
  draft,
  template,
  units,
  busy,
  onChange,
  onClose,
  onSave
}: {
  open: boolean;
  draft: MaterializeDraft;
  template: PostboxTemplate | null;
  units: PostboxOrganizationUnit[];
  busy: boolean;
  onChange: (draft: MaterializeDraft) => void;
  onClose: () => void;
  onSave: () => void;
}) {
  const revision = template ? currentRevision(template) : null;
  const compatible = compatibleTargets(units, revision?.function_type_id);
  const unit = compatible.find((item) => item.id === draft.organization_unit_id);
  return (
    <Dialog
      open={open}
      title={`Resolve address${template ? ` · ${template.name}` : ""}`}
      className="postbox-dialog"
      onClose={onClose}
      closeDisabled={busy}
      footer={
        <div className="button-row compact-actions">
          <Button onClick={onClose} disabled={busy}>Cancel</Button>
          <Button variant="primary" onClick={onSave} disabled={busy || !draft.organization_unit_id || !draft.function_id}>
            Resolve address
          </Button>
        </div>
      }
    >
      <div className="postbox-form-grid">
        <FormField label="Organization unit">
          <select
            value={draft.organization_unit_id}
            onChange={(event) => {
              const nextUnit = compatible.find((item) => item.id === event.target.value);
              onChange({
                ...draft,
                organization_unit_id: event.target.value,
                function_id: nextUnit?.functions[0]?.id ?? ""
              });
            }}
          >
            <option value="">Select unit</option>
            {compatible.map((item) => (
              <option key={item.id} value={item.id}>{item.name}</option>
            ))}
          </select>
        </FormField>
        <FormField label="Function">
          <select value={draft.function_id} onChange={(event) => onChange({ ...draft, function_id: event.target.value })}>
            <option value="">Select function</option>
            {(unit?.functions || []).map((fn) => (
              <option key={fn.id} value={fn.id}>{fn.name}</option>
            ))}
          </select>
        </FormField>
        <FormField label="Optional case or service context">
          <input value={draft.context_key} onChange={(event) => onChange({ ...draft, context_key: event.target.value })} />
        </FormField>
      </div>
    </Dialog>
  );
}

function currentRevision(template: PostboxTemplate) {
  return template.revisions.find((revision) => revision.revision === template.current_revision)
    ?? template.revisions.at(-1)
    ?? null;
}

function revisionPayload(draft: TemplateDraft): PostboxTemplateRevisionPayload {
  return {
    function_type_id: draft.function_type_id || null,
    scope_kind: draft.scope_kind,
    scope_id: draft.scope_kind === "tenant" ? null : draft.scope_id || null,
    name_pattern: draft.name_pattern,
    address_pattern: draft.address_pattern,
    classification: draft.classification,
    allow_vacant_delivery: draft.allow_vacant_delivery
  };
}

function compatibleTargets(
  units: PostboxOrganizationUnit[],
  functionTypeId?: string | null
): PostboxOrganizationUnit[] {
  return units
    .map((unit) => ({
      ...unit,
      functions: functionTypeId
        ? unit.functions.filter((fn) => fn.function_type_id === functionTypeId)
        : unit.functions
    }))
    .filter((unit) => unit.functions.length);
}

function errorMessage(error: unknown): string {
  return error instanceof Error ? error.message : "Postbox request failed";
}
