import { useEffect, useMemo, useState } from "react";
import { ExternalLink, LockKeyhole, LockOpen } from "lucide-react";
import { Link } from "react-router-dom";
import type { ApiSettings } from "../../types";
import { Button } from "@govoplan/core-webui";
import { Card } from "@govoplan/core-webui";
import { ConfirmDialog } from "@govoplan/core-webui";
import { FormField } from "@govoplan/core-webui";
import { LoadingFrame } from "@govoplan/core-webui";
import { MetricCard } from "@govoplan/core-webui";
import { PageTitle } from "@govoplan/core-webui";
import { StatusBadge } from "@govoplan/core-webui";
import { DismissibleAlert, TableActionGroup, i18nMessage, useGuardedNavigate, useUnsavedDraftGuard } from "@govoplan/core-webui";
import { DataGrid, type DataGridColumn } from "@govoplan/core-webui";
import {
  lockCampaignVersionPermanently,
  lockCampaignVersionTemporarily,
  unlockCampaignVersionUserLock,
  updateCampaignMetadata,
  type CampaignVersionDetail,
  type CampaignVersionListItem } from
"../../api/campaigns";
import { useCampaignWorkspaceData } from "./hooks/useCampaignWorkspaceData";
import {
  asArray,
  asRecord,
  canUnlockValidationVersion,
  formatDateTime,
  getCampaignJson,
  isFinalLockedVersion,
  isPermanentUserLockedVersion,
  isTemporaryUserLockedVersion,
  isVersionReadyForDelivery,
  summaryValue } from
"./utils/campaignView";
import { buildUndefinedPlaceholders, extractTemplatePlaceholders, recipientAddressTemplateFieldOptions } from "./utils/templatePlaceholders";

const campaignModeOptions = ["draft", "test", "send"];
type LockAction = "temporary" | "unlock" | "permanent";
type PendingLockAction = {version: CampaignVersionListItem;action: LockAction;} | null;

