import React, { useMemo, useState } from "react";
import {
  Document,
  Font,
  Image,
  Page,
  StyleSheet,
  Text,
  View,
  pdf,
} from "@react-pdf/renderer";
import { FileDown, LoaderCircle } from "lucide-react";
import { toast } from "sonner";

import notoEthiopic from "@/record-management/fonts/NotoSansEthiopic-Regular.ttf";
import { useLocalizedName } from "@/shared/common/localizedName";
import { Button } from "@/shared/common/ui/button";
import { useTranslation } from "react-i18next";
import type {
  AssignmentApiResponse,
  AssignmentMultipleUser,
  LocalizedText,
} from "@/record-management/dto/AssignementStep";

interface MovementNode {
  id: string;
  routeType: "Sequential" | "Multiple";
  taskStatus: string;
  assigner: string;
  assignee: string;
  remark: string;
  signature?: string;
  teeter?: string;
  children?: MovementNode[];
}

interface MovementPdfExportButtonProps {
  recordTitle: string;
  recordType: string;
  subject: string;
  createdDate: string;
  referenceNumber?: string;
  assignmentChain: AssignmentApiResponse[];
  multipleAssignments?: AssignmentApiResponse[];
  lang: string;
}

interface MovementTreeRow {
  id: string;
  level: number;
  routeType: "Sequential" | "Multiple";
  taskStatus: string;
  assigner: string;
  assignee: string;
  remark: string;
}

interface PdfLabels {
  assigner: string;
  assignee: string;
  status: string;
  remark: string;
  title: string;
  empty: string;
  exportPdf: string;
  exporting: string;
  page: string;
  of: string;
}

Font.register({
  family: "CustomFont",
  fonts: [
    {
      src: notoEthiopic, // handles Amharic + English fallback
    },
  ],
});
const fallbackText = "N/A";

