"use client";

import { useCallback, useEffect, useRef, useState } from "react";
import Link from "next/link";
import { toast } from "sonner";
import { UploadCloud, FileText, CheckCircle2, XCircle, Download, ArrowRight } from "lucide-react";

import { Card, CardContent } from "@/shared/components/ui/card";
import { Button } from "@/shared/components/ui/button";
import { Label } from "@/shared/components/ui/label";
import { Table, TableHeader, TableBody, TableRow, TableHead, TableCell } from "@/shared/components/ui/table";
import { downloadCsv } from "@/shared/utils/download-csv";
import { getAllContactListsAction } from "../actions/get-all-contact-lists-action";
import { parseContactImportAction } from "../actions/parse-contact-import-action";
import { confirmImportMappingAction } from "../actions/confirm-import-mapping-action";
import { processImportBatchAction } from "../actions/process-import-batch-action";
import { exportImportErrorsAction } from "../actions/export-import-errors-action";

type Step = "upload" | "mapping" | "processing" | "done";

interface ParseResult {
  jobId: string;
  headers: string[];
  sampleRows: Record<string, string>[];
  totalRows: number;
}

interface ImportJob {
  id: string;
  status: "MAPPING" | "PROCESSING" | "COMPLETED" | "FAILED";
  totalRows: number;
  processedRows: number;
  importedCount: number;
  updatedCount: number;
  skippedCount: number;
  errorCount: number;
}

interface ContactListOption {
  id: string;
  name: string;
}

const NONE_VALUE = "__none__";

interface ContactsImportPageViewProps {
  initialListId?: string;
  onClose?: () => void;
}

