"use client"

import { useMemo, useState } from "react"
import { useMutation, useQuery } from "convex/react"
import { toast } from "sonner"
import { Plus, Trash2 } from "lucide-react"

import { api } from "@/convex/_generated/api"
import type { Id } from "@/convex/_generated/dataModel"
import { useAuth } from "@/lib/auth-client"
import { cn } from "@/lib/utils"
import { Button } from "@/components/ui/button"
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog"
import { Input } from "@/components/ui/input"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
import { Checkbox } from "@/components/ui/checkbox"
import { SearchableCombobox, type SearchableComboboxOption } from "@/components/ui/searchable-combobox"
import { ScrollArea } from "@/components/ui/scroll-area"
import { Badge } from "@/components/ui/badge"

type DeviceFieldDefinition = {
  id: string
  key: string
  label: string
  description?: string
  type: string
  required: boolean
  options?: Array<{ value: string; label: string }>
  scope: string
  companyId: string | null
}

const DEVICE_SCOPE_OPTIONS: Array<{ value: string; label: string }> = [
  { value: "all", label: "Todos os dispositivos" },
  { value: "desktop", label: "Somente desktops" },
  { value: "mobile", label: "Somente celulares" },
  { value: "tablet", label: "Somente tablets" },
]

type DeviceCustomFieldManagerProps = {
  tenantId: string
  defaultScope?: string | null
  defaultCompanyId?: string | null
  className?: string
}