const styles = StyleSheet.create({
  page: {
    paddingTop: 28,
    paddingBottom: 32,
    paddingHorizontal: 28,
    fontSize: 10,
    color: "#111827",
    fontFamily: "CustomFont",
  },
  title: {
    fontSize: 18,
    fontWeight: 700,
    marginBottom: 6,
  },
  subtitle: {
    fontSize: 10,
    color: "#4B5563",
    marginBottom: 16,
  },
  section: {
    marginBottom: 16,
    borderWidth: 1,
    borderColor: "#E5E7EB",
    borderStyle: "solid",
    borderRadius: 6,
    padding: 12,
  },
  sectionTitle: {
    fontSize: 11,
    fontWeight: 700,
    color: "var(--primary-700, var(--primary))",
    marginBottom: 8,
  },
  metaGrid: {
    flexDirection: "row",
    flexWrap: "wrap",
  },
  metaItem: {
    width: "48%",
    marginBottom: 8,
    marginRight: "2%",
  },
  metaLabel: {
    fontSize: 9,
    color: "#6B7280",
    marginBottom: 2,
  },
  metaValue: {
    fontSize: 10,
    fontWeight: 600,
  },
  legendRow: {
    flexDirection: "row",
    alignItems: "center",
    marginBottom: 10,
    gap: 8,
  },
  legendPill: {
    borderRadius: 999,
    borderWidth: 1,
    borderColor: "#A7F3D0",
    borderStyle: "solid",
    backgroundColor: "#ECFDF5",
    paddingHorizontal: 8,
    paddingVertical: 4,
    fontSize: 8.5,
    color: "#065F46",
  },
  listContainer: {
    borderWidth: 1,
    borderColor: "#D1D5DB",
    borderStyle: "solid",
    borderRadius: 6,
    padding: 10,
  },
  treeRow: {
    borderBottomWidth: 1,
    borderBottomColor: "#E5E7EB",
    borderBottomStyle: "solid",
    paddingTop: 8,
    paddingBottom: 8,
  },
  treeRowLast: {
    borderBottomWidth: 0,
  },
  treeHeader: {
    flexDirection: "row",
    alignItems: "center",
    marginBottom: 4,
  },
  treeMarker: {
    width: 16,
    height: 16,
    borderRadius: 999,
    textAlign: "center",
    fontSize: 8,
    paddingTop: 2,
    marginRight: 6,
    color: "#FFFFFF",
    backgroundColor: "var(--primary)",
  },
  treeMarkerMultiple: {
    backgroundColor: "#7C3AED",
  },
  treeTitle: {
    fontSize: 10,
    fontWeight: 700,
    color: "#111827",
  },
  fieldRow: {
    flexDirection: "row",
    marginTop: 2,
  },
  fieldLabel: {
    width: 72,
    fontSize: 9,
    color: "#6B7280",
  },
  fieldValue: {
    flex: 1,
    fontSize: 9.5,
    color: "#111827",
  },
  emptyState: {
    borderWidth: 1,
    borderColor: "#E5E7EB",
    borderStyle: "dashed",
    borderRadius: 6,
    padding: 18,
    textAlign: "center",
    color: "#6B7280",
  },
  footer: {
    position: "absolute",
    bottom: 14,
    right: 28,
    fontSize: 8,
    color: "#6B7280",
  },
  treeNode: {
    borderWidth: 1,
    borderColor: "#D1D5DB",
    borderRadius: 6,
    padding: 8,
    marginBottom: 6,
  },
  treeChildren: {
    borderLeftWidth: 1,
    borderLeftColor: "#9CA3AF",
    marginLeft: 8,
    paddingLeft: 8,
  },
  flowRow: {
    flexDirection: "row",
    alignItems: "center",
    marginBottom: 8,
  },
  actorBlock: {
    flex: 1,
    borderWidth: 1,
    borderColor: "#D1D5DB",
    borderRadius: 6,
    paddingVertical: 6,
    paddingHorizontal: 8,
    backgroundColor: "#FFFFFF",
  },
  actorLabel: {
    fontSize: 8,
    color: "#6B7280",
    marginBottom: 3,
  },
  actorValue: {
    fontSize: 9.5,
    color: "#111827",
  },
  flowArrow: {
    marginHorizontal: 8,
    fontSize: 12,
    color: "#4B5563",
  },
  statusRow: {
    flexDirection: "row",
    alignItems: "center",
    marginBottom: 6,
  },
  statusLabel: {
    fontSize: 8,
    color: "#6B7280",
    marginRight: 6,
  },
  statusPill: {
    borderWidth: 1,
    borderColor: "#A7F3D0",
    borderRadius: 999,
    backgroundColor: "#ECFDF5",
    paddingHorizontal: 8,
    paddingVertical: 3,
  },
  statusPillText: {
    fontSize: 8.5,
    color: "#065F46",
  },
  remarkRow: {
    flexDirection: "row",
    alignItems: "flex-start",
    marginTop: 6,
  },
  remarkAssets: {
    width: 88,
    marginRight: 12,
    flexShrink: 0,
  },
  remarkAssetImage: {
    width: 80,
    height: 80,
    borderRadius: 6,
    borderWidth: 1,
    borderColor: "#D1D5DB",
    backgroundColor: "#FFFFFF",
    objectFit: "contain",
    padding: 4,
    marginBottom: 8,
  },
  remarkText: {
    flex: 1,
    fontSize: 9.5,
    color: "#111827",
  },
  remarkLabel: {
    fontSize: 8,
    color: "#6B7280",
    marginBottom: 3,
  },
});

const formatStatus = (
  value: string | null | undefined,
  t: (...args: any[]) => string,
) => {
  if (!value) return fallbackText;

  const formatted = value
    .split("_")
    .filter(Boolean)
    .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
    .join(" ");

  return t(`statusBar.${value}`, formatted);
};

const getLocalizedPersonName = (
  value: unknown,
  localizeName: (value?: LocalizedText) => string,
) => {
  if (typeof value === "string") {
    return value;
  }

  if (value && typeof value === "object" && "am" in value) {
    return localizeName(value as LocalizedText) || fallbackText;
  }

  return "";
};

const getAssignerText = (
  assignment: AssignmentApiResponse,
  localizeName: (value?: LocalizedText) => string,
) => {
  const person = getLocalizedPersonName(
    assignment?.assigner?.employee?.name,
    localizeName,
  );
  const position = getLocalizedPersonName(
    assignment?.assigner?.position?.name,
    localizeName,
  );

  if (person && position) return `${person} - ${position}`;
  return person || position || fallbackText;
};

