import { useMemo, useState } from "react";
import { View } from "react-native";
import { router, useLocalSearchParams } from "expo-router";
import { useMutation, useQuery } from "@tanstack/react-query";
import { api } from "@/lib/api";
import { t } from "@/lib/i18n";
import {
  Body,
  Button,
  Card,
  EmptyState,
  ErrorView,
  Heading,
  LoadingView,
  Row,
  Screen,
  Small,
  Spacer,
  Tag,
} from "@/components/ui";
import { spacing } from "@/lib/theme";

type DiffRow = {
  kind: "new_item" | "moved" | "quantity_changed" | "vanished" | "unchanged";
  previousItemId?: string;
  displayName: string;
  unit: string;
  previousQuantity?: number;
  newQuantity?: number;
  previousLocationId?: string;
  newLocationId?: string;
  confidence: number;
  reason: string;
};

export default function ScanDiffReviewScreen() {
  const { jobId } = useLocalSearchParams<{ jobId: string }>();
  const [rejectedKinds] = useState<Set<string>>(new Set());

  const query = useQuery({
    queryKey: ["scan-diff", jobId],
    queryFn: () => api<{ rows: DiffRow[] }>(`/v1/scans/${jobId}/diff`, { method: "POST", body: {} }),
  });

  const apply = useMutation({
    mutationFn: (rows: DiffRow[]) =>
      api<{ appliedItemIds: string[] }>(`/v1/scans/${jobId}/diff/apply`, {
        method: "POST",
        body: { idempotencyKey: `scan-diff-${jobId}-${Date.now()}`, rows },
      }),
    onSuccess: () => {
      router.back();
    },
  });

  const rows = useMemo(() => query.data?.rows ?? [], [query.data]);
  const actionable = rows.filter((r) => r.kind !== "unchanged");
  const accepted = actionable.filter((r) => !rejectedKinds.has(rowKey(r)));

  if (query.isLoading) return <LoadingView />;
  if (query.isError) return <ErrorView onRetry={() => void query.refetch()} />;

  if (actionable.length === 0) {
    return (
      <Screen>
        <Heading>{t("scan.diff.title")}</Heading>
        <EmptyState text={t("scan.diff.noChanges")} />
        <Button label={t("common.back")} variant="secondary" onPress={() => router.back()} />
      </Screen>
    );
  }

  return (
    <Screen>
      <Heading>{t("scan.diff.title")}</Heading>
      <Small>{t("scan.diff.subtitle")}</Small>
      <Spacer size={spacing.sm} />

      {actionable.map((row) => (
        <Card key={rowKey(row)}>
          <Row style={{ justifyContent: "space-between" }}>
            <Body>{row.displayName}</Body>
            <Tag label={t(`scan.diff.${row.kind}`)} tone={toneForKind(row.kind)} />
          </Row>
          <Small>{row.reason}</Small>
          {(row.kind === "quantity_changed" || row.kind === "moved") && (
            <Small>
              {formatQty(row.previousQuantity)} → {formatQty(row.newQuantity)} {row.unit}
            </Small>
          )}
          {row.kind === "vanished" && (
            <Small style={{ opacity: 0.8 }}>{t("reconciliation.tasteHint")}</Small>
          )}
        </Card>
      ))}

      <Small style={{ opacity: 0.7 }}>{t("scan.diff.undoHint")}</Small>
      <Spacer size={spacing.sm} />

      <Button
        label={t("scan.diff.acceptAll")}
        loading={apply.isPending}
        onPress={() => apply.mutate(accepted)}
      />
    </Screen>
  );
}

function rowKey(row: DiffRow): string {
  return `${row.kind}:${row.previousItemId ?? "new"}:${row.displayName}`;
}

function toneForKind(kind: DiffRow["kind"]) {
  switch (kind) {
    case "vanished":
      return "warning";
    case "new_item":
      return "success";
    case "quantity_changed":
    case "moved":
      return "accent";
    default:
      return "neutral";
  }
}

function formatQty(q?: number): string {
  if (q == null) return "-";
  return Number.isInteger(q) ? String(q) : q.toFixed(1);
}