export default function CampaignOverviewPage({ settings, campaignId }: {settings: ApiSettings;campaignId: string;}) {
  const navigate = useGuardedNavigate();
  const { data, loading, error, reload, setError } = useCampaignWorkspaceData(settings, campaignId, { includeSummary: true });
  const campaign = data.campaign;
  const versions = useMemo(() => data.versions.slice().sort((a, b) => (b.version_number ?? 0) - (a.version_number ?? 0)), [data.versions]);
  const [identity, setIdentity] = useState({ external_id: "", name: "", status: "", description: "" });
  const [identityDirty, setIdentityDirty] = useState(false);
  const [savingIdentity, setSavingIdentity] = useState(false);
  const [pendingLockAction, setPendingLockAction] = useState<PendingLockAction>(null);
  const [lockBusy, setLockBusy] = useState(false);
  const [message, setMessage] = useState("");
  const versionMetrics = useMemo(() => campaignVersionMetrics(data.currentVersion), [data.currentVersion]);

  useUnsavedDraftGuard({
    dirty: identityDirty,
    onSave: saveIdentity,
    onDiscard: () => {
      if (!campaign) return;
      setIdentity({
        external_id: campaign.external_id ?? "",
        name: campaign.name ?? "",
        status: campaign.status ?? "",
        description: campaign.description ?? ""
      });
      setIdentityDirty(false);
    }
  });

  useEffect(() => {
    if (!campaign || identityDirty) return;
    setIdentity({
      external_id: campaign.external_id ?? "",
      name: campaign.name ?? "",
      status: campaign.status ?? "",
      description: campaign.description ?? ""
    });
  }, [campaign, identityDirty]);

  function patchIdentity(key: keyof typeof identity, value: string) {
    setIdentity((current) => ({ ...current, [key]: value }));
    setIdentityDirty(true);
    setMessage("");
  }

  async function saveIdentity(): Promise<boolean> {
    if (!campaign || savingIdentity || !identityDirty) return false;
    setSavingIdentity(true);
    setError("");
    setMessage("");
    try {
      await updateCampaignMetadata(settings, campaign.id, {
        external_id: identity.external_id,
        name: identity.name,
        status: identity.status,
        description: identity.description
      });
      setIdentityDirty(false);
      await reload();
      return true;
    } catch (err) {
      setError(err instanceof Error ? err.message : String(err));
      return false;
    } finally {
      setSavingIdentity(false);
    }
  }

  async function applyLockAction() {
    const pending = pendingLockAction;
    if (!pending || lockBusy) return;
    setLockBusy(true);
    setError("");
    setMessage("");
    try {
      if (pending.action === "temporary") {
        await lockCampaignVersionTemporarily(settings, campaignId, pending.version.id);
        setMessage(i18nMessage("i18n:govoplan-campaign.version_value_temporarily_locked.4ed4ffa7", { value0: pending.version.version_number }));
      } else if (pending.action === "unlock") {
        await unlockCampaignVersionUserLock(settings, campaignId, pending.version.id);
        setMessage(i18nMessage("i18n:govoplan-campaign.temporary_lock_removed_from_version_value.9a05bcfb", { value0: pending.version.version_number }));
      } else {
        await lockCampaignVersionPermanently(settings, campaignId, pending.version.id);
        setMessage(i18nMessage("i18n:govoplan-campaign.version_value_permanently_locked.60595f45", { value0: pending.version.version_number }));
      }
      setPendingLockAction(null);
      await reload();
    } catch (err) {
      setError(err instanceof Error ? err.message : String(err));
    } finally {
      setLockBusy(false);
    }
  }

  async function discardOverview() {
    if (campaign) {
      setIdentity({
        external_id: campaign.external_id ?? "",
        name: campaign.name ?? "",
        status: campaign.status ?? "",
        description: campaign.description ?? ""
      });
      setIdentityDirty(false);
    }
    await reload({ force: true });
  }

  return (
    <div className="content-pad workspace-data-page">
      <div className="page-heading split workspace-heading">
        <div>
          <PageTitle loading={loading}>{campaign?.name || "i18n:govoplan-campaign.overview.0efc2e6b"}</PageTitle>
          <p className="mono-small">i18n:govoplan-campaign.campaign_overview_version_independent_identity_a.ebaf1113</p>
        </div>
        <div className="button-row compact-actions">
          <Button onClick={() => void discardOverview()} disabled={loading || savingIdentity || lockBusy}>Discard</Button>
          <Button variant="primary" onClick={() => void saveIdentity()} disabled={!campaign || !identityDirty || savingIdentity}>{savingIdentity ? "i18n:govoplan-campaign.saving.56a2285c" : "i18n:govoplan-campaign.save.efc007a3"}</Button>
        </div>
      </div>

      {error && <DismissibleAlert tone="danger" resetKey={error} floating>{error}</DismissibleAlert>}
      {message && <DismissibleAlert tone="success" resetKey={message} floating>{message}</DismissibleAlert>}

      <LoadingFrame loading={loading} label="i18n:govoplan-campaign.loading_campaign_overview.ffa1adf0">
        <div className="metric-grid campaign-overview-metrics">
          <MetricCard label="i18n:govoplan-campaign.queueable.ea776f8d" value={data.summary?.cards?.queueable ?? "—"} tone="good" detail="i18n:govoplan-campaign.ready_or_warning.4dcce676" />
          <MetricCard label="i18n:govoplan-campaign.needs_attention.a126722e" value={data.summary?.cards?.needs_attention ?? "—"} tone="warning" detail="i18n:govoplan-campaign.review_first.741ac781" />
          <MetricCard label="i18n:govoplan-campaign.sent.35f49dcf" value={data.summary?.cards?.sent ?? "—"} tone="info" detail="i18n:govoplan-campaign.smtp_success.3591a856" />
          <MetricCard label="i18n:govoplan-campaign.failed.09fef5d8" value={data.summary?.cards?.failed ?? "—"} tone="danger" detail="i18n:govoplan-campaign.smtp_failures.00b33b85" />
        </div>

        <Card
          title="i18n:govoplan-campaign.campaign_identity.a00ca574"
          collapsible
          actions={<Link className="btn btn-secondary" to="wizard/create">i18n:govoplan-campaign.edit_with_wizard.672a7d1a</Link>}>
          <div className="form-grid campaign-identity-grid">
            <FormField label="i18n:govoplan-campaign.campaign_id.4c4ed79e">
              <input value={identity.external_id} onChange={(event) => patchIdentity("external_id", event.target.value)} />
            </FormField>
            <FormField label="i18n:govoplan-campaign.mode.a7b93d21">
              <select value={identity.status} onChange={(event) => patchIdentity("status", event.target.value)}>
                {campaignModeOptions.map((option) => <option key={option} value={option}>{option}</option>)}
              </select>
            </FormField>
            <FormField label="i18n:govoplan-campaign.name.709a2322">
              <input value={identity.name} onChange={(event) => patchIdentity("name", event.target.value)} />
            </FormField>
            <FormField label="i18n:govoplan-campaign.description.55f8ebc8">
              <textarea rows={4} value={identity.description} onChange={(event) => patchIdentity("description", event.target.value)} />
            </FormField>
          </div>
        </Card>

        <Card title="Versions" collapsible actions={<Link
          to={`send?version=${campaign?.current_version_id}`}
          className={`btn btn-primary`}
          aria-label={i18nMessage("i18n:govoplan-campaign.open_curent_version.cc1cd678", {})}
          title={i18nMessage("i18n:govoplan-campaign.open_curent_version.cc1cd678", {})}>

              i18n:govoplan-campaign.open.cf9b7706
            </Link>}>
          <div className="metric-grid inside campaign-versions-metrics">
            <MetricCard label="i18n:govoplan-campaign.version.2da600bf" value={data.currentVersion?.version_number ? `#${data.currentVersion.version_number}` : "—"} tone="neutral" />
            <MetricCard label="i18n:govoplan-campaign.fields.e8b68527" value={versionMetrics.fieldCount} tone="info" />
            <MetricCard label="i18n:govoplan-campaign.recipients.78cbf8eb" value={versionMetrics.recipientCount} tone="neutral" detail="i18n:govoplan-campaign.active_inline_recipients.8ba58f6e" />
            <MetricCard label="i18n:govoplan-campaign.template_health.22e14b59" value={versionMetrics.templateHealthValue} tone={versionMetrics.templateHealthTone} detail={versionMetrics.templateHealthDetail} />
          </div>
          <div className="metric-grid inside">
            <MetricCard label="i18n:govoplan-campaign.validation_errors.e54ca4fe" value={summaryValue(data.currentVersion?.validation_summary, ["error_count", "errors", "blocked"])} />
            <MetricCard label="i18n:govoplan-campaign.warnings.1430f976" value={summaryValue(data.currentVersion?.validation_summary, ["warning_count", "warnings"])} />
            <MetricCard label="i18n:govoplan-campaign.built_messages.1fb804f2" value={summaryValue(data.currentVersion?.build_summary, ["built_count", "built", "messages_built"])} />
            <MetricCard label="i18n:govoplan-campaign.jobs_total.98da65bc" value={data.summary?.cards?.jobs_total ?? "—"} />
          </div>
          <div className="admin-table-surface version-history-table-surface">
            <DataGrid
              id={`campaign-${campaignId}-versions`}
              rows={versions}
              columns={versionColumns(setPendingLockAction, navigate, campaign?.current_version_id)}
              getRowKey={(version) => version.id}
              initialSort={{ columnId: "version", direction: "desc" }}
              emptyText="i18n:govoplan-campaign.no_versions_found.a8284e9e"
              className="version-history-table"
              rowClassName={(version) => version.id === data.currentVersion?.id ? "current-version-row" : undefined} />
            
          </div>
        </Card>
      </LoadingFrame>

      <ConfirmDialog
        open={Boolean(pendingLockAction)}
        title={lockDialogTitle(pendingLockAction)}
        message={lockDialogMessage(pendingLockAction)}
        confirmLabel={lockDialogLabel(pendingLockAction)}
        tone={pendingLockAction?.action === "unlock" ? "default" : "danger"}
        busy={lockBusy}
        onCancel={() => setPendingLockAction(null)}
        onConfirm={() => void applyLockAction()} />
      
    </div>);

}

