import { useState, useMemo, useEffect } from "react";
import { Layers, Plus, Edit, Trash2 } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Textarea } from "@/components/ui/textarea";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog";
import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle } from "@/components/ui/alert-dialog";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import { usePrompts } from "@/contexts/PromptsContext";
import { areasService, type AreaItem } from "@/services/areas";
import { toast } from "sonner";

export function AreasView() {
  const { areas, setAreas, areaDescriptions, setAreaDescriptions, setPrompts } = usePrompts();

  const [isCreateOpen, setIsCreateOpen] = useState(false);
  const [isEditOpen, setIsEditOpen] = useState(false);
  const [isDeleteOpen, setIsDeleteOpen] = useState(false);
  const [selectedAreaItem, setSelectedAreaItem] = useState<AreaItem | null>(null);
  const [editName, setEditName] = useState("");
  const [editDescription, setEditDescription] = useState("");
  const [newName, setNewName] = useState("");
  const [newDescription, setNewDescription] = useState("");
  const [isCreatingArea, setIsCreatingArea] = useState(false);
  const [isSavingEdit, setIsSavingEdit] = useState(false);
  const [isDeletingArea, setIsDeletingArea] = useState(false);

  const selectedArea = selectedAreaItem?.nome ?? null;

  const [filterNome, setFilterNome] = useState("");
  const [currentPage, setCurrentPage] = useState(1);
  const [itemsPerPage, setItemsPerPage] = useState(10);

  const [areasList, setAreasList] = useState<AreaItem[]>([]);
  const [totalRegistros, setTotalRegistros] = useState(0);
  const [totalPaginas, setTotalPaginas] = useState(1);
  const [loadingList, setLoadingList] = useState(true);
  const normalizedAreas = useMemo(
    () => new Set(areas.map((area) => area.trim().toLocaleLowerCase())),
    [areas]
  );

  const totalPages = Math.max(1, totalPaginas);
  const isFiltering = filterNome.trim().length > 0;
  const createName = newName.trim();
  const isCreateNameDuplicated = createName.length > 0 && normalizedAreas.has(createName.toLocaleLowerCase());
  const editNameNormalized = editName.trim().toLocaleLowerCase();
  const selectedAreaNormalized = selectedAreaItem?.nome.trim().toLocaleLowerCase();
  const isEditNameDuplicated =
    editName.trim().length > 0 &&
    editNameNormalized !== selectedAreaNormalized &&
    normalizedAreas.has(editNameNormalized);

  useEffect(() => {
    let cancelled = false;
    setLoadingList(true);
    areasService.listar({
      nome: filterNome.trim() || undefined,
      page: currentPage,
      per_page: itemsPerPage,
    })
      .then((res) => {
        if (!cancelled) {
          setAreasList(res.data ?? []);
          setTotalRegistros(res.total_registros ?? 0);
          setTotalPaginas(res.total_paginas ?? 1);
          setAreas((prev) => [...new Set([...prev, ...(res.data ?? []).map((a) => a.nome)])].sort((a, b) => a.localeCompare(b)));
          setAreaDescriptions((prev) => ({
            ...prev,
            ...Object.fromEntries((res.data ?? []).map((a) => [a.nome, a.descricao ?? ""])),
          }));
        }
      })
      .catch((e: unknown) => {
        if (!cancelled) {
          const msg = e && typeof e === "object" && "message" in e ? (e as { message: string }).message : "Erro ao carregar áreas.";
          toast.error(msg);
          setAreasList([]);
          setTotalRegistros(0);
          setTotalPaginas(1);
        }
      })
      .finally(() => {
        if (!cancelled) setLoadingList(false);
      });
    return () => { cancelled = true; };
  }, [filterNome, currentPage, itemsPerPage]);

  useEffect(() => {
    setCurrentPage(1);
  }, [filterNome]);

  const handleItemsPerPageChange = (value: string) => {
    setItemsPerPage(Number(value));
    setCurrentPage(1);
  };

  const handleCreate = async () => {
    const name = newName.trim();
    const description = newDescription.trim();
    if (!name) return;
    if (normalizedAreas.has(name.toLocaleLowerCase())) {
      toast.error("Já existe uma área com esse nome.");
      return;
    }
    setIsCreatingArea(true);
    try {
      await areasService.criar(name, description);
      setAreas((prev) => [...prev, name].sort((a, b) => a.localeCompare(b)));
      setAreaDescriptions((prev) => ({ ...prev, [name]: description }));
      setNewName("");
      setNewDescription("");
      setIsCreateOpen(false);
      toast.success("Área criada.");
      areasService.listar({ nome: filterNome.trim() || undefined, page: currentPage, per_page: itemsPerPage })
        .then((res) => {
          setAreasList(res.data ?? []);
          setTotalRegistros(res.total_registros ?? 0);
          setTotalPaginas(res.total_paginas ?? 1);
          setAreas((p) => [...new Set([...p, ...(res.data ?? []).map((a) => a.nome)])].sort((a, b) => a.localeCompare(b)));
          setAreaDescriptions((p) => ({ ...p, ...Object.fromEntries((res.data ?? []).map((a) => [a.nome, a.descricao ?? ""])) }));
        })
        .catch(() => {});
    } catch (e: unknown) {
      const message = e && typeof e === "object" && "message" in e ? (e as { message: string }).message : "Erro ao criar área.";
      toast.error(message);
    } finally {
      setIsCreatingArea(false);
    }
  };

  const openEdit = (item: AreaItem) => {
    setSelectedAreaItem(item);
    setEditName(item.nome);
    setEditDescription(item.descricao ?? areaDescriptions[item.nome] ?? "");
    setIsEditOpen(true);
  };

  const refetchList = () => {
    areasService.listar({ nome: filterNome.trim() || undefined, page: currentPage, per_page: itemsPerPage })
      .then((res) => {
        setAreasList(res.data ?? []);
        setTotalRegistros(res.total_registros ?? 0);
        setTotalPaginas(res.total_paginas ?? 1);
        setAreas((p) => [...new Set([...p, ...(res.data ?? []).map((a) => a.nome)])].sort((a, b) => a.localeCompare(b)));
        setAreaDescriptions((p) => ({ ...p, ...Object.fromEntries((res.data ?? []).map((a) => [a.nome, a.descricao ?? ""])) }));
      })
      .catch(() => {});
  };

  const handleSaveEdit = async () => {
    if (!selectedAreaItem || !editName.trim()) {
      setIsEditOpen(false);
      return;
    }
    const name = editName.trim();
    const description = editDescription.trim();
    if (
      name.toLocaleLowerCase() !== selectedAreaItem.nome.trim().toLocaleLowerCase() &&
      normalizedAreas.has(name.toLocaleLowerCase())
    ) {
      toast.error("Já existe uma área com esse nome.");
      return;
    }
    setIsSavingEdit(true);
    try {
      await areasService.editar(selectedAreaItem.id, name, description);
      const oldName = selectedAreaItem.nome;
      if (name !== oldName) {
        setAreas((prev) => prev.map((a) => (a === oldName ? name : a)).sort((a, b) => a.localeCompare(b)));
        setPrompts((prev) => prev.map((p) => (p.area === oldName ? { ...p, area: name } : p)));
      }
      setAreaDescriptions((prev) => {
        const next = { ...prev };
        if (oldName in next) delete next[oldName];
        next[name] = description;
        return next;
      });
      setSelectedAreaItem(null);
      setIsEditOpen(false);
      toast.success("Área atualizada.");
      refetchList();
    } catch (e: unknown) {
      const message = e && typeof e === "object" && "message" in e ? (e as { message: string }).message : "Erro ao editar área.";
      toast.error(message);
    } finally {
      setIsSavingEdit(false);
    }
  };

  const openDelete = (item: AreaItem) => {
    setSelectedAreaItem(item);
    setIsDeleteOpen(true);
  };

  const handleDelete = async () => {
    if (!selectedAreaItem || totalRegistros <= 1) return;
    setIsDeletingArea(true);
    try {
      await areasService.deletar(selectedAreaItem.id);
      const fallback = areasList.find((a) => a.id !== selectedAreaItem!.id)?.nome ?? areas.find((a) => a !== selectedAreaItem!.nome);
      if (fallback) {
        setPrompts((prev) =>
          prev.map((p) => (p.area === selectedAreaItem.nome ? { ...p, area: fallback } : p))
        );
      }
      setAreas((prev) => prev.filter((a) => a !== selectedAreaItem.nome));
      setAreaDescriptions((prev) => {
        const next = { ...prev };
        delete next[selectedAreaItem.nome];
        return next;
      });
      setSelectedAreaItem(null);
      setIsDeleteOpen(false);
      toast.success("Área excluída.");
      refetchList();
    } catch (e: unknown) {
      const message = e && typeof e === "object" && "message" in e ? (e as { message: string }).message : "Erro ao excluir área.";
      toast.error(message);
    } finally {
      setIsDeletingArea(false);
    }
  };

  const clearFilters = () => {
    setFilterNome("");
    setCurrentPage(1);
  };

  return (
    <div className="flex flex-col h-full bg-background pb-16 md:pb-0">
      <div className="p-3 md:p-6 border-b border-border">
        <div className="flex flex-col md:flex-row items-start md:items-center justify-between gap-3 mb-4">
          <h1 className="text-xl md:text-3xl font-bold text-foreground flex items-center gap-2">
            <Layers className="w-5 h-5 md:w-6 md:h-6" />
            Áreas
          </h1>
          <div className="flex gap-2 w-full md:w-auto">
            <Button onClick={() => setIsCreateOpen(true)} className="gap-1 md:gap-2 flex-1 md:flex-none text-xs md:text-sm">
              <Plus className="w-3 h-3 md:w-4 md:h-4" />
              <span className="hidden sm:inline">Nova área</span>
              <span className="sm:hidden">Novo</span>
            </Button>
          </div>
        </div>
        {(loadingList || totalRegistros > 0) && (
          <div className="flex flex-col md:flex-row items-stretch md:items-center gap-2 md:gap-4">
            <Input
              placeholder="Buscar áreas..."
              value={filterNome}
              onChange={(e) => setFilterNome(e.target.value)}
              className="w-full md:max-w-sm text-sm"
            />
            {filterNome.trim() && (
              <Button variant="ghost" size="sm" onClick={clearFilters}>
                Limpar
              </Button>
            )}
            <div className="flex items-center gap-2 justify-between md:justify-start">
              <span className="text-xs md:text-sm text-muted-foreground whitespace-nowrap">Itens:</span>
              <Select value={itemsPerPage.toString()} onValueChange={handleItemsPerPageChange}>
                <SelectTrigger className="w-16 md:w-20">
                  <SelectValue />
                </SelectTrigger>
                <SelectContent>
                  <SelectItem value="5">5</SelectItem>
                  <SelectItem value="10">10</SelectItem>
                  <SelectItem value="20">20</SelectItem>
                  <SelectItem value="50">50</SelectItem>
                </SelectContent>
              </Select>
            </div>
          </div>
        )}
      </div>

      <div className="flex-1 overflow-auto p-3 md:p-6">
        {!loadingList && totalRegistros === 0 && !isFiltering ? (
          <Card className="max-w-2xl mx-auto mt-12">
            <CardHeader>
              <CardTitle className="flex items-center gap-2">
                <Layers className="w-5 h-5" />
                Nenhuma área cadastrada
              </CardTitle>
              <CardDescription>
                Crie a primeira área para usar nos prompts (ex.: Bate-papo, Imagens).
              </CardDescription>
            </CardHeader>
            <CardContent>
              <Button onClick={() => setIsCreateOpen(true)}>
                <Plus className="w-4 h-4 mr-2" />
                Nova área
              </Button>
            </CardContent>
          </Card>
        ) : (
          <>
            <div className="border rounded-lg overflow-x-auto">
              <Table>
                <TableHeader>
                  <TableRow>
                    <TableHead className="min-w-[200px] font-semibold text-xs md:text-sm">Área</TableHead>
                    <TableHead className="text-center text-xs md:text-sm">Ações</TableHead>
                  </TableRow>
                </TableHeader>
                <TableBody>
                  {loadingList ? (
                    <TableRow>
                      <TableCell colSpan={2} className="text-center text-muted-foreground py-8">
                        Carregando...
                      </TableCell>
                    </TableRow>
                  ) : totalRegistros === 0 ? (
                    <TableRow>
                      <TableCell colSpan={2} className="text-center text-muted-foreground py-8">
                        Nenhum resultado para o filtro {filterNome.trim() ? `"${filterNome.trim()}"` : "atual"}.
                      </TableCell>
                    </TableRow>
                  ) : (
                    areasList.map((item) => (
                      <TableRow key={item.id}>
                        <TableCell className="font-medium text-xs md:text-sm">{item.nome}</TableCell>
                        <TableCell>
                          <div className="flex items-center justify-center gap-1">
                            <Button
                              variant="ghost"
                              size="icon"
                              onClick={() => openEdit(item)}
                              title="Editar"
                              className="h-7 w-7 md:h-9 md:w-9 hover:bg-slate-100 dark:hover:bg-slate-700 hover:text-foreground"
                            >
                              <Edit className="w-3 h-3 md:w-4 md:h-4" />
                            </Button>
                            <Button
                              variant="ghost"
                              size="icon"
                              onClick={() => openDelete(item)}
                              title="Excluir"
                              disabled={totalRegistros <= 1}
                              className="h-7 w-7 md:h-9 md:w-9 hover:bg-slate-100 dark:hover:bg-slate-700 text-destructive hover:text-destructive"
                            >
                              <Trash2 className="w-3 h-3 md:w-4 md:h-4" />
                            </Button>
                          </div>
                        </TableCell>
                      </TableRow>
                    ))
                  )}
                </TableBody>
              </Table>
            </div>

            {!loadingList && totalRegistros > 0 && (
              <div className="flex flex-col sm:flex-row items-stretch sm:items-center justify-between gap-2 mt-4">
                <p className="text-xs md:text-sm text-muted-foreground text-center sm:text-left">
                  Mostrando {totalRegistros} {totalRegistros === 1 ? "área" : "áreas"}
                </p>
                <div className="flex gap-1 md:gap-2 justify-center">
                  <Button
                    variant="outline"
                    size="sm"
                    onClick={() => setCurrentPage((p) => Math.max(1, p - 1))}
                    disabled={currentPage === 1}
                    className="text-xs md:text-sm px-2 md:px-4"
                  >
                    <span className="hidden sm:inline">Anterior</span>
                    <span className="sm:hidden">Ant</span>
                  </Button>
                  <div className="flex items-center gap-1">
                    {Array.from({ length: Math.min(totalPages, 5) }, (_, i) => {
                      let page: number;
                      if (totalPages <= 5) {
                        page = i + 1;
                      } else if (currentPage <= 3) {
                        page = i + 1;
                      } else if (currentPage >= totalPages - 2) {
                        page = totalPages - 4 + i;
                      } else {
                        page = currentPage - 2 + i;
                      }
                      return (
                        <Button
                          key={page}
                          variant={currentPage === page ? "default" : "outline"}
                          size="sm"
                          onClick={() => setCurrentPage(page)}
                          className="w-8 h-8 md:w-10 md:h-9 p-0 text-xs md:text-sm"
                        >
                          {page}
                        </Button>
                      );
                    })}
                  </div>
                  <Button
                    variant="outline"
                    size="sm"
                    onClick={() => setCurrentPage((p) => Math.min(totalPages, p + 1))}
                    disabled={currentPage === totalPages}
                    className="text-xs md:text-sm px-2 md:px-4"
                  >
                    <span className="hidden sm:inline">Próxima</span>
                    <span className="sm:hidden">Prox</span>
                  </Button>
                </div>
              </div>
            )}
          </>
        )}
      </div>

      {/* Modal Novo */}
      <Dialog open={isCreateOpen} onOpenChange={setIsCreateOpen}>
        <DialogContent>
          <DialogHeader>
            <DialogTitle>Nova área</DialogTitle>
            <DialogDescription>Informe o nome e, se quiser, a descrição da área. Ela poderá ser usada nos prompts.</DialogDescription>
          </DialogHeader>
          <div className="space-y-4 py-2">
            <div>
              <Label htmlFor="new-area">Nome</Label>
              <Input
                id="new-area"
                value={newName}
                onChange={(e) => setNewName(e.target.value)}
                placeholder="Ex: Suporte"
                onKeyDown={(e) => e.key === "Enter" && handleCreate()}
                aria-invalid={isCreateNameDuplicated}
                className={isCreateNameDuplicated ? "border-destructive focus-visible:ring-destructive" : undefined}
              />
              {isCreateNameDuplicated && (
                <p className="mt-1 text-sm text-destructive">
                  Já existe uma área com esse nome. Escolha um nome diferente.
                </p>
              )}
            </div>
            <div>
              <Label htmlFor="new-area-desc">Descrição</Label>
              <Textarea
                id="new-area-desc"
                value={newDescription}
                onChange={(e) => setNewDescription(e.target.value)}
                placeholder="Ex: Área para prompts de atendimento"
                rows={3}
                className="resize-none"
              />
            </div>
          </div>
          <DialogFooter>
            <Button variant="outline" onClick={() => setIsCreateOpen(false)} disabled={isCreatingArea}>
              Cancelar
            </Button>
            <Button onClick={handleCreate} disabled={!newName.trim() || isCreateNameDuplicated || isCreatingArea}>
              {isCreatingArea ? "Criando..." : "Criar"}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      {/* Modal Editar */}
      <Dialog open={isEditOpen} onOpenChange={setIsEditOpen}>
        <DialogContent>
          <DialogHeader>
            <DialogTitle>Editar área</DialogTitle>
            <DialogDescription>Altere o nome e a descrição da área. Os prompts vinculados serão atualizados.</DialogDescription>
          </DialogHeader>
          <div className="space-y-4 py-2">
            <div>
              <Label htmlFor="edit-area">Nome</Label>
              <Input
                id="edit-area"
                value={editName}
                onChange={(e) => setEditName(e.target.value)}
                onKeyDown={(e) => e.key === "Enter" && handleSaveEdit()}
                aria-invalid={isEditNameDuplicated}
                className={isEditNameDuplicated ? "border-destructive focus-visible:ring-destructive" : undefined}
              />
              {isEditNameDuplicated && (
                <p className="mt-1 text-sm text-destructive">
                  Já existe uma área com esse nome. Escolha um nome diferente.
                </p>
              )}
            </div>
            <div>
              <Label htmlFor="edit-area-desc">Descrição</Label>
              <Textarea
                id="edit-area-desc"
                value={editDescription}
                onChange={(e) => setEditDescription(e.target.value)}
                placeholder="Ex: Área para prompts de atendimento"
                rows={3}
                className="resize-none"
              />
            </div>
          </div>
          <DialogFooter>
            <Button variant="outline" onClick={() => setIsEditOpen(false)} disabled={isSavingEdit}>
              Cancelar
            </Button>
            <Button onClick={handleSaveEdit} disabled={!editName.trim() || isEditNameDuplicated || isSavingEdit}>
              {isSavingEdit ? "Salvando..." : "Salvar"}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      {/* Modal Excluir */}
      <AlertDialog open={isDeleteOpen} onOpenChange={setIsDeleteOpen}>
        <AlertDialogContent>
          <AlertDialogHeader>
            <AlertDialogTitle>Excluir área</AlertDialogTitle>
            <AlertDialogDescription>
             Deseja excluir a área "{selectedArea}"? Esta ação não pode ser desfeita.
            </AlertDialogDescription>
          </AlertDialogHeader>
          <AlertDialogFooter>
            <AlertDialogCancel disabled={isDeletingArea} className="bg-white text-slate-900 hover:bg-slate-100 hover:text-slate-900">
              Cancelar
            </AlertDialogCancel>
            <AlertDialogAction
              onClick={handleDelete}
              disabled={totalRegistros <= 1 || isDeletingArea}
              className={(totalRegistros <= 1 || isDeletingArea) ? "opacity-50 cursor-not-allowed" : "bg-destructive text-destructive-foreground hover:bg-destructive/90"}
            >
              {isDeletingArea ? "Excluindo..." : "Excluir"}
            </AlertDialogAction>
          </AlertDialogFooter>
        </AlertDialogContent>
      </AlertDialog>
    </div>
  );
}
