import { useMemo, useState } from "react";
import { Link } from "react-router-dom";
import { usePlatformModuleInstalled } from "@govoplan/core-webui";
import type { ApiSettings } from "../../types";
import { Button } from "@govoplan/core-webui";
import { Card } from "@govoplan/core-webui";
import CampaignDraftPageScaffold from "./components/CampaignDraftPageScaffold";
import { useCampaignWorkspaceData } from "./hooks/useCampaignWorkspaceData";
import { useCampaignDraftEditor } from "./hooks/useCampaignDraftEditor";
import { asArray, asRecord, isAuditLockedVersion } from "./utils/campaignView";
import FieldValueInput from "./components/FieldValueInput";
import AttachmentRulesOverlay from "./components/AttachmentRulesOverlay";
import { getDraftFields } from "./utils/fieldDefinitions";
import { getIndividualAttachmentBasePaths, normalizeAttachmentBasePaths, normalizeAttachmentRules, normalizeAttachmentZipCollection, type AttachmentRule, type AttachmentZipCollection } from "./utils/attachments";
import { materializeRecipientImportWithAttachmentDefaults, type RecipientImportMode, type RecipientImportPreview } from "./utils/bulkImport";
import { buildTemplatePreviewContext } from "./utils/templatePlaceholders";
import { RecipientImportDialog } from "./RecipientDataPage";
import { addressesFromValue } from "@govoplan/core-webui";
import { DismissibleAlert, i18nMessage } from "@govoplan/core-webui";
import DataGrid, { type DataGridColumn } from "../../components/table/DataGrid";


export default function RecipientDetailsPage({ settings, campaignId }: {settings: ApiSettings;campaignId: string;}) {
  const filesModuleInstalled = usePlatformModuleInstalled("files");
  const { data, loading, error, reload, setError } = useCampaignWorkspaceData(settings, campaignId);
  const [importOpen, setImportOpen] = useState(false);
  const [recipientDataPage, setRecipientDataPage] = useState(1);
  const [recipientDataPageSize, setRecipientDataPageSize] = useState(10);

  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: "recipient-data",
    unsavedTitle: "i18n:govoplan-campaign.unsaved_recipient_data_changes.c810507e",
    unsavedMessage: "i18n:govoplan-campaign.recipient_field_values_or_attachments_have_unsav.49ab1870"
  });
  const entries = asRecord(displayDraft.entries);
  const inlineEntries = asArray(entries.inline).map(asRecord);
  const source = asRecord(entries.source);
  const fieldDefinitions = useMemo(() => getDraftFields(displayDraft), [displayDraft]);
  const attachmentSection = asRecord(displayDraft.attachments);
  const attachmentBasePaths = useMemo(() => normalizeAttachmentBasePaths(attachmentSection.base_paths, attachmentSection), [attachmentSection]);
  const individualAttachmentBasePaths = useMemo(() => getIndividualAttachmentBasePaths(attachmentBasePaths), [attachmentBasePaths]);
  const importBasePaths = useMemo(() => normalizeAttachmentBasePaths(attachmentSection.base_paths, attachmentSection, true), [attachmentSection]);
  const defaultImportBasePath = useMemo(() => importBasePaths.find((basePath) => basePath.allow_individual) ?? importBasePaths[0] ?? null, [importBasePaths]);
  const zipConfig = useMemo(() => normalizeAttachmentZipCollection(attachmentSection.zip), [attachmentSection.zip]);


  function replaceInlineEntries(nextEntries: Record<string, unknown>[]) {
    patch(["entries", "inline"], nextEntries);
  }

  function updateEntry(index: number, updater: (entry: Record<string, unknown>) => Record<string, unknown>) {
    const nextEntries = inlineEntries.map((entry, currentIndex) => currentIndex === index ? updater(entry) : entry);
    replaceInlineEntries(nextEntries);
  }

  function updateEntryField(index: number, field: string, value: unknown) {
    updateEntry(index, (entry) => ({
      ...entry,
      fields: {
        ...asRecord(entry.fields),
        [field]: value
      }
    }));
  }

  function updateEntryAttachments(index: number, attachments: AttachmentRule[]) {
    updateEntry(index, (entry) => ({ ...entry, attachments }));
  }

  function applyRecipientImport(preview: RecipientImportPreview, mode: RecipientImportMode) {
    if (locked || !draft) return;
    setDraft(materializeRecipientImportWithAttachmentDefaults(draft, preview, { mode }));
    markDirty();
    setImportOpen(false);
  }


  return (
    <>
    <CampaignDraftPageScaffold
      settings={settings}
      campaignId={campaignId}
      title="i18n:govoplan-campaign.recipient_data.c2baaf10"
      loading={loading}
      version={version}
      versions={data.versions}
      saveState={saveState}
      onReload={reload}
      onSave={() => saveDraft("manual")}
      dirty={dirty}
      locked={locked}
      draft={draft}
      error={error}
      localError={localError}
      currentVersionId={data.campaign?.current_version_id}>

          <Card title="i18n:govoplan-campaign.recipient_field_values_and_attachments.96e670ca" actions={<Button disabled={locked} onClick={() => setImportOpen(true)}>i18n:govoplan-campaign.import.d6fbc9d2</Button>}>
            {inlineEntries.length === 0 && !source.type && <p className="muted">i18n:govoplan-campaign.no_recipient_profiles_are_stored_in_the_current_.e9f9a224</p>}
            {inlineEntries.length === 0 && Boolean(source.type) &&
            <DismissibleAlert tone="info">i18n:govoplan-campaign.this_campaign_references_an_external_recipient_s.0d1ae252</DismissibleAlert>
            }
            {inlineEntries.length > 0 &&
            <div className="admin-table-surface recipient-data-table-surface">
                <DataGrid
                id={`campaign-${campaignId}-recipient-data`}
                rows={inlineEntries}
                columns={recipientDataColumns({ settings, campaignId, draft: displayDraft, locked, filesModuleInstalled, fieldDefinitions, individualAttachmentBasePaths, zipConfig, updateEntryAttachments, updateEntryField })}
                getRowKey={(entry, index) => String(entry.id || index)}
                emptyText="i18n:govoplan-campaign.no_recipient_data_found.a12be7d0"
                className="recipient-table-wrap recipient-data-table-wrap recipient-data-table"
                pagination={{
                  page: recipientDataPage,
                  pageSize: recipientDataPageSize,
                  pageSizeOptions: [10, 25, 50, 100, 250],
                  onPageChange: setRecipientDataPage,
                  onPageSizeChange: (pageSize) => {
                    setRecipientDataPageSize(pageSize);
                    setRecipientDataPage(1);
                  }
                }} />
              
              </div>
            }
          </Card>
    </CampaignDraftPageScaffold>

      {importOpen &&
      <RecipientImportDialog
        settings={settings}
        campaignId={campaignId}
        existingEntries={inlineEntries}
        existingFields={fieldDefinitions}
        defaultAttachmentBasePath={defaultImportBasePath}
        onCancel={() => setImportOpen(false)}
        onImport={applyRecipientImport} />

      }
    </>);

}