type TemplateHealthTone = "neutral" | "good" | "warning" | "danger" | "info";

type CampaignVersionMetrics = {
  fieldCount: number;
  recipientCount: number;
  templateHealthValue: string;
  templateHealthTone: TemplateHealthTone;
  templateHealthDetail: string;
};

function campaignVersionMetrics(version: CampaignVersionDetail | null): CampaignVersionMetrics {
  const campaignJson = getCampaignJson(version);
  const fields = asArray(campaignJson.fields).map(asRecord);
  const entries = asRecord(campaignJson.entries);
  const inlineEntries = asArray(entries.inline).map(asRecord);
  const template = asRecord(campaignJson.template);
  const globalValues = asRecord(campaignJson.global_values);
  const bodyMode = normalizeTemplateBodyMode(textValue(template.body_mode, "both"));
  const subject = textValue(template.subject);
  const textBody = bodyMode !== "html" ? textValue(template.text) : "";
  const htmlBody = bodyMode !== "text" ? textValue(template.html) : "";
  const subjectOk = subject.trim().length > 0;
  const bodyOk = bodyMode === "html" ? htmlBody.trim().length > 0 : bodyMode === "text" ? textBody.trim().length > 0 : Boolean(textBody.trim() || htmlBody.trim());
  const localFieldNames = fields.map((field) => textValue(field.name || field.id)).filter(Boolean);
  const globalFieldNames = Object.keys(globalValues).filter(Boolean);
  const addressFieldNames = recipientAddressTemplateFieldOptions().map((field) => field.name);
  const localAvailableNames = new Set([...localFieldNames, ...addressFieldNames]);
  const globalAvailableNames = new Set(globalFieldNames);
  const allAvailableNames = new Set([...localAvailableNames, ...globalAvailableNames]);
  const placeholders = extractTemplatePlaceholders([subject, textBody, htmlBody].join("\n"));
  const undefinedPlaceholders = buildUndefinedPlaceholders(placeholders, allAvailableNames, {
    local: localAvailableNames,
    global: globalAvailableNames
  });
  const placeholdersOk = undefinedPlaceholders.length === 0;
  const score = [subjectOk, bodyOk, placeholdersOk].filter(Boolean).length;
  return {
    fieldCount: localFieldNames.length,
    recipientCount: inlineEntries.filter((entry) => entry.active !== false).length,
    templateHealthValue: `${score}/3`,
    templateHealthTone: score === 3 ? "good" : score === 2 ? "warning" : "danger",
    templateHealthDetail: [
    subjectOk ? "i18n:govoplan-campaign.subject_ok.3dbdc3ed" : "i18n:govoplan-campaign.subject_missing.f545bf65",
    bodyOk ? "i18n:govoplan-campaign.body_ok.cdb33005" : "i18n:govoplan-campaign.body_missing.bd58622f",
    placeholdersOk ? "i18n:govoplan-campaign.placeholders_ok.3a07f3bc" : `${undefinedPlaceholders.length} undefined`].
    join(" · ")
  };
}

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