const getSequentialAssigneeText = (
  assignment: AssignmentApiResponse,
  isExternalOutgoing: boolean,
  localizeName: (value?: LocalizedText) => string,
) => {
  const employeeName = getLocalizedPersonName(
    assignment?.assignee?.employee?.name,
    localizeName,
  );
  const positionName = getLocalizedPersonName(
    assignment?.assigneePosition?.name,
    localizeName,
  );

  if (
    isExternalOutgoing &&
    assignment?.assigneePosition?.role &&
    assignment?.assigneePosition?.department
  ) {
    return `${assignment.assigneePosition.role}, ${assignment.assigneePosition.department}`;
  }

  if (employeeName && positionName) return `${employeeName} - ${positionName}`;
  return employeeName || positionName || fallbackText;
};

const getMultipleAssigneeText = (
  assignment: AssignmentApiResponse,
  isExternalOutgoing: boolean,
  localizeName: (value?: LocalizedText) => string,
) => {
  if (
    !Array.isArray(assignment?.assignedToUsers) ||
    assignment.assignedToUsers.length === 0
  ) {
    return fallbackText;
  }

  return assignment.assignedToUsers
    .map((user: AssignmentMultipleUser) => {
      if (isExternalOutgoing && user?.role && user?.department) {
        return `${user.role}, ${user.department}`;
      }

      const name = getLocalizedPersonName(user?.name, localizeName);
      return name || user?.department || fallbackText;
    })
    .join(", ");
};

const renderTree = (nodes: MovementNode[], labels: PdfLabels, level = 0) => {
  return nodes.map((node) => {
    return (
      <View key={node.id} style={{ marginLeft: level * 12 }}>
        <View
          style={[
            styles.treeNode,
            {
              backgroundColor:
                node.routeType === "Multiple" ? "#F3E8FF" : "#ECFDF5",
              borderColor:
                node.routeType === "Multiple" ? "#7C3AED" : "var(--primary)",
            },
          ]}
        >
          <View style={styles.flowRow}>
            <View style={styles.actorBlock}>
              <Text style={styles.actorLabel}>{labels.assigner}</Text>
              <Text style={styles.actorValue}>{node.assigner}</Text>
            </View>
            <Text style={styles.flowArrow}>-&gt;</Text>
            <View style={styles.actorBlock}>
              <Text style={styles.actorLabel}>{labels.assignee}</Text>
              <Text style={styles.actorValue}>{node.assignee}</Text>
            </View>
          </View>

          <View style={styles.statusRow}>
            <Text style={styles.statusLabel}>{labels.status}</Text>
            <View style={styles.statusPill}>
              <Text style={styles.statusPillText}>{node.taskStatus}</Text>
            </View>
          </View>

          <View style={styles.remarkRow}>
            {(node.signature || node.teeter) && (
              <View style={styles.remarkAssets}>
                {node.signature && (
                  <Image src={node.signature} style={styles.remarkAssetImage} />
                )}
                {node.teeter && (
                  <Image src={node.teeter} style={styles.remarkAssetImage} />
                )}
              </View>
            )}
            <View style={styles.remarkText}>
              <Text style={styles.remarkLabel}>{labels.remark}</Text>
              <Text>{node.remark}</Text>
            </View>
          </View>
        </View>

        {node.children && node.children.length > 0 && (
          <View style={styles.treeChildren}>
            {renderTree(node.children, labels, level + 1)}
          </View>
        )}
      </View>
    );
  });
};
const buildTree = ({
  assignments,
  routeType,
  isExternalOutgoing,
  localizeName,
  t,
}: {
  assignments: AssignmentApiResponse[];
  routeType: "Sequential" | "Multiple";
  isExternalOutgoing: boolean;
  localizeName: (value?: LocalizedText) => string;
  t: (...args: any[]) => string;
}): MovementNode[] => {
  return assignments.map((assignment) => {
    const node: MovementNode = {
      id: assignment?.id || Math.random().toString(),
      routeType,
      taskStatus:
        routeType === "Multiple" && Array.isArray(assignment?.assignedToUsers)
          ? assignment.assignedToUsers
              .map((u) => formatStatus(u?.status, t))
              .join(", ")
          : formatStatus(assignment?.status, t),
      assigner: getAssignerText(assignment, localizeName),
      assignee:
        routeType === "Multiple"
          ? getMultipleAssigneeText(
              assignment,
              isExternalOutgoing,
              localizeName,
            )
          : getSequentialAssigneeText(
              assignment,
              isExternalOutgoing,
              localizeName,
            ),
      remark: assignment?.comment || fallbackText,
      children: [],
      signature: assignment?.signature?.presigned,
      teeter: assignment?.teeter?.presigned,
    };

    // ✅ sequential children
    if (assignment.children?.length) {
      node.children = buildTree({
        assignments: assignment.children,
        routeType,
        isExternalOutgoing,
        localizeName,
        t,
      });
    }

    return node;
  });
};