export function ContactsImportPageView({ initialListId, onClose }: ContactsImportPageViewProps = {}) {
  const [step, setStep] = useState<Step>("upload");
  const [isDragging, setIsDragging] = useState(false);
  const [isUploading, setIsUploading] = useState(false);
  const [selectedFile, setSelectedFile] = useState<File | null>(null);
  const fileInputRef = useRef<HTMLInputElement>(null);

  const [parseResult, setParseResult] = useState<ParseResult | null>(null);
  const [emailColumn, setEmailColumn] = useState("");
  const [nameColumn, setNameColumn] = useState(NONE_VALUE);
  const [phoneColumn, setPhoneColumn] = useState(NONE_VALUE);
  const [tagsColumn, setTagsColumn] = useState(NONE_VALUE);
  const [duplicateStrategy, setDuplicateStrategy] = useState<"IGNORE" | "UPDATE" | "CREATE_ANYWAY">("UPDATE");
  const [targetListId, setTargetListId] = useState(initialListId ?? "");
  const [lists, setLists] = useState<ContactListOption[]>([]);

  const [job, setJob] = useState<ImportJob | null>(null);

  useEffect(() => {
    getAllContactListsAction()
      .then((data) => setLists(data.lists ?? []))
      .catch(() => {});
  }, []);

  async function handleUpload(file: File) {
    if (!file.name.toLowerCase().endsWith(".csv")) {
      toast.error("Só arquivos .csv são suportados nesta versão.");
      return;
    }

    setIsUploading(true);
    try {
      const formData = new FormData();
      formData.append("file", file);
      const data: ParseResult = await parseContactImportAction(formData);
      setParseResult(data);
      setEmailColumn(data.headers.find((h) => h.toLowerCase().includes("mail")) ?? data.headers[0] ?? "");
      setStep("mapping");
    } catch (err) {
      toast.error(err instanceof Error ? err.message : "Não foi possível processar o arquivo");
    } finally {
      setIsUploading(false);
    }
  }

  const handleDrop = useCallback((e: React.DragEvent) => {
    e.preventDefault();
    setIsDragging(false);
    const file = e.dataTransfer.files?.[0];
    if (file) setSelectedFile(file);
  }, []);

  function handlePrepareImport() {
    if (selectedFile) handleUpload(selectedFile);
  }

  async function handleConfirmMapping() {
    if (!parseResult || !emailColumn) return;

    try {
      await confirmImportMappingAction(parseResult.jobId, {
        columnMapping: {
          email: emailColumn,
          ...(nameColumn !== NONE_VALUE && { name: nameColumn }),
          ...(phoneColumn !== NONE_VALUE && { phone: phoneColumn }),
          ...(tagsColumn !== NONE_VALUE && { tags: tagsColumn }),
        },
        duplicateStrategy,
        ...(targetListId && { targetListId }),
      });

      setStep("processing");
      runProcessing(parseResult.jobId);
    } catch {
      toast.error("Não foi possível confirmar o mapeamento de colunas.");
    }
  }

  async function runProcessing(jobId: string) {
    // Polling em lotes — sem fila/worker em background, cada chamada processa até 200 linhas e o
    // front repete até o job concluir, atualizando a barra de progresso a cada resposta.
    let current: ImportJob | null = null;
    do {
      let data;
      try {
        data = await processImportBatchAction(jobId);
      } catch {
        toast.error("Ocorreu um erro ao processar a importação.");
        return;
      }
      current = data.job;
      setJob(current);
    } while (current && current.status !== "COMPLETED");

    setStep("done");
  }

  function reset() {
    setStep("upload");
    setParseResult(null);
    setJob(null);
    setSelectedFile(null);
    setEmailColumn("");
    setNameColumn(NONE_VALUE);
    setPhoneColumn(NONE_VALUE);
    setTagsColumn(NONE_VALUE);
    setTargetListId(initialListId ?? "");
  }

  const progressPct = job && job.totalRows > 0 ? Math.round((job.processedRows / job.totalRows) * 100) : 0;

  return (
    <div className="max-w-3xl mx-auto space-y-6">
      {step === "upload" && (
        <Card className="bg-white border border-zinc-200/80 rounded-2xl shadow-xs">
          <CardContent className="p-6 space-y-5">
            <div className="rounded-2xl border border-zinc-200 bg-zinc-50/60 p-5">
              <div
                onDragOver={(e) => {
                  e.preventDefault();
                  setIsDragging(true);
                }}
                onDragLeave={() => setIsDragging(false)}
                onDrop={handleDrop}
                className={`border-2 border-dashed rounded-xl bg-white p-10 text-center transition-colors ${
                  isDragging ? "border-indigo-400 bg-indigo-50/50" : "border-zinc-300"
                }`}
              >
                {selectedFile ? (
                  <div className="flex flex-col items-center gap-1">
                    <FileText className="w-8 h-8 text-indigo-600 mb-1" />
                    <p className="text-sm font-bold text-zinc-900">{selectedFile.name}</p>
                    <p className="text-xs text-zinc-500 mb-3">{(selectedFile.size / 1024).toFixed(1)} KB</p>
                    <Button
                      type="button"
                      variant="ghost"
                      size="sm"
                      className="h-7 text-xs text-zinc-500"
                      onClick={() => setSelectedFile(null)}
                    >
                      Trocar arquivo
                    </Button>
                  </div>
                ) : (
                  <>
                    <UploadCloud className="w-10 h-10 text-zinc-400 mx-auto mb-3" />
                    <p className="text-sm font-bold text-zinc-900">Arraste e solte um arquivo para adicionar contatos</p>
                    <p className="text-xs text-zinc-500 mt-1 mb-4">.csv, com cabeçalho na primeira linha</p>
                    <Button
                      type="button"
                      variant="outline"
                      onClick={() => fileInputRef.current?.click()}
                    >
                      Selecionar um arquivo
                    </Button>
                  </>
                )}
                <input
                  ref={fileInputRef}
                  type="file"
                  accept=".csv"
                  className="hidden"
                  onChange={(e) => {
                    const file = e.target.files?.[0];
                    if (file) setSelectedFile(file);
                  }}
                />
              </div>
            </div>

            <div className="flex justify-end gap-2">
              {onClose && (
                <Button type="button" variant="outline" onClick={onClose}>
                  Cancelar
                </Button>
              )}
              <Button type="button" onClick={handlePrepareImport} disabled={!selectedFile || isUploading}>
                {isUploading ? "Processando..." : "Preparar importação"}
              </Button>
            </div>
          </CardContent>
        </Card>
      )}

      {step === "mapping" && parseResult && (
        <Card className="bg-white border border-zinc-200/80 rounded-2xl shadow-xs">
          <CardContent className="p-6 space-y-5">
            <div className="flex items-center gap-2 text-xs text-zinc-500">
              <FileText className="w-4 h-4" />
              <span>{parseResult.totalRows} linhas encontradas</span>
            </div>

            <div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
              <div className="space-y-1.5">
                <Label>E-mail (obrigatório)</Label>
                <select
                  value={emailColumn}
                  onChange={(e) => setEmailColumn(e.target.value)}
                  className="w-full h-10 rounded-lg border border-zinc-300 bg-white px-2.5 text-sm"
                >
                  {parseResult.headers.map((h) => (
                    <option key={h} value={h}>
                      {h}
                    </option>
                  ))}
                </select>
              </div>
              <div className="space-y-1.5">
                <Label>Nome</Label>
                <select
                  value={nameColumn}
                  onChange={(e) => setNameColumn(e.target.value)}
                  className="w-full h-10 rounded-lg border border-zinc-300 bg-white px-2.5 text-sm"
                >
                  <option value={NONE_VALUE}>Ignorar</option>
                  {parseResult.headers.map((h) => (
                    <option key={h} value={h}>
                      {h}
                    </option>
                  ))}
                </select>
              </div>
              <div className="space-y-1.5">
                <Label>Telefone</Label>
                <select
                  value={phoneColumn}
                  onChange={(e) => setPhoneColumn(e.target.value)}
                  className="w-full h-10 rounded-lg border border-zinc-300 bg-white px-2.5 text-sm"
                >
                  <option value={NONE_VALUE}>Ignorar</option>
                  {parseResult.headers.map((h) => (
                    <option key={h} value={h}>
                      {h}
                    </option>
                  ))}
                </select>
              </div>
              <div className="space-y-1.5">
                <Label>Tags</Label>
                <select
                  value={tagsColumn}
                  onChange={(e) => setTagsColumn(e.target.value)}
                  className="w-full h-10 rounded-lg border border-zinc-300 bg-white px-2.5 text-sm"
                >
                  <option value={NONE_VALUE}>Ignorar</option>
                  {parseResult.headers.map((h) => (
                    <option key={h} value={h}>
                      {h}
                    </option>
                  ))}
                </select>
              </div>
            </div>

            <div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
              <div className="space-y-1.5">
                <Label>Se o e-mail já existir</Label>
                <select
                  value={duplicateStrategy}
                  onChange={(e) => setDuplicateStrategy(e.target.value as typeof duplicateStrategy)}
                  className="w-full h-10 rounded-lg border border-zinc-300 bg-white px-2.5 text-sm"
                >
                  <option value="IGNORE">Ignorar (manter como está)</option>
                  <option value="UPDATE">Atualizar dados do contato</option>
                  <option value="CREATE_ANYWAY">Criar mesmo assim</option>
                </select>
              </div>
              <div className="space-y-1.5">
                <Label>Lista de destino</Label>
                <select
                  value={targetListId}
                  onChange={(e) => setTargetListId(e.target.value)}
                  className="w-full h-10 rounded-lg border border-zinc-300 bg-white px-2.5 text-sm"
                >
                  <option value="">Nenhuma</option>
                  {lists.map((list) => (
                    <option key={list.id} value={list.id}>
                      {list.name}
                    </option>
                  ))}
                </select>
              </div>
            </div>

            <div className="space-y-2">
              <Label>Pré-visualização (5 primeiras linhas)</Label>
              <div className="overflow-x-auto border border-zinc-200 rounded-lg">
                <Table className="text-xs">
                  <TableHeader>
                    <TableRow>
                      {parseResult.headers.map((h) => (
                        <TableHead key={h}>{h}</TableHead>
                      ))}
                    </TableRow>
                  </TableHeader>
                  <TableBody>
                    {parseResult.sampleRows.map((row, idx) => (
                      <TableRow key={idx}>
                        {parseResult.headers.map((h) => (
                          <TableCell key={h}>{row[h]}</TableCell>
                        ))}
                      </TableRow>
                    ))}
                  </TableBody>
                </Table>
              </div>
            </div>

            <div className="flex justify-end gap-2">
              <Button variant="outline" onClick={reset}>
                Cancelar
              </Button>
              <Button onClick={handleConfirmMapping} disabled={!emailColumn}>
                Confirmar e Iniciar Importação
              </Button>
            </div>
          </CardContent>
        </Card>
      )}

      {step === "processing" && (
        <Card className="bg-white border border-zinc-200/80 rounded-2xl shadow-xs">
          <CardContent className="p-8 text-center space-y-4">
            <p className="text-sm font-bold text-zinc-900">Importando contatos...</p>
            <div className="w-full bg-zinc-100 h-2.5 rounded-full overflow-hidden">
              <div className="bg-indigo-600 h-2.5 rounded-full transition-all" style={{ width: `${progressPct}%` }} />
            </div>
            <p className="text-xs text-zinc-500">
              {job?.processedRows ?? 0} de {job?.totalRows ?? 0} linhas processadas ({progressPct}%)
            </p>
          </CardContent>
        </Card>
      )}

      {step === "done" && job && (
        <Card className="bg-white border border-zinc-200/80 rounded-2xl shadow-xs">
          <CardContent className="p-8 space-y-5">
            <div className="text-center space-y-1">
              <CheckCircle2 className="w-10 h-10 text-emerald-600 mx-auto" />
              <p className="text-sm font-bold text-zinc-900">Importação concluída</p>
            </div>

            <div className="grid grid-cols-2 sm:grid-cols-4 gap-3 text-center">
              <div className="p-3 bg-emerald-50 rounded-xl border border-emerald-100">
                <p className="text-lg font-extrabold text-emerald-700">{job.importedCount}</p>
                <p className="text-[11px] text-emerald-800">Importados</p>
              </div>
              <div className="p-3 bg-indigo-50 rounded-xl border border-indigo-100">
                <p className="text-lg font-extrabold text-indigo-700">{job.updatedCount}</p>
                <p className="text-[11px] text-indigo-800">Atualizados</p>
              </div>
              <div className="p-3 bg-zinc-50 rounded-xl border border-zinc-200">
                <p className="text-lg font-extrabold text-zinc-700">{job.skippedCount}</p>
                <p className="text-[11px] text-zinc-600">Ignorados</p>
              </div>
              <div className="p-3 bg-rose-50 rounded-xl border border-rose-100">
                <p className="text-lg font-extrabold text-rose-700">{job.errorCount}</p>
                <p className="text-[11px] text-rose-800">Com erro</p>
              </div>
            </div>

            {job.errorCount > 0 && (
              <div className="flex items-center justify-center gap-2 text-xs text-rose-700">
                <XCircle className="w-4 h-4" />
                <button
                  type="button"
                  onClick={async () => {
                    try {
                      const { csvContent, fileName } = await exportImportErrorsAction(job.id);
                      downloadCsv(csvContent, fileName);
                    } catch {
                      toast.error("Não foi possível baixar o relatório de erros.");
                    }
                  }}
                  className="font-semibold underline inline-flex items-center gap-1 cursor-pointer"
                >
                  <Download className="w-3.5 h-3.5" />
                  Baixar relatório de erros
                </button>
              </div>
            )}

            <div className="flex justify-center gap-2 pt-2">
              <Button variant="outline" onClick={reset}>
                Importar outro arquivo
              </Button>
              <Link
                href="/contacts"
                className="inline-flex items-center gap-1.5 h-9 px-4 rounded-lg bg-indigo-600 hover:bg-indigo-700 text-white text-xs font-bold transition-colors"
              >
                Ver Contatos
                <ArrowRight className="w-3.5 h-3.5" />
              </Link>
            </div>
          </CardContent>
        </Card>
      )}
    </div>
  );
}
