import { useEffect, useMemo, useState } from "react";
import { useQuery } from "@tanstack/react-query";
import {
  ActionIcon,
  Alert,
  Box,
  Button,
  Divider,
  Group,
  Loader,
  Modal,
  Select,
  Stack,
  Text,
  Textarea,
  TextInput,
  Tooltip,
} from "@mantine/core";
import {
  ArrowDown,
  ArrowUp,
  FileText,
  Info,
  Lock,
  Plus,
  Trash2,
} from "lucide-react";
import type { Freight } from "@edr/types";

import { contractsService } from "@/services/contracts.service";

/** New client-side article id (server keeps whatever id we send). */
function newArticleId(): string {
  const c = globalThis.crypto;
  if (c && typeof c.randomUUID === "function") return c.randomUUID();
  return `art-${Date.now()}-${Math.floor(Math.random() * 1e6)}`;
}

interface EditableArticle {
  id: string;
  title: string;
  body: string;
}

export interface ContractDocumentEditorModalProps {
  opened: boolean;
  onClose: () => void;
  contractId: string;
  /**
   * "accept" — shown from the Accept-for-approval action: pick a validity window
   * and (optionally) edit the articles, then start the approval chain.
   * "edit" — re-edit the frozen articles of an already-accepted contract before
   * generating/regenerating its PDF.
   */
  mode: "accept" | "edit";
  /** Validity options (accept mode only). */
  validityOptions?: Array<{ value: string; label: string }>;
  validityLoading?: boolean;
  accepting?: boolean;
  saving?: boolean;
  onAccept?: (
    validityDays: number,
    snapshot: Freight.IContractDocumentSnapshot,
  ) => void;
  onSaveEdit?: (snapshot: Freight.IContractDocumentSnapshot) => void;
}

/**
 * Per-contract contract-document editor. Loads the resolved template (or this
 * contract's frozen snapshot) and lets staff add/remove/reorder/edit articles
 * for THIS contract only — it never writes back to the shared six templates.
 */