function textValue(value: unknown, fallback = ""): string {
  return typeof value === "string" ? value : fallback;
}

function versionColumns(setPendingLockAction: (action: PendingLockAction) => void, navigate: (to: string) => void, currentVersionId?: string | null): DataGridColumn<CampaignVersionListItem>[] {
  return [
  { id: "version", header: "i18n:govoplan-campaign.version.2da600bf", width: 110, sortable: true, filterable: true, filterType: "integer", sticky: "start", render: (version) => `#${version.version_number}`, value: (version) => version.version_number ?? 0 },
  { id: "state", header: "i18n:govoplan-campaign.state.a7250206", width: 140, sortable: true, filterable: true, columnType: "from-list", list: { options: ["editing", "validated", "built", "approved", "queued", "sending", "sent", "completed", "partially_completed", "outcome_unknown", "failed", "partially_sent", "failed_partial", "cancelled", "archived"].map((value) => ({ value, label: value.replace(/_/g, " ") })), display: "pill" }, render: (version) => <StatusBadge status={version.workflow_state ?? "editing"} />, value: (version) => version.workflow_state ?? "editing" },
  { id: "lock", header: "i18n:govoplan-campaign.lock.891ebccd", width: 190, sortable: true, filterable: true, columnType: "from-list", list: { options: [{ value: "Current working version", label: "i18n:govoplan-campaign.current_working_version.eda99d70" }, { value: "Historical version", label: "i18n:govoplan-campaign.historical_version.8880931f" }, { value: "Temporarily locked", label: "i18n:govoplan-campaign.temporarily_locked.1716dc95" }, { value: "Permanently locked", label: "i18n:govoplan-campaign.permanently_locked.327d59fd" }, { value: "Delivery locked", label: "i18n:govoplan-campaign.delivery_locked.2b664305" }] }, render: (version) => versionLockLabel(version, currentVersionId), value: (version) => versionLockLabel(version, currentVersionId) },
  { id: "validation", header: "i18n:govoplan-campaign.validation.dd74d182", width: 170, sortable: true, filterable: true, columnType: "from-list", list: { options: [{ value: "Not validated", label: "i18n:govoplan-campaign.not_validated.11bb4178" }, { value: "Valid", label: "i18n:govoplan-campaign.valid.a4aefa35" }, { value: "Validation issues", label: "i18n:govoplan-campaign.validation_issues.528305b1" }] }, render: validationLabel, value: validationLabel },
  { id: "build", header: "i18n:govoplan-campaign.build.bbd80cf7", width: 140, sortable: true, filterable: true, columnType: "from-list", list: { options: [{ value: "Not built", label: "i18n:govoplan-campaign.not_built.88bbe87a" }, { value: "Built", label: "i18n:govoplan-campaign.built.a6ad3f82" }, { value: "Build issues", label: "i18n:govoplan-campaign.build_issues.3e03bf8e" }] }, render: buildLabel, value: buildLabel },
  { id: "updated", header: "i18n:govoplan-campaign.updated.f2f8570d", width: 190, sortable: true, filterable: true, filterType: "date", render: (version) => formatDateTime(version.updated_at), value: (version) => version.updated_at ?? "" },
  {
    id: "actions",
    header: "i18n:govoplan-campaign.actions.c3cd636a",
    width: 150,
    sticky: "end",
    render: (version) => {
      const isCurrent = version.id === currentVersionId;
      const temporarilyLocked = isCurrent && isTemporaryUserLockedVersion(version);
      const canTemporarilyLock = isCurrent && !temporarilyLocked && !isPermanentUserLockedVersion(version) && !isFinalLockedVersion(version) && !canUnlockValidationVersion(version) && !version.locked_at;
      return <TableActionGroup actions={[
        { id: "open", label: i18nMessage("i18n:govoplan-campaign.open_version_value.7ef53546", { value0: version.version_number }), icon: <ExternalLink aria-hidden="true" />, variant: isCurrent ? "primary" : "secondary", onClick: () => navigate(`send?version=${version.id}`) },
        { id: "unlock", label: "i18n:govoplan-campaign.unlock.1526a17e", icon: <LockOpen aria-hidden="true" />, applicable: temporarilyLocked, onClick: () => setPendingLockAction({ version, action: "unlock" }) },
        { id: "permanent-lock", label: "i18n:govoplan-campaign.lock_permanently.cc0ce9e7", icon: <LockKeyhole aria-hidden="true" />, variant: "danger", applicable: temporarilyLocked, onClick: () => setPendingLockAction({ version, action: "permanent" }) },
        { id: "temporary-lock", label: i18nMessage("i18n:govoplan-campaign.temporarily_lock_version_value.8019e581", { value0: version.version_number }), icon: <LockKeyhole aria-hidden="true" />, applicable: canTemporarilyLock, onClick: () => setPendingLockAction({ version, action: "temporary" }) }
      ]} />;

    }
  }];

}