type RecipientDataColumnContext = {
  settings: ApiSettings;
  campaignId: string;
  draft: Record<string, unknown>;
  locked: boolean;
  filesModuleInstalled: boolean;
  fieldDefinitions: ReturnType<typeof getDraftFields>;
  individualAttachmentBasePaths: ReturnType<typeof getIndividualAttachmentBasePaths>;
  zipConfig: AttachmentZipCollection;
  updateEntryAttachments: (index: number, attachments: AttachmentRule[]) => void;
  updateEntryField: (index: number, field: string, value: unknown) => void;
};

function recipientDataColumns({ settings, campaignId, draft, locked, filesModuleInstalled, fieldDefinitions, individualAttachmentBasePaths, zipConfig, updateEntryAttachments, updateEntryField }: RecipientDataColumnContext): DataGridColumn<Record<string, unknown>>[] {
  return [
  { id: "number", header: "#", width: 70, sortable: true, filterType: "integer", sticky: "start", render: (_entry, index) => <span className="mono-small recipient-index-cell">{index + 1}</span>, value: (_entry, index) => index + 1 },
  {
    id: "recipient",
    header: "i18n:govoplan-campaign.recipient.90343260",
    width: 260,
    resizable: true,
    sortable: true,
    filterable: true,
    sticky: "start",
    render: (entry) =>
    <Link className="recipient-data-identity" to="../recipients" title="i18n:govoplan-campaign.open_recipient_address_profile.f7daa676">
          <span className="recipient-data-address">{firstRecipientEmail(entry) || "i18n:govoplan-campaign.no_to_address.683350f9"}</span>
          {extraRecipientCount(entry) > 0 && <span className="recipient-extra-bubble">+{extraRecipientCount(entry)}</span>}
        </Link>,

    value: firstRecipientEmail
  },
  {
    id: "attachments",
    header: "i18n:govoplan-campaign.attachments.6771ade6",
    width: 180,
    filterable: true,
    render: (entry, index) => {
      const attachments = normalizeAttachmentRules(entry.attachments);
      return (
        <AttachmentRulesOverlay
          title={i18nMessage("i18n:govoplan-campaign.attachments_for_recipient_value.9a8df82d", { value0: index + 1 })}
          rules={attachments}
          settings={settings}
          campaignId={campaignId}
          disabled={locked}
          buttonLabel={`entries: ${attachments.length}`}
          basePaths={individualAttachmentBasePaths}
          zipConfig={zipConfig}
          filesModuleInstalled={filesModuleInstalled}
          previewContext={buildTemplatePreviewContext(draft, entry)}
          onChange={(rules) => updateEntryAttachments(index, rules)} />);


    },
    value: (entry) => normalizeAttachmentRules(entry.attachments).map((rule) => `${rule.label ?? ""} ${rule.file_filter ?? ""}`).join(", ")
  },
  ...fieldDefinitions.map((field): DataGridColumn<Record<string, unknown>> => ({
    id: `field-${field.name}`,
    header: field.label || field.name,
    width: 190,
    resizable: true,
    sortable: true,
    filterable: true,
    filterType: field.type === "integer" ? "integer" : field.type === "double" ? "number" : field.type === "date" ? "date" : "text",
    render: (entry, index) => {
      const fields = asRecord(entry.fields);
      return (
        <FieldValueInput
          className="recipient-field-input"
          fieldType={field.type}
          value={fields[field.name]}
          disabled={locked || field.can_override === false}
          placeholder={field.can_override === false ? "i18n:govoplan-campaign.uses_global_value.98eae5e0" : undefined}
          onChange={(value) => updateEntryField(index, field.name, value)} />);


    },
    value: (entry) => String(asRecord(entry.fields)[field.name] ?? "")
  }))];

}

function firstRecipientEmail(entry: Record<string, unknown>): string {
  return (addressesFromValue(entry.to)[0] ?? addressesFromValue(entry.recipient)[0] ?? addressesFromValue(entry)[0])?.email ?? "";
}

function extraRecipientCount(entry: Record<string, unknown>): number {
  const count = addressesFromValue(entry.to).length;
  return Math.max(0, count - 1);
}
