"use client"

import { z } from "zod"
import { useEffect, useMemo, useState } from "react"
import type { Doc, Id } from "@/convex/_generated/dataModel"
import type { TicketPriority, TicketQueueSummary } from "@/lib/schemas/ticket"
import { useMutation, useQuery } from "convex/react"
import { api } from "@/convex/_generated/api"
import { DEFAULT_TENANT_ID } from "@/lib/constants"
import { useAuth } from "@/lib/auth-client"
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
import { FieldSet, FieldGroup, Field, FieldLabel, FieldError } from "@/components/ui/field"
import { useForm } from "react-hook-form"
import { zodResolver } from "@hookform/resolvers/zod"
import { toast } from "sonner"
import { Spinner } from "@/components/ui/spinner"
import { Dropzone } from "@/components/ui/dropzone"
import { RichTextEditor, sanitizeEditorHtml } from "@/components/ui/rich-text-editor"
import {
  PriorityIcon,
  priorityStyles,
} from "@/components/tickets/priority-select"
import { CategorySelectFields } from "@/components/tickets/category-select"
import { useDefaultQueues } from "@/hooks/use-default-queues"
import { cn } from "@/lib/utils"

const schema = z.object({
  subject: z.string().default(""),
  summary: z.string().optional(),
  description: z.string().default(""),
  priority: z.enum(["LOW", "MEDIUM", "HIGH", "URGENT"]).default("MEDIUM"),
  channel: z.enum(["EMAIL", "WHATSAPP", "CHAT", "PHONE", "API", "MANUAL"]).default("MANUAL"),
  queueName: z.string().nullable().optional(),
  assigneeId: z.string().nullable().optional(),
  categoryId: z.string().min(1, "Selecione uma categoria"),
  subcategoryId: z.string().min(1, "Selecione uma categoria secundária"),
})