function versionLockLabel(version: CampaignVersionListItem, currentVersionId?: string | null): string {
  if (currentVersionId && version.id !== currentVersionId) return "i18n:govoplan-campaign.historical_review_only.5afffe82";
  if (isTemporaryUserLockedVersion(version)) return "i18n:govoplan-campaign.temporary_user_lock.c2bda6a9";
  if (isPermanentUserLockedVersion(version)) return "i18n:govoplan-campaign.permanent_user_lock.9d5d8959";
  if (isFinalLockedVersion(version)) return "i18n:govoplan-campaign.permanent_delivery_lock.07932206";
  if (canUnlockValidationVersion(version)) return "i18n:govoplan-campaign.temporary_validation_lock.fdc5545d";
  if (version.locked_at) return "i18n:govoplan-campaign.temporarily_locked.1716dc95";
  return "i18n:govoplan-campaign.editable.b91faec0";
}

function validationLabel(version: CampaignVersionListItem): string {
  const validation = version.validation_summary ?? {};
  if (validation.ok === true && isVersionReadyForDelivery(version)) return "i18n:govoplan-campaign.passed.271d60f4";
  if (validation.ok === false) return "i18n:govoplan-campaign.needs_attention.a126722e";
  if (validation.ok === true) return "i18n:govoplan-campaign.passed_unavailable_while_user_locked.d6771ff4";
  return "i18n:govoplan-campaign.not_validated.11bb4178";
}