export function DeviceCustomFieldManager({
  tenantId,
  defaultScope,
  defaultCompanyId,
  className,
}: DeviceCustomFieldManagerProps) {
  const { convexUserId, role } = useAuth()
  const isAdmin = (role ?? "").toLowerCase() === "admin"
  const viewerId = convexUserId ? (convexUserId as Id<"users">) : null
  const [open, setOpen] = useState(false)
  const [confirmDeleteId, setConfirmDeleteId] = useState<string | null>(null)

  const fields = useQuery(
    api.deviceFields.list,
    open && isAdmin && viewerId
      ? {
          tenantId,
          viewerId,
          scope: undefined,
          companyId: undefined,
        }
      : "skip"
  ) as DeviceFieldDefinition[] | undefined

  const companies = useQuery(
    api.companies.list,
    open && isAdmin && viewerId
      ? { tenantId, viewerId }
      : "skip"
  ) as Array<{ id: string; name: string; slug?: string }> | undefined

  const createField = useMutation(api.deviceFields.create)
  const removeField = useMutation(api.deviceFields.remove)

  const companyOptions = useMemo<SearchableComboboxOption[]>(() => {
    if (!companies) return []
    return companies
      .map((company) => ({
        value: company.id,
        label: company.name,
        description: company.slug ?? undefined,
        keywords: company.slug ? [company.slug] : [],
      }))
      .sort((a, b) => a.label.localeCompare(b.label, "pt-BR"))
  }, [companies])

  const companyLabelById = useMemo(() => {
    const map = new Map<string, string>()
    companyOptions.forEach((option) => map.set(option.value, option.label))
    return map
  }, [companyOptions])

  const [label, setLabel] = useState("")
  const [description, setDescription] = useState("")
  const [type, setType] = useState<string>("text")
  const [required, setRequired] = useState(false)
  const [scope, setScope] = useState<string>(defaultScope ?? "all")
  const [companySelection, setCompanySelection] = useState<string>(defaultCompanyId ?? "all")
  const [options, setOptions] = useState<Array<{ label: string; value: string }>>([])
  const [isSubmitting, setIsSubmitting] = useState(false)

  const resetForm = () => {
    setLabel("")
    setDescription("")
    setType("text")
    setRequired(false)
    setScope(defaultScope ?? "all")
    setCompanySelection(defaultCompanyId ?? "all")
    setOptions([])
  }

  const handleCreate = async () => {
    if (!viewerId) return
    const trimmedLabel = label.trim()
    if (trimmedLabel.length < 2) {
      toast.error("Informe um rótulo para o campo.")
      return
    }
    const normalizedOptions =
      type === "select" || type === "multiselect"
        ? options
            .map((option) => ({
              label: option.label.trim(),
              value: option.value.trim(),
            }))
            .filter((option) => option.label.length > 0 && option.value.length > 0)
        : undefined
    if ((type === "select" || type === "multiselect") && (!normalizedOptions || normalizedOptions.length === 0)) {
      toast.error("Adicione ao menos uma opção para o campo de seleção.")
      return
    }
    setIsSubmitting(true)
    try {
      await createField({
        tenantId,
        actorId: viewerId,
        label: trimmedLabel,
        description: description.trim() || undefined,
        type,
        required,
        options: normalizedOptions,
        scope: scope === "all" ? undefined : scope,
        companyId: companySelection === "all" ? undefined : (companySelection as Id<"companies">),
      })
      toast.success("Campo criado com sucesso.")
      resetForm()
    } catch (error) {
      console.error(error)
      toast.error("Não foi possível criar o campo personalizado.")
    } finally {
      setIsSubmitting(false)
    }
  }

  const handleDelete = async (fieldId: string) => {
    if (!viewerId) return
    setConfirmDeleteId(null)
    try {
      await removeField({
        tenantId,
        actorId: viewerId,
        fieldId: fieldId as Id<"deviceFields">,
      })
      toast.success("Campo removido com sucesso.")
    } catch (error) {
      console.error(error)
      toast.error("Não foi possível remover o campo.")
    }
  }

  if (!isAdmin) {
    return null
  }

  const triggerButton = (
    <Button
      type="button"
      variant="outline"
      size="sm"
      className={cn("gap-2", className)}
      onClick={() => setOpen(true)}
    >
      <Plus className="size-3.5" />
      Gerenciar campos
    </Button>
  )

  return (
    <>
      {triggerButton}
      <Dialog
        open={open}
        onOpenChange={(value) => {
        setOpen(value)
        if (!value) {
          resetForm()
        }
      }}
      >
        <DialogContent className="max-w-4xl space-y-5">
          <DialogHeader>
            <DialogTitle>Campos personalizados de dispositivos</DialogTitle>
            <DialogDescription>
              Cadastre e organize campos adicionais que podem ser preenchidos pelos dispositivos monitorados.
              Você pode restringir um campo a um tipo de dispositivo específico ou a uma empresa selecionada.
            </DialogDescription>
          </DialogHeader>

          <div className="grid gap-6 lg:grid-cols-[1.4fr_1fr] xl:grid-cols-[1.6fr_1fr]">
            <div className="space-y-3">
              <div className="flex items-center justify-between">
                <h3 className="text-sm font-semibold text-neutral-900">Campos cadastrados</h3>
                <Badge variant="outline" className="rounded-full px-2.5 py-0.5 text-[11px] font-semibold">
                  {fields?.length ?? 0}
                </Badge>
              </div>
              <ScrollArea className="max-h-[320px] rounded-lg border border-slate-200">
                <div className="divide-y divide-slate-200">
                  {fields && fields.length > 0 ? (
                    fields.map((field) => (
                      <div key={field.id} className="flex flex-col gap-2 p-3 text-sm text-neutral-700">
                        <div className="flex items-center justify-between gap-2">
                          <div>
                            <p className="font-semibold text-neutral-900">{field.label}</p>
                            <p className="text-xs text-neutral-500">Chave: {field.key}</p>
                          </div>
                          <Button
                            type="button"
                            variant="ghost"
                            size="icon"
                            className="text-neutral-500 hover:text-destructive"
                            onClick={() => setConfirmDeleteId(field.id)}
                          >
                            <Trash2 className="size-4" />
                          </Button>
                        </div>
                        <div className="flex flex-wrap items-center gap-2 text-xs text-neutral-500">
                          <span className="inline-flex items-center gap-1 rounded-full bg-slate-100 px-2 py-0.5">
                            Tipo: <span className="font-medium text-neutral-800">{translateType(field.type)}</span>
                          </span>
                          <span className="inline-flex items-center gap-1 rounded-full bg-slate-100 px-2 py-0.5">
                            Escopo: <span className="font-medium text-neutral-800">{translateScope(field.scope)}</span>
                          </span>
                          <span className="inline-flex items-center gap-1 rounded-full bg-slate-100 px-2 py-0.5">
                            Empresa:{" "}
                            <span className="font-medium text-neutral-800">
                              {field.companyId ? companyLabelById.get(field.companyId) ?? "Empresa específica" : "Todas"}
                            </span>
                          </span>
                          {field.required ? (
                            <span className="inline-flex items-center gap-1 rounded-full bg-amber-100 px-2 py-0.5 text-amber-700">
                              Obrigatório
                            </span>
                          ) : null}
                        </div>
                        {field.description ? (
                          <p className="text-xs text-neutral-500">{field.description}</p>
                        ) : null}
                        {(field.options ?? []).length > 0 ? (
                          <div className="space-y-1">
                            <p className="text-xs font-medium text-neutral-500">Opções:</p>
                            <div className="flex flex-wrap gap-2">
                              {field.options!.map((option) => (
                                <span
                                  key={option.value}
                                  className="inline-flex items-center rounded-full border border-slate-200 px-2 py-0.5 text-[11px] text-neutral-600"
                                >
                                  {option.label} <span className="ml-1 text-neutral-400">({option.value})</span>
                                </span>
                              ))}
                            </div>
                          </div>
                        ) : null}
                      </div>
                    ))
                  ) : (
                    <div className="p-4 text-sm text-neutral-500">
                      Nenhum campo cadastrado ainda.
                    </div>
                  )}
                </div>
              </ScrollArea>
            </div>

            <div className="space-y-4 rounded-lg border border-slate-200 bg-white p-4">
              <div className="space-y-1">
                <h3 className="text-sm font-semibold text-neutral-900">Novo campo</h3>
                <p className="text-xs text-neutral-500">
                  Informe o rótulo, tipo e demais características do campo personalizado.
                </p>
              </div>
              <div className="space-y-3">
                <div className="space-y-1">
                  <label className="text-xs font-medium text-neutral-600">Rótulo</label>
                  <Input value={label} onChange={(event) => setLabel(event.target.value)} placeholder="Ex.: Patrimônio" />
                </div>
                <div className="space-y-1">
                  <label className="text-xs font-medium text-neutral-600">Descrição (opcional)</label>
                  <Input
                    value={description}
                    onChange={(event) => setDescription(event.target.value)}
                    placeholder="Texto auxiliar exibido aos agentes"
                  />
                </div>
                <div className="grid gap-3 sm:grid-cols-2">
                  <div className="space-y-1">
                    <label className="text-xs font-medium text-neutral-600">Tipo</label>
                    <Select value={type} onValueChange={(value) => setType(value)}>
                      <SelectTrigger>
                        <SelectValue placeholder="Selecione" />
                      </SelectTrigger>
                      <SelectContent>
                        <SelectItem value="text">Texto</SelectItem>
                        <SelectItem value="number">Número</SelectItem>
                        <SelectItem value="date">Data</SelectItem>
                        <SelectItem value="boolean">Verdadeiro/Falso</SelectItem>
                        <SelectItem value="select">Seleção única</SelectItem>
                        <SelectItem value="multiselect">Seleção múltipla</SelectItem>
                      </SelectContent>
                    </Select>
                  </div>
                  <div className="space-y-1">
                    <label className="text-xs font-medium text-neutral-600">Escopo</label>
                    <Select value={scope} onValueChange={(value) => setScope(value)}>
                      <SelectTrigger>
                        <SelectValue placeholder="Selecione" />
                      </SelectTrigger>
                      <SelectContent>
                        {DEVICE_SCOPE_OPTIONS.map((option) => (
                          <SelectItem key={option.value} value={option.value}>
                            {option.label}
                          </SelectItem>
                        ))}
                      </SelectContent>
                    </Select>
                  </div>
                </div>
                <div className="space-y-1">
                  <label className="text-xs font-medium text-neutral-600">Empresa</label>
                  <SearchableCombobox
                    value={companySelection}
                    onValueChange={(value) => setCompanySelection(value ?? "all")}
                    options={[
                      { value: "all", label: "Todas as empresas" },
                      ...companyOptions,
                    ]}
                    placeholder="Selecionar empresa..."
                    searchPlaceholder="Pesquisar empresa..."
                    emptyText="Nenhuma empresa encontrada."
                  />
                </div>
                <label className="inline-flex items-center gap-2 text-xs font-medium text-neutral-600">
                  <Checkbox checked={required} onCheckedChange={(value) => setRequired(value === true)} />
                  Campo obrigatório
                </label>
                {(type === "select" || type === "multiselect") ? (
                  <div className="space-y-2 rounded-lg border border-slate-200 p-3">
                    <p className="text-xs font-medium text-neutral-600">
                      Opções de seleção
                    </p>
                    <div className="grid gap-2">
                      {options.map((option, index) => (
                        <div key={`option-${index}`} className="grid gap-2 sm:grid-cols-[1fr_160px_auto]">
                          <Input
                            value={option.label}
                            placeholder="Rótulo"
                            onChange={(event) =>
                              setOptions((previous) => {
                                const next = [...previous]
                                next[index] = { ...next[index], label: event.target.value }
                                return next
                              })
                            }
                          />
                          <Input
                            value={option.value}
                            placeholder="Valor"
                            onChange={(event) =>
                              setOptions((previous) => {
                                const next = [...previous]
                                next[index] = { ...next[index], value: event.target.value }
                                return next
                              })
                            }
                          />
                          <Button
                            type="button"
                            variant="ghost"
                            size="icon"
                            onClick={() =>
                              setOptions((previous) => previous.filter((_, optionIndex) => optionIndex !== index))
                            }
                          >
                            <Trash2 className="size-4" />
                          </Button>
                        </div>
                      ))}
                    </div>
                    <div className="flex justify-end">
                      <Button
                        type="button"
                        size="sm"
                        variant="outline"
                        className="gap-2"
                        onClick={() => setOptions((previous) => [...previous, { label: "", value: "" }])}
                      >
                        <Plus className="size-3.5" />
                        Adicionar opção
                      </Button>
                    </div>
                  </div>
                ) : null}
              </div>
              <DialogFooter className="flex flex-col gap-2 sm:flex-row sm:justify-end">
                <Button type="button" variant="outline" onClick={resetForm}>
                  Limpar
                </Button>
                <Button type="button" onClick={handleCreate} disabled={isSubmitting}>
                  {isSubmitting ? "Criando..." : "Criar campo"}
                </Button>
              </DialogFooter>
            </div>
          </div>
        </DialogContent>
      </Dialog>

      <Dialog open={confirmDeleteId !== null} onOpenChange={(value) => {
        if (!value) setConfirmDeleteId(null)
      }}>
        <DialogContent className="max-w-md space-y-4">
          <DialogHeader>
            <DialogTitle>Remover campo personalizado</DialogTitle>
            <DialogDescription>
              Esta ação não pode ser desfeita. Confirme para remover o campo selecionado. Os dispositivos deixarão de exibir este dado imediatamente.
            </DialogDescription>
          </DialogHeader>
          <DialogFooter className="flex flex-col gap-2 sm:flex-row sm:justify-end">
            <Button type="button" variant="outline" onClick={() => setConfirmDeleteId(null)}>
              Cancelar
            </Button>
            <Button
              type="button"
              variant="destructive"
              onClick={() => {
                if (confirmDeleteId) {
                  void handleDelete(confirmDeleteId)
                }
              }}
            >
              Remover
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </>
  )
}

function translateType(type: string) {
  switch (type) {
    case "text":
      return "Texto"
    case "number":
      return "Número"
    case "date":
      return "Data"
    case "boolean":
      return "Verdadeiro/Falso"
    case "select":
      return "Seleção única"
    case "multiselect":
      return "Seleção múltipla"
    default:
      return type
  }
}

function translateScope(scope: string) {
  const normalized = (scope ?? "all").toLowerCase()
  const matched = DEVICE_SCOPE_OPTIONS.find((option) => option.value === normalized)
  return matched?.label ?? "Todos os dispositivos"
}