export function NewTicketDialog({ triggerClassName }: { triggerClassName?: string } = {}) {
  const [open, setOpen] = useState(false)
  const [loading, setLoading] = useState(false)
  const form = useForm<z.infer<typeof schema>>({
    resolver: zodResolver(schema),
    defaultValues: {
      subject: "",
      summary: "",
      description: "",
      priority: "MEDIUM",
      channel: "MANUAL",
      queueName: null,
      assigneeId: null,
      categoryId: "",
      subcategoryId: "",
    },
    mode: "onTouched",
  })
  const { convexUserId, isStaff } = useAuth()
  const queuesEnabled = Boolean(isStaff && convexUserId)
  const queueArgs = queuesEnabled
    ? { tenantId: DEFAULT_TENANT_ID, viewerId: convexUserId as Id<"users"> }
    : "skip"

  useDefaultQueues(DEFAULT_TENANT_ID)
  const queuesRaw = useQuery(
    queuesEnabled ? api.queues.summary : "skip",
    queueArgs
  ) as TicketQueueSummary[] | undefined
  const queues = useMemo(() => queuesRaw ?? [], [queuesRaw])
  const create = useMutation(api.tickets.create)
  const addComment = useMutation(api.tickets.addComment)
  const staffRaw = useQuery(api.users.listAgents, { tenantId: DEFAULT_TENANT_ID }) as Doc<"users">[] | undefined
  const staff = useMemo(
    () => (staffRaw ?? []).sort((a, b) => a.name.localeCompare(b.name, "pt-BR")),
    [staffRaw]
  )
  const [attachments, setAttachments] = useState<Array<{ storageId: string; name: string; size?: number; type?: string }>>([])
  const attachmentsTotalBytes = useMemo(
    () => attachments.reduce((acc, item) => acc + (item.size ?? 0), 0),
    [attachments]
  )
  const priorityValue = form.watch("priority") as TicketPriority
  const channelValue = form.watch("channel")
  const queueValue = form.watch("queueName") ?? "NONE"
  const assigneeValue = form.watch("assigneeId") ?? null
  const assigneeSelectValue = assigneeValue ?? "NONE"
  const categoryIdValue = form.watch("categoryId")
  const subcategoryIdValue = form.watch("subcategoryId")
  const isSubmitted = form.formState.isSubmitted
  const selectTriggerClass = "flex h-8 w-full items-center justify-between rounded-full border border-slate-300 bg-white px-3 text-sm font-medium text-neutral-800 shadow-sm focus:ring-0 data-[state=open]:border-[#00d6eb]"
  const selectItemClass = "flex items-center gap-2 rounded-md px-2 py-2 text-sm text-neutral-800 transition data-[state=checked]:bg-[#00e8ff]/15 data-[state=checked]:text-neutral-900 focus:bg-[#00e8ff]/10"
  const [assigneeInitialized, setAssigneeInitialized] = useState(false)

  useEffect(() => {
    if (!open) {
      setAssigneeInitialized(false)
      return
    }
    if (assigneeInitialized) return
    if (!convexUserId) return
    form.setValue("assigneeId", convexUserId, { shouldDirty: false, shouldTouch: false })
    setAssigneeInitialized(true)
  }, [open, assigneeInitialized, convexUserId, form])

  const handleCategoryChange = (value: string) => {
    const previous = form.getValues("categoryId") ?? ""
    const next = value ?? ""
    form.setValue("categoryId", next, {
      shouldDirty: previous !== next && previous !== "",
      shouldTouch: true,
      shouldValidate: isSubmitted,
    })
    if (!isSubmitted) {
      form.clearErrors("categoryId")
    }
  }

  const handleSubcategoryChange = (value: string) => {
    const previous = form.getValues("subcategoryId") ?? ""
    const next = value ?? ""
    form.setValue("subcategoryId", next, {
      shouldDirty: previous !== next && previous !== "",
      shouldTouch: true,
      shouldValidate: isSubmitted,
    })
    if (!isSubmitted) {
      form.clearErrors("subcategoryId")
    }
  }

  async function submit(values: z.infer<typeof schema>) {
    if (!convexUserId) return

    const subjectTrimmed = (values.subject ?? "").trim()
    if (subjectTrimmed.length < 3) {
      form.setError("subject", { type: "min", message: "Informe um assunto com pelo menos 3 caracteres." })
      return
    }

    const sanitizedDescription = sanitizeEditorHtml(values.description ?? "")
    const plainDescription = sanitizedDescription.replace(/<[^>]*>/g, "").trim()
    if (plainDescription.length === 0) {
      form.setError("description", { type: "custom", message: "Descreva o contexto do chamado." })
      return
    }

    setLoading(true)
    toast.loading("Criando ticket…", { id: "new-ticket" })
    try {
      const sel = queues.find((q) => q.name === values.queueName)
      const selectedAssignee = form.getValues("assigneeId") ?? null
      const id = await create({
        actorId: convexUserId as Id<"users">,
        tenantId: DEFAULT_TENANT_ID,
        subject: subjectTrimmed,
        summary: values.summary?.trim() || undefined,
        priority: values.priority,
        channel: values.channel,
        queueId: sel?.id as Id<"queues"> | undefined,
        requesterId: convexUserId as Id<"users">,
        assigneeId: selectedAssignee ? (selectedAssignee as Id<"users">) : undefined,
        categoryId: values.categoryId as Id<"ticketCategories">,
        subcategoryId: values.subcategoryId as Id<"ticketSubcategories">,
      })
      const summaryFallback = values.summary?.trim() ?? ""
      const bodyHtml = plainDescription.length > 0 ? sanitizedDescription : summaryFallback
      if (attachments.length > 0 || bodyHtml.trim().length > 0) {
        const typedAttachments = attachments.map((a) => ({
          storageId: a.storageId as unknown as Id<"_storage">,
          name: a.name,
          size: a.size,
          type: a.type,
        }))
        await addComment({ ticketId: id as Id<"tickets">, authorId: convexUserId as Id<"users">, visibility: "INTERNAL", body: bodyHtml, attachments: typedAttachments })
      }
      toast.success("Ticket criado!", { id: "new-ticket" })
      setOpen(false)
      form.reset({
        subject: "",
        summary: "",
        description: "",
        priority: "MEDIUM",
        channel: "MANUAL",
        queueName: null,
        assigneeId: convexUserId ?? null,
        categoryId: "",
        subcategoryId: "",
      })
      form.clearErrors()
      setAssigneeInitialized(false)
      setAttachments([])
      // Navegar para o ticket recém-criado
      window.location.href = `/tickets/${id}`
    } catch {
      toast.error("Não foi possível criar o ticket.", { id: "new-ticket" })
    } finally {
      setLoading(false)
    }
  }

  return (
    <Dialog open={open} onOpenChange={setOpen}>
      <DialogTrigger asChild>
        <Button
          size="sm"
          className={cn(
            "rounded-lg border border-black bg-black px-3 py-1.5 text-sm font-semibold text-white transition hover:bg-[#18181b]/85 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[#18181b]/30",
            triggerClassName
          )}
        >
          Novo ticket
        </Button>
      </DialogTrigger>
      <DialogContent className="max-w-4xl gap-0 overflow-hidden rounded-3xl border border-slate-200 bg-white p-0 shadow-2xl lg:max-w-5xl">
        <div className="max-h-[88vh] overflow-y-auto">
          <div className="space-y-5 px-6 py-7 sm:px-8 md:px-10">
            <form className="space-y-6" onSubmit={form.handleSubmit(submit)}>
              <div className="flex flex-col gap-4 border-b border-slate-200 pb-5 md:flex-row md:items-start md:justify-between">
                <DialogHeader className="gap-1.5 p-0">
                  <DialogTitle className="text-xl font-semibold text-neutral-900">Novo ticket</DialogTitle>
                  <DialogDescription className="text-sm text-neutral-600">
                    Preencha as informações básicas para abrir um chamado.
                  </DialogDescription>
                </DialogHeader>
                <div className="flex justify-end md:min-w-[140px]">
                  <Button
                    type="submit"
                    disabled={loading}
                    className="inline-flex items-center gap-2 rounded-lg border border-black bg-black px-4 py-2 text-sm font-semibold text-white transition hover:bg-[#18181b]/85 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[#18181b]/30 disabled:opacity-60"
                  >
                    {loading ? (
                      <>
                        <Spinner className="me-2" /> Criando…
                      </>
                    ) : (
                      "Criar"
                    )}
                  </Button>
                </div>
              </div>
              <FieldSet>
                <FieldGroup className="lg:grid-cols-[minmax(0,1.2fr)_minmax(0,0.8fr)]">
                  <div className="space-y-4">
                    <Field>
                      <FieldLabel htmlFor="subject" className="flex items-center gap-1">
                        Assunto <span className="text-destructive">*</span>
                      </FieldLabel>
                      <Input id="subject" {...form.register("subject")} placeholder="Ex.: Erro 500 no portal" />
                      <FieldError errors={form.formState.errors.subject ? [{ message: form.formState.errors.subject.message }] : []} />
                    </Field>
                    <Field>
                      <FieldLabel htmlFor="summary">Resumo</FieldLabel>
                      <textarea
                        id="summary"
                        className="min-h-[96px] w-full rounded-lg border border-slate-300 bg-background p-3 text-sm shadow-sm focus-visible:border-[#00d6eb] focus-visible:outline-none"
                        {...form.register("summary")}
                        placeholder="Explique em poucas linhas o contexto do chamado."
                      />
                    </Field>
                    <Field>
                      <FieldLabel className="flex items-center gap-1">
                        Descrição <span className="text-destructive">*</span>
                      </FieldLabel>
                      <RichTextEditor
                        value={form.watch("description") || ""}
                        onChange={(html) =>
                          form.setValue("description", html, {
                            shouldDirty: true,
                            shouldTouch: true,
                            shouldValidate: form.formState.isSubmitted,
                          })
                        }
                        placeholder="Detalhe o problema, passos para reproduzir, links, etc."
                      />
                      <FieldError
                        errors={
                          form.formState.errors.description
                            ? [{ message: form.formState.errors.description.message }]
                            : []
                        }
                      />
                    </Field>
                    <Field>
                      <FieldLabel>Anexos</FieldLabel>
                      <Dropzone
                        onUploaded={(files) => setAttachments((prev) => [...prev, ...files])}
                        className="space-y-1.5 [&>div:first-child]:rounded-2xl [&>div:first-child]:p-4 [&>div:first-child]:pb-5 [&>div:first-child]:shadow-sm"
                        currentFileCount={attachments.length}
                        currentTotalBytes={attachmentsTotalBytes}
                      />
                      <FieldError className="mt-1">Formatos comuns de imagem e documentos são aceitos.</FieldError>
                    </Field>
                  </div>
                  <div className="space-y-4">
                    <Field>
                      <CategorySelectFields
                        tenantId={DEFAULT_TENANT_ID}
                        categoryId={categoryIdValue || null}
                        subcategoryId={subcategoryIdValue || null}
                        onCategoryChange={handleCategoryChange}
                        onSubcategoryChange={handleSubcategoryChange}
                        categoryLabel="Categoria primária *"
                        subcategoryLabel="Categoria secundária *"
                        layout="stacked"
                      />
                      {form.formState.errors.categoryId?.message || form.formState.errors.subcategoryId?.message ? (
                        <FieldError className="mt-1 space-y-0.5">
                          <>
                            {form.formState.errors.categoryId?.message ? <div>{form.formState.errors.categoryId?.message}</div> : null}
                            {form.formState.errors.subcategoryId?.message ? <div>{form.formState.errors.subcategoryId?.message}</div> : null}
                          </>
                        </FieldError>
                      ) : null}
                    </Field>
                    <div className="grid gap-3 sm:grid-cols-2 xl:grid-cols-1 xl:gap-4">
                      <Field>
                        <FieldLabel>Prioridade</FieldLabel>
                        <Select value={priorityValue} onValueChange={(v) => form.setValue("priority", v as z.infer<typeof schema>["priority"])}>
                          <SelectTrigger className={selectTriggerClass}>
                            <SelectValue placeholder="Escolha a prioridade" />
                          </SelectTrigger>
                          <SelectContent className="rounded-xl border border-slate-200 bg-white text-neutral-800 shadow-md">
                            {(["LOW", "MEDIUM", "HIGH", "URGENT"] as const).map((option) => (
                              <SelectItem key={option} value={option} className={selectItemClass}>
                                <span className="inline-flex items-center gap-2">
                                  <PriorityIcon value={option} />
                                  {priorityStyles[option].label}
                                </span>
                              </SelectItem>
                            ))}
                          </SelectContent>
                        </Select>
                      </Field>
                      <Field>
                        <FieldLabel>Canal</FieldLabel>
                        <Select value={channelValue} onValueChange={(v) => form.setValue("channel", v as z.infer<typeof schema>["channel"])}>
                          <SelectTrigger className={selectTriggerClass}>
                            <SelectValue placeholder="Canal" />
                          </SelectTrigger>
                          <SelectContent className="rounded-xl border border-slate-200 bg-white text-neutral-800 shadow-md">
                            <SelectItem value="EMAIL" className={selectItemClass}>
                              E-mail
                            </SelectItem>
                            <SelectItem value="WHATSAPP" className={selectItemClass}>
                              WhatsApp
                            </SelectItem>
                            <SelectItem value="CHAT" className={selectItemClass}>
                              Chat
                            </SelectItem>
                            <SelectItem value="PHONE" className={selectItemClass}>
                              Telefone
                            </SelectItem>
                            <SelectItem value="API" className={selectItemClass}>
                              API
                            </SelectItem>
                            <SelectItem value="MANUAL" className={selectItemClass}>
                              Manual
                            </SelectItem>
                          </SelectContent>
                        </Select>
                      </Field>
                      <Field>
                        <FieldLabel>Fila</FieldLabel>
                        <Select value={queueValue} onValueChange={(v) => form.setValue("queueName", v === "NONE" ? null : v)}>
                          <SelectTrigger className={selectTriggerClass}>
                            <SelectValue placeholder="Sem fila" />
                          </SelectTrigger>
                          <SelectContent className="rounded-xl border border-slate-200 bg-white text-neutral-800 shadow-md">
                            <SelectItem value="NONE" className={selectItemClass}>
                              Sem fila
                            </SelectItem>
                            {queues.map((q) => (
                              <SelectItem key={q.id} value={q.name} className={selectItemClass}>
                                {q.name}
                              </SelectItem>
                            ))}
                          </SelectContent>
                        </Select>
                      </Field>
                      <Field>
                        <FieldLabel>Responsável</FieldLabel>
                        <Select
                          value={assigneeSelectValue}
                          onValueChange={(value) =>
                            form.setValue("assigneeId", value === "NONE" ? null : value, {
                              shouldDirty: value !== assigneeValue,
                              shouldTouch: true,
                            })
                          }
                        >
                          <SelectTrigger className={selectTriggerClass}>
                            <SelectValue placeholder={staff.length === 0 ? "Carregando..." : "Selecione o responsável"} />
                          </SelectTrigger>
                          <SelectContent className="rounded-xl border border-slate-200 bg-white text-neutral-800 shadow-md">
                            <SelectItem value="NONE" className={selectItemClass}>
                              Sem responsável
                            </SelectItem>
                            {staff.map((member) => (
                              <SelectItem key={member._id} value={member._id} className={selectItemClass}>
                                {member.name}
                              </SelectItem>
                            ))}
                          </SelectContent>
                        </Select>
                      </Field>
                    </div>
                  </div>
                </FieldGroup>
              </FieldSet>
            </form>
          </div>
        </div>
      </DialogContent>
    </Dialog>
  )
}