export function ContractDocumentEditorModal({
  opened,
  onClose,
  contractId,
  mode,
  validityOptions = [],
  validityLoading = false,
  accepting = false,
  saving = false,
  onAccept,
  onSaveEdit,
}: ContractDocumentEditorModalProps) {
  const { data: draft, isLoading } = useQuery({
    queryKey: ["contracts", contractId, "document-draft"],
    queryFn: () => contractsService.getContractDocumentDraft(contractId),
    enabled: opened && Boolean(contractId),
    // Always refetch the current draft when the dialog opens.
    staleTime: 0,
  });

  const [documentTitle, setDocumentTitle] = useState("");
  const [whereasClauses, setWhereasClauses] = useState<string[]>([]);
  const [articles, setArticles] = useState<EditableArticle[]>([]);
  const [validityDays, setValidityDays] = useState<string | null>(null);

  // Seed the editor from the loaded draft whenever the dialog (re)opens.
  useEffect(() => {
    if (!opened || !draft) return;
    setDocumentTitle(draft.documentTitle ?? "");
    setWhereasClauses(draft.whereasClauses ?? []);
    setArticles(
      (draft.articles ?? []).map((a) => ({
        id: a.id || newArticleId(),
        title: a.title,
        body: a.body,
      })),
    );
  }, [opened, draft]);

  // Default validity to the first configured option (accept mode).
  useEffect(() => {
    if (mode === "accept" && !validityDays && validityOptions.length > 0) {
      setValidityDays(validityOptions[0].value);
    }
  }, [mode, validityDays, validityOptions]);

  // Editing rights belong to the approver whose turn it is, so the server
  // decides per-caller — the client cannot derive this from the contract alone.
  const locked = mode === "edit" && !draft?.editableByMe;

  const moveArticle = (index: number, delta: number) => {
    setArticles((prev) => {
      const next = [...prev];
      const target = index + delta;
      if (target < 0 || target >= next.length) return prev;
      [next[index], next[target]] = [next[target], next[index]];
      return next;
    });
  };

  const updateArticle = (id: string, patch: Partial<EditableArticle>) =>
    setArticles((prev) =>
      prev.map((a) => (a.id === id ? { ...a, ...patch } : a)),
    );

  const removeArticle = (id: string) =>
    setArticles((prev) => prev.filter((a) => a.id !== id));

  const addArticle = () =>
    setArticles((prev) => [
      ...prev,
      { id: newArticleId(), title: "", body: "" },
    ]);

  const buildSnapshot = (): Freight.IContractDocumentSnapshot => ({
    code: draft?.code ?? null,
    name: draft?.name ?? null,
    documentTitle: documentTitle.trim() || null,
    whereasClauses: whereasClauses
      .map((c) => c.trim())
      .filter((c) => c.length > 0),
    articles: articles
      .filter((a) => a.title.trim().length > 0 || a.body.trim().length > 0)
      .map((a, index) => ({
        id: a.id,
        title: a.title.trim(),
        body: a.body,
        order: index + 1,
      })),
  });

  const hasArticles = useMemo(
    () => articles.some((a) => a.title.trim() || a.body.trim()),
    [articles],
  );

  const submit = () => {
    const snapshot = buildSnapshot();
    if (mode === "accept") {
      const days = Number(validityDays);
      if (!days) return;
      onAccept?.(days, snapshot);
    } else {
      onSaveEdit?.(snapshot);
    }
  };

  const submitting = accepting || saving;
  const canSubmit =
    hasArticles &&
    !locked &&
    (mode === "edit" || Boolean(validityDays)) &&
    !submitting;

  return (
    <Modal
      opened={opened}
      onClose={onClose}
      size="xl"
      centered
      radius="md"
      title={
        <Group gap="xs">
          <FileText size={18} />
          <Text fw={700}>
            {mode === "accept"
              ? "Review contract document & accept"
              : "Edit contract document"}
          </Text>
        </Group>
      }
    >
      {isLoading ? (
        <Group justify="center" py="xl">
          <Loader size="sm" color="gray" />
          <Text size="sm" c="dimmed">
            Loading document…
          </Text>
        </Group>
      ) : (
        <Stack gap="md">
          <Alert
            variant="light"
            color={locked ? "orange" : "blue"}
            icon={locked ? <Lock size={16} /> : <Info size={16} />}
          >
            {locked
              ? draft?.nextApproverRole
                ? `Only the current approver (${draft.nextApproverRole}) can edit this document right now.`
                : "This document can no longer be edited — the contract has advanced beyond approval."
              : "Edits apply to THIS contract only. The six shared templates are never changed."}
          </Alert>

          <TextInput
            label="Document title"
            placeholder="e.g. Bulk Cargo Transportation and Customs Clearance Services"
            value={documentTitle}
            onChange={(e) => setDocumentTitle(e.currentTarget.value)}
            disabled={locked}
          />

          <Box>
            <Group justify="space-between" mb={6}>
              <Text size="sm" fw={600}>
                WHEREAS recitals
              </Text>
              <Button
                size="compact-xs"
                variant="light"
                color="gray"
                leftSection={<Plus size={13} />}
                disabled={locked}
                onClick={() => setWhereasClauses((p) => [...p, ""])}
              >
                Add recital
              </Button>
            </Group>
            {whereasClauses.length === 0 ? (
              <Text size="xs" c="dimmed">
                No recitals.
              </Text>
            ) : (
              <Stack gap="xs">
                {whereasClauses.map((clause, i) => (
                  <Group key={i} gap="xs" wrap="nowrap" align="flex-start">
                    <Textarea
                      style={{ flex: 1 }}
                      autosize
                      minRows={1}
                      value={clause}
                      disabled={locked}
                      onChange={(e) =>
                        setWhereasClauses((prev) =>
                          prev.map((c, idx) =>
                            idx === i ? e.currentTarget.value : c,
                          ),
                        )
                      }
                    />
                    <ActionIcon
                      variant="subtle"
                      color="red"
                      disabled={locked}
                      onClick={() =>
                        setWhereasClauses((prev) =>
                          prev.filter((_, idx) => idx !== i),
                        )
                      }
                    >
                      <Trash2 size={15} />
                    </ActionIcon>
                  </Group>
                ))}
              </Stack>
            )}
          </Box>

          <Divider label="Articles" labelPosition="left" />

          <Stack gap="md">
            {articles.map((article, index) => (
              <Box
                key={article.id}
                p="sm"
                style={{
                  border: "1px solid var(--mantine-color-gray-3)",
                  borderRadius: 8,
                }}
              >
                <Group justify="space-between" mb="xs" wrap="nowrap">
                  <Text size="sm" fw={700} c="dimmed">
                    Article {index + 1}
                  </Text>
                  <Group gap={4} wrap="nowrap">
                    <Tooltip label="Move up" withArrow>
                      <ActionIcon
                        variant="subtle"
                        color="gray"
                        disabled={locked || index === 0}
                        onClick={() => moveArticle(index, -1)}
                      >
                        <ArrowUp size={15} />
                      </ActionIcon>
                    </Tooltip>
                    <Tooltip label="Move down" withArrow>
                      <ActionIcon
                        variant="subtle"
                        color="gray"
                        disabled={locked || index === articles.length - 1}
                        onClick={() => moveArticle(index, 1)}
                      >
                        <ArrowDown size={15} />
                      </ActionIcon>
                    </Tooltip>
                    <Tooltip label="Delete article" withArrow>
                      <ActionIcon
                        variant="subtle"
                        color="red"
                        disabled={locked}
                        onClick={() => removeArticle(article.id)}
                      >
                        <Trash2 size={15} />
                      </ActionIcon>
                    </Tooltip>
                  </Group>
                </Group>
                <Stack gap="xs">
                  <TextInput
                    placeholder="Article title"
                    value={article.title}
                    disabled={locked}
                    onChange={(e) =>
                      updateArticle(article.id, { title: e.currentTarget.value })
                    }
                  />
                  <Textarea
                    placeholder="Article body — each line becomes a numbered clause. Use '- ' for bullets. Placeholders like {{client.companyName}} are supported."
                    autosize
                    minRows={3}
                    styles={{ input: { fontFamily: "var(--mantine-font-family-monospace)" } }}
                    value={article.body}
                    disabled={locked}
                    onChange={(e) =>
                      updateArticle(article.id, { body: e.currentTarget.value })
                    }
                  />
                </Stack>
              </Box>
            ))}

            <Button
              variant="light"
              color="edr-green"
              leftSection={<Plus size={15} />}
              disabled={locked}
              onClick={addArticle}
            >
              Add article
            </Button>
          </Stack>

          <Divider />

          {mode === "accept" && (
            <>
              {validityOptions.length > 0 ? (
                <Select
                  label="Contract validity"
                  placeholder="Select a validity period"
                  data={validityOptions}
                  value={validityDays}
                  onChange={setValidityDays}
                  allowDeselect={false}
                  comboboxProps={{ withinPortal: true }}
                />
              ) : (
                <Text size="sm" c="orange.7">
                  {validityLoading
                    ? "Loading validity periods…"
                    : "No validity periods are configured yet. Add them under Dropdown Settings."}
                </Text>
              )}
            </>
          )}

          <Group justify="flex-end" gap="sm">
            <Button variant="default" onClick={onClose} disabled={submitting}>
              Cancel
            </Button>
            <Button
              color="edr-green"
              loading={submitting}
              disabled={!canSubmit}
              onClick={submit}
            >
              {mode === "accept"
                ? "Accept & start approval"
                : "Save document changes"}
            </Button>
          </Group>
        </Stack>
      )}
    </Modal>
  );
}
