import { useRef, useState } from "react";
import { createFileRoute } from "@tanstack/react-router";
import { useMutation, useQuery } from "@tanstack/react-query";
import { toast } from "sonner";
import { formatDistanceToNow } from "date-fns";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { Progress } from "@/components/ui/progress";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table";
import { cn } from "@/lib/utils";
import { listImportsFn, previewCsvFn, runImportFn } from "@/lib/voters/voters.functions";
import type { ImportStatus } from "@/lib/voters/types";
import {
  AlertTriangle,
  ArrowRight,
  CheckCircle2,
  Copy,
  Database,
  FileSpreadsheet,
  FileUp,
  Loader2,
  ShieldCheck,
  Upload,
  XCircle,
} from "lucide-react";

export const Route = createFileRoute("/audiences/import")({
  component: ImportWizard,
});

type Step = 1 | 2 | 3 | 4;

interface UploadedFile {
  name: string;
  size: number;
  text: string;
}

const statusVariant: Record<ImportStatus, string> = {
  completed: "bg-success/10 text-success border-success/30",
  processing: "bg-primary/10 text-primary border-primary/30",
  pending: "bg-muted text-muted-foreground border-border",
  failed: "bg-destructive/10 text-destructive border-destructive/30",
};

function ImportWizard() {
  const [step, setStep] = useState<Step>(1);
  const [file, setFile] = useState<UploadedFile | null>(null);
  const [dragOver, setDragOver] = useState(false);
  const inputRef = useRef<HTMLInputElement>(null);

  const previewMutation = useMutation({
    mutationFn: (input: { csv: string; filename: string }) => previewCsvFn({ data: input }),
    onSuccess: () => setStep(2),
    onError: (err) => toast.error(err instanceof Error ? err.message : "Failed to read file"),
  });

  const importMutation = useMutation({
    mutationFn: (input: { csv: string; filename: string }) => runImportFn({ data: input }),
    onSuccess: (res) => {
      toast.success(
        `Imported ${res.inserted.toLocaleString()} supporters (${res.duplicates} duplicates, ${res.invalid} invalid)`,
      );
      historyQuery.refetch();
    },
    onError: (err) => toast.error(err instanceof Error ? err.message : "Import failed"),
  });

  const historyQuery = useQuery({
    queryKey: ["voters", "imports"],
    queryFn: () => listImportsFn(),
    refetchInterval: importMutation.isPending ? 2000 : false,
  });

  const preview = previewMutation.data;
  const importResult = importMutation.data;
  const history = historyQuery.data ?? [];

  const accept = async (f: File) => {
    try {
      const text = await f.text();
      setFile({ name: f.name, size: f.size, text });
      previewMutation.mutate({ csv: text, filename: f.name });
    } catch (err) {
      toast.error(err instanceof Error ? err.message : "Failed to read file");
    }
  };

  const startImport = () => {
    if (!file) return;
    setStep(4);
    importMutation.mutate({ csv: file.text, filename: file.name });
  };

  const reset = () => {
    setFile(null);
    setStep(1);
    previewMutation.reset();
    importMutation.reset();
  };

  // Synthesised progress from server-reported counts when polling.
  const progress = importResult ? 100 : importMutation.isPending ? 50 : 0;

  return (
    <div className="grid lg:grid-cols-[1fr_320px] gap-4">
      <div className="space-y-4 min-w-0">
        <Stepper step={step} />

        {step === 1 && (
          <Card>
            <CardHeader className="pb-2">
              <CardTitle className="text-base flex items-center gap-2">
                <Upload className="h-4 w-4 text-primary" /> Upload supporter file
              </CardTitle>
              <p className="text-xs text-muted-foreground">
                CSV or XLSX · up to 50MB · columns auto-detected
              </p>
            </CardHeader>
            <CardContent>
              <div
                className={cn(
                  "rounded-xl border-2 border-dashed p-8 text-center transition-colors cursor-pointer",
                  dragOver
                    ? "border-primary bg-primary/5"
                    : "border-border hover:border-primary/40 hover:bg-muted/40",
                )}
                onClick={() => inputRef.current?.click()}
                onDragOver={(e) => {
                  e.preventDefault();
                  setDragOver(true);
                }}
                onDragLeave={() => setDragOver(false)}
                onDrop={(e) => {
                  e.preventDefault();
                  setDragOver(false);
                  const f = e.dataTransfer.files[0];
                  if (f) accept(f);
                }}
              >
                <div className="mx-auto h-12 w-12 rounded-2xl bg-gradient-to-br from-primary/15 to-accent/10 grid place-items-center mb-3">
                  <FileUp className="h-5 w-5 text-primary" />
                </div>
                <div className="text-sm font-medium">Drop your file here, or click to browse</div>
                <p className="text-xs text-muted-foreground mt-1">
                  Accepted: .csv, .xlsx, .xls · Max 50MB
                </p>
                <Button size="sm" className="mt-4 gap-1.5">
                  <FileUp className="h-3.5 w-3.5" /> Choose file
                </Button>
                <input
                  ref={inputRef}
                  type="file"
                  className="hidden"
                  accept=".csv,.xlsx,.xls"
                  onChange={(e) => e.target.files?.[0] && accept(e.target.files[0])}
                />
              </div>

              <div className="mt-4 grid grid-cols-1 sm:grid-cols-3 gap-3 text-xs">
                <TipCard
                  icon={ShieldCheck}
                  title="Consent required"
                  body="Every row must include an explicit opt-in flag."
                />
                <TipCard
                  icon={Database}
                  title="Auto-deduplication"
                  body="Existing voters are matched by phone + fuzzy name."
                />
                <TipCard
                  icon={FileSpreadsheet}
                  title="Smart mapping"
                  body="Columns are matched to schema with AI."
                />
              </div>
            </CardContent>
          </Card>
        )}

        {step === 2 && file && (
          <Card>
            <CardHeader className="pb-2">
              <div className="flex items-center justify-between">
                <CardTitle className="text-base">Validate & map columns</CardTitle>
                <Badge variant="outline" className="text-[10px] gap-1">
                  <FileSpreadsheet className="h-3 w-3" /> {file.name}
                </Badge>
              </div>
              <p className="text-xs text-muted-foreground">
                {preview?.totalRows.toLocaleString() ?? "—"} rows detected · review mapping below
              </p>
            </CardHeader>
            <CardContent className="space-y-4">
              {previewMutation.isPending && (
                <div className="flex items-center gap-2 text-xs text-muted-foreground">
                  <Loader2 className="h-3.5 w-3.5 animate-spin" /> Parsing file…
                </div>
              )}

              {preview && (
                <>
                  <div className="grid grid-cols-2 sm:grid-cols-4 gap-3">
                    <ValidationStat
                      label="Total rows"
                      value={preview.totalRows.toLocaleString()}
                      tone="muted"
                    />
                    <ValidationStat
                      label="Mapped columns"
                      value={`${Object.keys(preview.mapping.index).length}/${preview.headers.length}`}
                      tone="success"
                    />
                    <ValidationStat
                      label="Unmapped"
                      value={preview.mapping.unmapped.length.toString()}
                      tone={preview.mapping.unmapped.length ? "warning" : "muted"}
                    />
                    <ValidationStat
                      label="Missing required"
                      value={preview.mapping.missingRequired.length.toString()}
                      tone={preview.mapping.missingRequired.length ? "destructive" : "success"}
                    />
                  </div>

                  <div className="rounded-lg border overflow-hidden">
                    <div className="grid grid-cols-[1fr_24px_1fr_100px] gap-3 px-4 py-2 border-b bg-muted/40 text-[11px] font-medium text-muted-foreground uppercase tracking-wide">
                      <span>Source column</span>
                      <span />
                      <span>Maps to</span>
                      <span className="text-right">Confidence</span>
                    </div>
                    {preview.mapping.suggestions.map((c) => (
                      <div
                        key={c.source}
                        className="grid grid-cols-[1fr_24px_1fr_100px] gap-3 px-4 py-2 items-center border-b last:border-b-0 text-sm"
                      >
                        <span className="font-medium truncate">{c.source}</span>
                        <ArrowRight className="h-3.5 w-3.5 text-muted-foreground" />
                        <span className={cn("text-muted-foreground", !c.target && "italic")}>
                          {c.target ?? "ignored"}
                        </span>
                        <div className="flex items-center justify-end gap-1.5">
                          <div className="h-1.5 w-12 rounded-full bg-muted overflow-hidden">
                            <div
                              className={cn(
                                "h-full",
                                c.confidence > 95
                                  ? "bg-success"
                                  : c.confidence > 60
                                    ? "bg-warning"
                                    : "bg-destructive",
                              )}
                              style={{ width: `${c.confidence}%` }}
                            />
                          </div>
                          <span className="text-[11px] tabular-nums">{c.confidence}%</span>
                        </div>
                      </div>
                    ))}
                  </div>

                  {preview.mapping.missingRequired.length > 0 && (
                    <div className="rounded-lg border border-destructive/30 bg-destructive/5 p-3">
                      <div className="flex items-center gap-2 text-xs font-semibold">
                        <AlertTriangle className="h-3.5 w-3.5 text-destructive" /> Required columns
                        missing
                      </div>
                      <ul className="mt-2 space-y-1 text-[11px]">
                        {preview.mapping.missingRequired.map((field) => (
                          <li key={field} className="font-mono">
                            {field}
                          </li>
                        ))}
                      </ul>
                    </div>
                  )}
                </>
              )}

              <div className="flex items-center justify-between">
                <Button variant="ghost" type="button" size="sm" onClick={reset}>
                  ← Back
                </Button>
                <Button
                  size="sm"
                  className="gap-1.5"
                  onClick={() => setStep(3)}
                  disabled={!preview || preview.mapping.missingRequired.length > 0}
                >
                  Continue <ArrowRight className="h-3.5 w-3.5" />
                </Button>
              </div>
            </CardContent>
          </Card>
        )}

        {step === 3 && preview && (
          <Card>
            <CardHeader className="pb-2">
              <CardTitle className="text-base flex items-center gap-2">
                <Copy className="h-4 w-4 text-warning-foreground" /> Confirm import
              </CardTitle>
              <p className="text-xs text-muted-foreground">
                Duplicates will be skipped automatically based on phone number and national ID
                hashes.
              </p>
            </CardHeader>
            <CardContent className="space-y-3">
              <div className="rounded-lg border bg-muted/20 p-3 text-xs space-y-2">
                <div className="flex items-center justify-between">
                  <span className="text-muted-foreground">File</span>
                  <span className="font-medium">{file?.name}</span>
                </div>
                <div className="flex items-center justify-between">
                  <span className="text-muted-foreground">Rows to process</span>
                  <span className="font-medium tabular-nums">
                    {preview.totalRows.toLocaleString()}
                  </span>
                </div>
                <div className="flex items-center justify-between">
                  <span className="text-muted-foreground">Mapped fields</span>
                  <span className="font-medium tabular-nums">
                    {Object.keys(preview.mapping.index).length}
                  </span>
                </div>
              </div>

              <div className="flex flex-wrap items-center gap-2 text-[11px] text-muted-foreground">
                <Badge variant="outline" className="text-[10px] gap-1">
                  <CheckCircle2 className="h-3 w-3 text-success" /> Existing phone matches skipped
                </Badge>
                <Badge variant="outline" className="text-[10px]">
                  Invalid rows reported in audit log
                </Badge>
              </div>

              <div className="flex items-center justify-between">
                <Button variant="ghost" type="button" size="sm" onClick={() => setStep(2)}>
                  ← Back
                </Button>
                <Button size="sm" className="gap-1.5" onClick={startImport}>
                  Start import <ArrowRight className="h-3.5 w-3.5" />
                </Button>
              </div>
            </CardContent>
          </Card>
        )}

        {step === 4 && (
          <Card>
            <CardHeader className="pb-2">
              <CardTitle className="text-base flex items-center gap-2">
                {importMutation.isPending ? (
                  <Loader2 className="h-4 w-4 text-primary animate-spin" />
                ) : importMutation.isError ? (
                  <XCircle className="h-4 w-4 text-destructive" />
                ) : (
                  <CheckCircle2 className="h-4 w-4 text-success" />
                )}
                {importMutation.isPending
                  ? "Importing supporters…"
                  : importMutation.isError
                    ? "Import failed"
                    : "Import complete"}
              </CardTitle>
              <p className="text-xs text-muted-foreground">
                {importMutation.isPending
                  ? "Don't close this tab — chunked inserts are running on the server."
                  : importMutation.isError
                    ? importMutation.error instanceof Error
                      ? importMutation.error.message
                      : "Unknown error"
                    : "All clean rows have been added to the database."}
              </p>
            </CardHeader>
            <CardContent className="space-y-4">
              <div>
                <div className="flex justify-between text-xs mb-1.5">
                  <span className="text-muted-foreground">Progress</span>
                  <span className="font-medium tabular-nums">{Math.round(progress)}%</span>
                </div>
                <Progress value={progress} className="h-2" />
              </div>

              <div className="grid grid-cols-2 sm:grid-cols-4 gap-3">
                <ValidationStat
                  label="Inserted"
                  value={(importResult?.inserted ?? 0).toLocaleString()}
                  tone="success"
                  icon={CheckCircle2}
                />
                <ValidationStat
                  label="Duplicates"
                  value={(importResult?.duplicates ?? 0).toLocaleString()}
                  tone="warning"
                  icon={Copy}
                />
                <ValidationStat
                  label="Invalid"
                  value={(importResult?.invalid ?? 0).toLocaleString()}
                  tone="destructive"
                  icon={AlertTriangle}
                />
                <ValidationStat
                  label="Total rows"
                  value={(importResult?.totalRows ?? preview?.totalRows ?? 0).toLocaleString()}
                  tone="muted"
                  icon={Database}
                />
              </div>

              {importResult && importResult.errors.length > 0 && (
                <div className="rounded-lg border border-warning/30 bg-warning/5 p-3">
                  <div className="flex items-center gap-2 text-xs font-semibold">
                    <AlertTriangle className="h-3.5 w-3.5 text-warning-foreground" /> Validation
                    errors
                  </div>
                  <ul className="mt-2 space-y-1 text-[11px]">
                    {importResult.errors.slice(0, 5).map((e) => (
                      <li key={e.code} className="flex items-center justify-between gap-2">
                        <span className="font-mono">{e.code}</span>
                        <span className="text-muted-foreground truncate flex-1">{e.sample}</span>
                        <Badge variant="outline" className="text-[10px]">
                          {e.count}
                        </Badge>
                      </li>
                    ))}
                  </ul>
                </div>
              )}

              {(importResult || importMutation.isError) && (
                <div className="flex items-center justify-between rounded-lg border border-success/30 bg-success/5 p-3 text-xs">
                  <div className="flex items-center gap-2">
                    <CheckCircle2 className="h-4 w-4 text-success" />
                    <span>
                      {importResult
                        ? `Imported ${importResult.inserted.toLocaleString()} supporters into your database.`
                        : "Import did not complete."}
                    </span>
                  </div>
                  <Button size="sm" variant="outline" type="button" onClick={reset}>
                    Import another
                  </Button>
                </div>
              )}
            </CardContent>
          </Card>
        )}

        {/* Import history */}
        <Card>
          <CardHeader className="pb-3">
            <CardTitle className="text-sm">Import history</CardTitle>
          </CardHeader>
          <CardContent className="px-0">
            <Table>
              <TableHeader>
                <TableRow className="hover:bg-transparent">
                  <TableHead className="text-xs">File</TableHead>
                  <TableHead className="text-xs hidden sm:table-cell text-right">Rows</TableHead>
                  <TableHead className="text-xs text-right">Valid</TableHead>
                  <TableHead className="text-xs hidden md:table-cell text-right">Dupes</TableHead>
                  <TableHead className="text-xs hidden md:table-cell text-right">Invalid</TableHead>
                  <TableHead className="text-xs">Status</TableHead>
                  <TableHead className="text-xs hidden lg:table-cell">When</TableHead>
                </TableRow>
              </TableHeader>
              <TableBody>
                {history.length === 0 && (
                  <TableRow>
                    <TableCell
                      colSpan={7}
                      className="text-center text-xs text-muted-foreground py-6"
                    >
                      {historyQuery.isLoading ? "Loading imports…" : "No imports yet."}
                    </TableCell>
                  </TableRow>
                )}
                {history.map((h) => (
                  <TableRow key={h.id}>
                    <TableCell className="py-2.5">
                      <div className="flex items-center gap-2">
                        <FileSpreadsheet className="h-3.5 w-3.5 text-muted-foreground" />
                        <span className="text-sm font-medium truncate">{h.filename}</span>
                      </div>
                    </TableCell>
                    <TableCell className="hidden sm:table-cell text-right text-xs tabular-nums">
                      {h.totalRows.toLocaleString()}
                    </TableCell>
                    <TableCell className="text-right text-xs tabular-nums text-success">
                      {h.inserted.toLocaleString()}
                    </TableCell>
                    <TableCell className="hidden md:table-cell text-right text-xs tabular-nums">
                      {h.duplicates.toLocaleString()}
                    </TableCell>
                    <TableCell className="hidden md:table-cell text-right text-xs tabular-nums text-destructive">
                      {h.invalid.toLocaleString()}
                    </TableCell>
                    <TableCell>
                      <Badge
                        variant="outline"
                        className={cn("text-[10px] capitalize", statusVariant[h.status])}
                      >
                        {h.status}
                      </Badge>
                    </TableCell>
                    <TableCell className="hidden lg:table-cell text-xs text-muted-foreground">
                      {formatDistanceToNow(new Date(h.createdAt), { addSuffix: true })}
                    </TableCell>
                  </TableRow>
                ))}
              </TableBody>
            </Table>
          </CardContent>
        </Card>
      </div>

      {/* Side info */}
      <div className="space-y-4">
        <Card className="bg-gradient-to-br from-primary/5 via-accent/5 to-transparent border-primary/20">
          <CardHeader className="pb-2">
            <CardTitle className="text-sm flex items-center gap-2">
              <ShieldCheck className="h-4 w-4 text-primary" /> Compliance reminder
            </CardTitle>
          </CardHeader>
          <CardContent className="space-y-2 text-xs text-muted-foreground">
            <p>
              VotersAlert only allows outreach to{" "}
              <span className="text-foreground font-medium">opted-in</span> supporters.
            </p>
            <p>
              Every imported row must include explicit consent. Files without a consent column will
              be rejected.
            </p>
            <Button size="sm" variant="outline" className="w-full mt-2">
              View import policy
            </Button>
          </CardContent>
        </Card>

        <Card>
          <CardHeader className="pb-2">
            <CardTitle className="text-sm">Template & schema</CardTitle>
          </CardHeader>
          <CardContent className="space-y-2 text-xs">
            <p className="text-muted-foreground">
              Download the official CSV template with all required columns and example rows.
            </p>
            <Button size="sm" variant="outline" className="w-full gap-1.5">
              <FileSpreadsheet className="h-3.5 w-3.5" /> Download CSV template
            </Button>
            <Button size="sm" variant="ghost" className="w-full gap-1.5">
              <FileSpreadsheet className="h-3.5 w-3.5" /> Download XLSX template
            </Button>
          </CardContent>
        </Card>
      </div>
    </div>
  );
}