const MovementSlipPdfDocument: React.FC<{
  recordTitle: string;
  recordType: string;
  subject: string;
  createdDate: string;
  referenceNumber?: string;
  rows: MovementTreeRow[];
  labels: PdfLabels;
}> = ({ recordTitle, rows, labels }) => {
  return (
    <Document title={`Movement Slip - ${recordTitle || "Record"}`}>
      <Page size="A4" style={styles.page}>
        <Text style={styles.title}>{labels.title}</Text>

        {rows.length > 0 ? (
          <View style={styles.section}>
            <View style={styles.listContainer}>
              {renderTree(rows as MovementNode[], labels)}
            </View>
          </View>
        ) : (
          <Text style={styles.emptyState}>{labels.empty}</Text>
        )}

        <Text
          style={styles.footer}
          render={({ pageNumber, totalPages }) =>
            `${labels.page} ${pageNumber} ${labels.of} ${totalPages}`
          }
          fixed
        />
      </Page>
    </Document>
  );
};

const MovementPdfExportButton: React.FC<MovementPdfExportButtonProps> = ({
  recordTitle,
  recordType,
  subject,
  createdDate,
  referenceNumber,
  assignmentChain,
  multipleAssignments = [],
}) => {
  const localizedName = useLocalizedName();
  const { t } = useTranslation();
  const [isExporting, setIsExporting] = useState(false);

  const labels: PdfLabels = {
    assigner: t("assignment.assignedBy"),
    assignee: t("assignment.assignedTo"),
    status: t("userIncoming.Status"),
    remark: t("assignment.comment"),
    title: t("assignment.assignmentFlow"),
    empty: t("assignment.noAssignments"),
    exportPdf: t("common.export", "Export PDF"),
    exporting: t("common.exporting", "Exporting..."),
    page: t("common.page", "Page"),
    of: t("common.of", "of"),
  };

  const isExternalOutgoing = Boolean(
    recordType === "External" && referenceNumber?.includes("outgoing"),
  );

  const translate = (...args: Parameters<typeof t>) => String(t(...args));

  const tree = useMemo(() => {
    const tFn = (key: string, defaultValue?: string) => t(key, defaultValue ?? key);
    const base = buildTree({
      assignments: assignmentChain,
      routeType: "Sequential",
      isExternalOutgoing,
      localizeName: localizedName,
      t: translate,
    });

    if (multipleAssignments.length) {
      base.push(
        ...buildTree({
          assignments: multipleAssignments,
          routeType: "Multiple",
          isExternalOutgoing,
          localizeName: localizedName,
          t: translate,
        }),
      );
    }

    return base;
  }, [
    assignmentChain,
    multipleAssignments,
    isExternalOutgoing,
    localizedName,
    translate,
  ]);

  const handleExport = async () => {
    try {
      setIsExporting(true);

      const blob = await pdf(
        <MovementSlipPdfDocument
          recordTitle={recordTitle}
          recordType={recordType}
          subject={subject}
          createdDate={createdDate}
          referenceNumber={referenceNumber}
          rows={tree as MovementTreeRow[]}
          labels={labels}
        />,
      ).toBlob();

      const fileNameBase =
        recordTitle?.trim().replace(/[<>:\"/\\|?*]+/g, "_") ||
        "record-movement-slip";
      const blobUrl = URL.createObjectURL(blob);
      const anchor = document.createElement("a");
      anchor.href = blobUrl;
      anchor.download = `${fileNameBase}.pdf`;
      document.body.appendChild(anchor);
      anchor.click();
      document.body.removeChild(anchor);
      URL.revokeObjectURL(blobUrl);
    } catch (error: any) {
      toast.error(error?.message || "Failed to export movement PDF");
    } finally {
      setIsExporting(false);
    }
  };

  return (
    <Button
      variant="outline"
      size="sm"
      className="gap-2"
      onClick={handleExport}
      disabled={isExporting}
    >
      {isExporting ? (
        <LoaderCircle className="h-4 w-4 animate-spin" />
      ) : (
        <FileDown className="h-4 w-4" />
      )}
      <span>{isExporting ? labels.exporting : labels.exportPdf}</span>
    </Button>
  );
};

export default MovementPdfExportButton;