function buildLabel(version: CampaignVersionListItem): string {
  const build = version.build_summary ?? {};
  return String(build.built_count ?? build.ready_count ?? "i18n:govoplan-campaign.not_built.88bbe87a");
}

function lockDialogTitle(pending: PendingLockAction): string {
  if (pending?.action === "temporary") return "i18n:govoplan-campaign.temporarily_lock_version.8ccc5708";
  if (pending?.action === "unlock") return "i18n:govoplan-campaign.unlock_version.ebd2fd9a";
  if (pending?.action === "permanent") return "i18n:govoplan-campaign.lock_version_permanently.a8625753";
  return "i18n:govoplan-campaign.confirm_lock_action.617986ee";
}

function lockDialogMessage(pending: PendingLockAction): string {
  if (pending?.action === "temporary") {
    return "i18n:govoplan-campaign.this_makes_the_version_read_only_without_making_.9d86667b";
  }
  if (pending?.action === "unlock") {
    return "i18n:govoplan-campaign.this_removes_the_temporary_user_lock_and_makes_t.fdabd47a";
  }
  if (pending?.action === "permanent") {
    return "i18n:govoplan-campaign.this_lock_cannot_be_removed_by_any_role_the_vers.14ae9b80";
  }
  return "i18n:govoplan-campaign.continue.4e6302ed";
}

function lockDialogLabel(pending: PendingLockAction): string {
  if (pending?.action === "temporary") return "i18n:govoplan-campaign.lock_temporarily.3f91d346";
  if (pending?.action === "unlock") return "i18n:govoplan-campaign.unlock.1526a17e";
  if (pending?.action === "permanent") return "i18n:govoplan-campaign.lock_permanently.cc0ce9e7";
  return "i18n:govoplan-campaign.confirm.04a21221";
}