function Stepper({ step }: { step: Step }) {
  const steps = ["Upload", "Validate", "Duplicates", "Import"];
  return (
    <div className="flex items-center gap-2">
      {steps.map((s, i) => {
        const n = (i + 1) as Step;
        const done = step > n;
        const active = step === n;
        return (
          <div key={s} className="flex items-center gap-2 flex-1">
            <div
              className={cn(
                "h-7 w-7 rounded-full grid place-items-center text-[11px] font-semibold border",
                done && "bg-success text-success-foreground border-success",
                active && "bg-primary text-primary-foreground border-primary",
                !done && !active && "bg-muted text-muted-foreground border-border",
              )}
            >
              {done ? <CheckCircle2 className="h-3.5 w-3.5" /> : n}
            </div>
            <div
              className={cn(
                "text-xs font-medium",
                active ? "text-foreground" : "text-muted-foreground",
              )}
            >
              {s}
            </div>
            {i < steps.length - 1 && (
              <div className={cn("flex-1 h-px", done ? "bg-success" : "bg-border")} />
            )}
          </div>
        );
      })}
    </div>
  );
}

function TipCard({
  icon: Icon,
  title,
  body,
}: {
  icon: typeof ShieldCheck;
  title: string;
  body: string;
}) {
  return (
    <div className="rounded-md border bg-muted/30 p-3">
      <div className="flex items-center gap-1.5 text-xs font-semibold">
        <Icon className="h-3.5 w-3.5 text-primary" /> {title}
      </div>
      <p className="mt-1 text-[11px] text-muted-foreground leading-relaxed">{body}</p>
    </div>
  );
}

function ValidationStat({
  label,
  value,
  tone,
  icon: Icon,
}: {
  label: string;
  value: string;
  tone: "muted" | "success" | "warning" | "destructive";
  icon?: typeof CheckCircle2;
}) {
  return (
    <div
      className={cn(
        "rounded-md border p-2.5",
        tone === "success" && "border-success/30 bg-success/5",
        tone === "warning" && "border-warning/30 bg-warning/5",
        tone === "destructive" && "border-destructive/30 bg-destructive/5",
        tone === "muted" && "bg-muted/40",
      )}
    >
      <div className="flex items-center gap-1.5 text-[10px] text-muted-foreground uppercase tracking-wide">
        {Icon && <Icon className="h-3 w-3" />} {label}
      </div>
      <div className="mt-0.5 text-lg font-semibold tabular-nums">{value}</div>
    </div>
  );
}
