"use client"

import { useEffect, useMemo, useRef, useState } from "react"
import { format, parseISO } from "date-fns"
import { ptBR } from "date-fns/locale"
import { useRouter } from "next/navigation"
import { useMutation, useQuery } from "convex/react"
import { toast } from "sonner"
import { api } from "@/convex/_generated/api"
import type { Id } from "@/convex/_generated/dataModel"
import { DEFAULT_TENANT_ID } from "@/lib/constants"
import type { TicketPriority } from "@/lib/schemas/ticket"
import { sanitizeEditorHtml } from "@/components/ui/rich-text-editor"
import { useAuth } from "@/lib/auth-client"
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
import { Input } from "@/components/ui/input"
import { Button } from "@/components/ui/button"
import { CategorySelectFields } from "@/components/tickets/category-select"
import { Dropzone } from "@/components/ui/dropzone"
import { RichTextEditor } from "@/components/ui/rich-text-editor"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
import { normalizeCustomFieldInputs, hasMissingRequiredCustomFields } from "@/lib/ticket-form-helpers"
import { cn } from "@/lib/utils"
import { useLocalTimeZone } from "@/hooks/use-local-time-zone"
import type { TicketFormDefinition } from "@/lib/ticket-form-types"
import { Calendar } from "@/components/ui/calendar"
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"
import { Calendar as CalendarIcon } from "lucide-react"

const DEFAULT_PRIORITY: TicketPriority = "MEDIUM"

function toHtml(text: string) {
  const escaped = text
    .replace(/&/g, "&amp;")
    .replace(/</g, "&lt;")
    .replace(/>/g, "&gt;")
    .replace(/"/g, "&quot;")
    .replace(/'/g, "&#039;")
  return `<p>${escaped.replace(/\n/g, "<br />")}</p>`
}

export function PortalTicketForm() {
  const router = useRouter()
  const { convexUserId, session, machineContext, machineContextError, machineContextLoading } = useAuth()
  const createTicket = useMutation(api.tickets.create)
  const addComment = useMutation(api.tickets.addComment)
  const ensureTicketFormDefaults = useMutation(api.tickets.ensureTicketFormDefaults)

  const tenantId = session?.user.tenantId ?? DEFAULT_TENANT_ID
  const viewerId = (convexUserId ?? machineContext?.assignedUserId ?? null) as Id<"users"> | null

  const formsRemote = useQuery(
    api.tickets.listTicketForms,
    viewerId ? { tenantId, viewerId } : "skip"
  ) as TicketFormDefinition[] | undefined

  const forms = useMemo<TicketFormDefinition[]>(() => {
    const fallback: TicketFormDefinition = {
      key: "default",
      label: "Chamado",
      description: "Formulário básico para solicitações gerais.",
      fields: [],
    }
    if (!formsRemote || formsRemote.length === 0) {
      return [fallback]
    }
    const hasDefault = formsRemote.some((form) => form.key === fallback.key)
    if (hasDefault) {
      return formsRemote
    }
    return [fallback, ...formsRemote]
  }, [formsRemote])

  const [selectedFormKey, setSelectedFormKey] = useState<string>("default")
  const [customFieldValues, setCustomFieldValues] = useState<Record<string, unknown>>({})
  const [openCalendarField, setOpenCalendarField] = useState<string | null>(null)
  const calendarTimeZone = useLocalTimeZone()
  const hasEnsuredFormsRef = useRef(false)

  useEffect(() => {
    if (!viewerId || hasEnsuredFormsRef.current) return
    hasEnsuredFormsRef.current = true
    ensureTicketFormDefaults({
      tenantId,
      actorId: viewerId,
    }).catch((error) => {
      console.error("Falha ao preparar formulários personalizados", error)
      hasEnsuredFormsRef.current = false
    })
  }, [viewerId, tenantId, ensureTicketFormDefaults])

  useEffect(() => {
    if (!forms.length) return
    if (!forms.find((form) => form.key === selectedFormKey)) {
      setSelectedFormKey(forms[0].key)
      setCustomFieldValues({})
    }
  }, [forms, selectedFormKey])

  const selectedForm = useMemo(
    () => forms.find((form) => form.key === selectedFormKey) ?? forms[0],
    [forms, selectedFormKey]
  )

  const customFieldsInvalid = useMemo(
    () =>
      selectedForm?.fields?.length
        ? hasMissingRequiredCustomFields(selectedForm.fields, customFieldValues)
        : false,
    [selectedForm, customFieldValues]
  )

  const handleFormSelection = (value: string) => {
    setSelectedFormKey(value)
    setCustomFieldValues({})
  }

  const handleCustomFieldChange = (fieldId: string, value: unknown) => {
    setCustomFieldValues((prev) => ({
      ...prev,
      [fieldId]: value,
    }))
  }

  const [subject, setSubject] = useState("")
  const [description, setDescription] = useState("")
  const [categoryId, setCategoryId] = useState<string | null>(null)
  const [subcategoryId, setSubcategoryId] = useState<string | null>(null)
  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 allowTicketMentions = true
  const [isSubmitting, setIsSubmitting] = useState(false)
  const machineInactive = machineContext?.isActive === false
  const isFormValid = useMemo(() => {
    if (!subject.trim() || !description.trim() || !categoryId || !subcategoryId || machineInactive) {
      return false
    }
    if (customFieldsInvalid) {
      return false
    }
    return true
  }, [subject, description, categoryId, subcategoryId, machineInactive, customFieldsInvalid])
  const isViewerReady = Boolean(viewerId)
  const viewerErrorMessage = useMemo(() => {
    if (!machineContextError) return null
    const suffix = machineContextError.status ? ` (status ${machineContextError.status})` : ""
    return `${machineContextError.message}${suffix}`
  }, [machineContextError])

  async function handleSubmit(event: React.FormEvent) {
    event.preventDefault()
    if (isSubmitting || !isFormValid) return
    if (machineInactive) {
      toast.error("Esta dispositivo está desativada no momento. Reative-a para abrir novos chamados.", { id: "portal-new-ticket" })
      return
    }
    if (!viewerId) {
      const detail = viewerErrorMessage ? ` Detalhes: ${viewerErrorMessage}` : ""
      toast.error(
        `Não foi possível identificar o colaborador vinculado a esta dispositivo. Tente abrir novamente o portal ou contate o suporte.${detail}`,
        { id: "portal-new-ticket" }
      )
      return
    }

    const trimmedSubject = subject.trim()
    const sanitizedDescription = sanitizeEditorHtml(description || "")
    const plainDescription = sanitizedDescription.replace(/<[^>]*>/g, "").trim()
    if (plainDescription.length === 0) {
      toast.error("Descreva o que aconteceu para que possamos ajudar melhor.", { id: "portal-new-ticket" })
      return
    }

    let customFieldsPayload: Array<{ fieldId: Id<"ticketFields">; value: unknown }> = []
    if (selectedForm?.fields?.length) {
      const normalized = normalizeCustomFieldInputs(selectedForm.fields, customFieldValues)
      if (!normalized.ok) {
        toast.error(normalized.message, { id: "portal-new-ticket" })
        return
      }
      customFieldsPayload = normalized.payload
    }

    setIsSubmitting(true)
    toast.loading("Abrindo chamado...", { id: "portal-new-ticket" })
    try {
      const id = await createTicket({
        actorId: viewerId,
        tenantId,
        subject: trimmedSubject,
      priority: DEFAULT_PRIORITY,
      channel: "MANUAL",
      queueId: undefined,
      requesterId: viewerId,
      categoryId: categoryId as Id<"ticketCategories">,
      subcategoryId: subcategoryId as Id<"ticketSubcategories">,
      machineId: machineContext?.machineId ? (machineContext.machineId as Id<"machines">) : undefined,
      formTemplate: selectedFormKey !== "default" ? selectedFormKey : undefined,
      customFields: customFieldsPayload.length > 0 ? customFieldsPayload : undefined,
    })

      if (plainDescription.length > 0) {
        const MAX_COMMENT_CHARS = 20000
        if (plainDescription.length > MAX_COMMENT_CHARS) {
          toast.error(`Descrição muito longa (máx. ${MAX_COMMENT_CHARS} caracteres)`, { id: "portal-new-ticket" })
          setIsSubmitting(false)
          return
        }
        const htmlBody = sanitizedDescription || toHtml(trimmedSubject)

        const typedAttachments = attachments.map((file) => ({
          storageId: file.storageId as Id<"_storage">,
          name: file.name,
          size: file.size,
          type: file.type,
        }))
        await addComment({
          ticketId: id as Id<"tickets">,
          authorId: viewerId,
          visibility: "PUBLIC",
          body: htmlBody,
          attachments: typedAttachments,
        })
      }

      toast.success("Chamado criado com sucesso!", { id: "portal-new-ticket" })
      setAttachments([])
      setCustomFieldValues({})
      setSelectedFormKey("default")
      router.replace(`/portal/tickets/${id}`)
    } catch (error) {
      console.error(error)
      toast.error("Não foi possível abrir o chamado.", { id: "portal-new-ticket" })
    } finally {
      setIsSubmitting(false)
    }
  }

  return (
    <Card className="rounded-2xl border border-slate-200 bg-white shadow-sm">
      <CardHeader className="px-5 py-5">
        <CardTitle className="text-xl font-semibold text-neutral-900">Abrir novo chamado</CardTitle>
      </CardHeader>
      <CardContent className="space-y-6 px-5 pb-6">
        {machineInactive ? (
          <div className="rounded-xl border border-amber-200 bg-amber-50 px-4 py-3 text-sm text-amber-700">
            Esta dispositivo foi desativada pelos administradores e não pode abrir novos chamados até ser reativada.
          </div>
        ) : null}
        {!isViewerReady ? (
          <div className="rounded-xl border border-amber-200 bg-amber-50 px-4 py-3 text-sm text-amber-700">
            Vincule esta dispositivo a um colaborador na aplicação desktop para enviar chamados em nome dele.
            {machineContextLoading ? (
              <p className="mt-2 text-xs text-amber-600">Carregando informa��es da m�quina...</p>
            ) : null}
            {viewerErrorMessage ? (
              <p className="mt-2 text-xs text-amber-600">
                Detalhes do erro: {viewerErrorMessage}
              </p>
            ) : null}
          </div>
        ) : null}
        <form onSubmit={handleSubmit} className="space-y-6">
          {forms.length > 1 ? (
            <div className="space-y-2 rounded-xl border border-slate-200 bg-slate-50 px-4 py-4">
              <p className="text-sm font-semibold text-neutral-800">Tipo de solicitação</p>
              <Select value={selectedFormKey} onValueChange={handleFormSelection} disabled={isSubmitting || machineInactive}>
                <SelectTrigger className="h-9 rounded-lg border border-slate-300 bg-white px-3 text-left text-sm font-medium text-neutral-800 shadow-sm focus:ring-0">
                  <SelectValue placeholder="Selecione uma opção" />
                </SelectTrigger>
                <SelectContent className="rounded-xl border border-slate-200 bg-white text-neutral-800 shadow-md">
                  {forms.map((formOption) => (
                    <SelectItem key={formOption.key} value={formOption.key} className="text-sm">
                      {formOption.label}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
              {selectedForm?.description ? (
                <p className="text-xs text-neutral-500">{selectedForm.description}</p>
              ) : null}
            </div>
          ) : null}

          <div className="space-y-3">
            <div className="space-y-1">
              <label htmlFor="subject" className="flex items-center gap-1 text-sm font-medium text-neutral-800">
                Assunto <span className="text-red-500">*</span>
              </label>
              <Input
                id="subject"
                value={subject}
                onChange={(event) => setSubject(event.target.value)}
                placeholder="Ex.: Problema de acesso ao sistema"
                disabled={machineInactive || isSubmitting}
                required
              />
            </div>
            <div className="space-y-1">
              <label htmlFor="description" className="flex items-center gap-1 text-sm font-medium text-neutral-800">
                Detalhes <span className="text-red-500">*</span>
              </label>
              <RichTextEditor
                value={description}
                onChange={(html) => setDescription(html)}
                placeholder="Compartilhe passos para reproduzir, mensagens de erro ou informações adicionais."
                className="rounded-2xl border border-slate-200 shadow-sm focus-within:border-neutral-900 focus-within:ring-neutral-900/20"
                disabled={machineInactive || isSubmitting}
                ticketMention={{ enabled: allowTicketMentions }}
              />
            </div>
          </div>

          <div className="space-y-4">
            <CategorySelectFields
              tenantId={tenantId}
              categoryId={categoryId}
              subcategoryId={subcategoryId}
              onCategoryChange={setCategoryId}
              onSubcategoryChange={setSubcategoryId}
              layout="stacked"
              categoryLabel="Categoria *"
              subcategoryLabel="Subcategoria *"
              secondaryEmptyLabel="Selecione uma categoria"
            />
            {selectedForm.fields.length > 0 ? (
              <div className="grid gap-3 rounded-xl border border-slate-200 bg-white px-4 py-4 sm:grid-cols-2">
                <p className="text-sm font-semibold text-neutral-800 sm:col-span-2">Informações adicionais</p>
                {selectedForm.fields.map((field) => {
                  const value = customFieldValues[field.id]
                  const fieldId = `portal-custom-field-${field.id}`
                  const isRequiredStar = field.required && field.key !== "colaborador_patrimonio"
                  const labelSuffix = isRequiredStar ? <span className="text-red-500">*</span> : null
                  const helpText = field.description ? (
                    <p className="text-xs text-neutral-500">{field.description}</p>
                  ) : null
                  const spanClass =
                    field.type === "boolean" || field.key.includes("observacao") || field.key.includes("permissao")
                      ? "sm:col-span-2"
                      : ""

                  if (field.type === "boolean") {
                    return (
                      <label
                        key={field.id}
                        htmlFor={fieldId}
                        className={cn(
                          "flex items-center gap-3 rounded-lg border border-slate-200 bg-slate-50 px-3 py-2 text-sm text-neutral-800",
                          spanClass || "sm:col-span-2"
                        )}
                      >
                        <input
                          id={fieldId}
                          type="checkbox"
                          className="size-4 rounded border border-slate-300 text-[#00d6eb] focus-visible:ring-[#00d6eb]/40"
                          checked={Boolean(value)}
                          onChange={(event) => handleCustomFieldChange(field.id, event.target.checked)}
                          disabled={isSubmitting || machineInactive}
                        />
                        <span>
                          {field.label} {labelSuffix}
                        </span>
                      </label>
                    )
                  }

                  if (field.type === "select") {
                    return (
                      <div key={field.id} className={cn("space-y-1", spanClass)}>
                        <span className="flex items-center gap-1 text-sm font-medium text-neutral-800">
                          {field.label} {labelSuffix}
                        </span>
                        <Select
                          value={typeof value === "string" ? value : ""}
                          onValueChange={(selected) => handleCustomFieldChange(field.id, selected)}
                          disabled={isSubmitting || machineInactive}
                        >
                          <SelectTrigger className="h-9 rounded-lg border border-slate-300 bg-white px-3 text-left text-sm font-medium text-neutral-800 shadow-sm focus:ring-0">
                            <SelectValue placeholder="Selecione" />
                          </SelectTrigger>
                          <SelectContent className="rounded-xl border border-slate-200 bg-white text-neutral-800 shadow-md">
                            {field.options.map((option) => (
                              <SelectItem key={option.value} value={option.value} className="text-sm">
                                {option.label}
                              </SelectItem>
                            ))}
                          </SelectContent>
                        </Select>
                        {helpText}
                      </div>
                    )
                  }

                  if (field.type === "number") {
                    return (
                      <div key={field.id} className={cn("space-y-1", spanClass)}>
                        <label htmlFor={fieldId} className="flex items-center gap-1 text-sm font-medium text-neutral-800">
                          {field.label} {labelSuffix}
                        </label>
                        <Input
                          id={fieldId}
                          type="number"
                          inputMode="decimal"
                          value={typeof value === "number" || typeof value === "string" ? String(value) : ""}
                          onChange={(event) => handleCustomFieldChange(field.id, event.target.value)}
                          disabled={isSubmitting || machineInactive}
                        />
                        {helpText}
                      </div>
                    )
                  }

                  if (field.type === "date") {
                    const parsedDate =
                      typeof value === "string" && value ? parseISO(value) : undefined
                    const isValidDate = Boolean(parsedDate && !Number.isNaN(parsedDate.getTime()))
                    return (
                      <div key={field.id} className={cn("space-y-1", spanClass)}>
                        <label htmlFor={fieldId} className="flex items-center gap-1 text-sm font-medium text-neutral-800">
                          {field.label} {labelSuffix}
                        </label>
                        <Popover
                          open={openCalendarField === field.id}
                          onOpenChange={(open) => setOpenCalendarField(open ? field.id : null)}
                        >
                          <PopoverTrigger asChild>
                            <Button
                              type="button"
                              variant="outline"
                              disabled={isSubmitting || machineInactive}
                              className={cn(
                                "w-full justify-between gap-2 text-left font-normal",
                                !isValidDate && "text-muted-foreground"
                              )}
                            >
                              <span>
                                {isValidDate
                                  ? format(parsedDate as Date, "dd/MM/yyyy", { locale: ptBR })
                                  : "Selecionar data"}
                              </span>
                              <CalendarIcon className="size-4 text-muted-foreground" aria-hidden="true" />
                            </Button>
                          </PopoverTrigger>
                          <PopoverContent className="w-auto p-0" align="start">
                            <Calendar
                              mode="single"
                              selected={isValidDate ? (parsedDate as Date) : undefined}
                              onSelect={(selected) => {
                                handleCustomFieldChange(field.id, selected ? format(selected, "yyyy-MM-dd") : "")
                                setOpenCalendarField(null)
                              }}
                              initialFocus
                              captionLayout="dropdown"
                              startMonth={new Date(1900, 0)}
                              endMonth={new Date(new Date().getFullYear() + 5, 11)}
                              locale={ptBR}
                              timeZone={calendarTimeZone}
                            />
                          </PopoverContent>
                        </Popover>
                        {helpText}
                      </div>
                    )
                  }

                  const shouldUseTextarea = field.key.includes("observacao") || field.key.includes("permissao")

                  return (
                    <div key={field.id} className={cn("space-y-1", spanClass)}>
                      <label htmlFor={fieldId} className="flex items-center gap-1 text-sm font-medium text-neutral-800">
                        {field.label} {labelSuffix}
                      </label>
                      {shouldUseTextarea ? (
                        <textarea
                          id={fieldId}
                          className="min-h-[90px] rounded-lg border border-slate-300 px-3 py-2 text-sm text-neutral-800 shadow-sm focus:border-neutral-900 focus:outline-none focus:ring-2 focus:ring-neutral-900/10 disabled:cursor-not-allowed"
                          value={typeof value === "string" ? value : ""}
                          onChange={(event) => handleCustomFieldChange(field.id, event.target.value)}
                          disabled={isSubmitting || machineInactive}
                        />
                      ) : (
                        <Input
                          id={fieldId}
                          value={typeof value === "string" ? value : ""}
                          onChange={(event) => handleCustomFieldChange(field.id, event.target.value)}
                          disabled={isSubmitting || machineInactive}
                        />
                      )}
                      {helpText}
                    </div>
                  )
                })}
              </div>
            ) : null}
            {customFieldsInvalid ? (
              <p className="text-xs font-semibold text-red-500">
                Preencha todos os campos obrigatórios antes de registrar o chamado.
              </p>
            ) : null}
            <div className="space-y-1">
              <span className="text-sm font-medium text-neutral-800">Anexos (opcional)</span>
              <Dropzone
                onUploaded={(files) => setAttachments((prev) => [...prev, ...files])}
                className="rounded-xl border border-dashed border-slate-300 bg-slate-50 px-3 py-4 text-sm text-neutral-600 shadow-inner"
                currentFileCount={attachments.length}
                currentTotalBytes={attachmentsTotalBytes}
                disabled={!isViewerReady || machineInactive || isSubmitting}
              />
              <p className="text-xs text-neutral-500">
                Formatos comuns de imagens e documentos são aceitos.
              </p>
            </div>
          </div>

          <div className="flex justify-end gap-3">
            <Button
              type="button"
              variant="outline"
              onClick={() => router.push("/portal/tickets")}
              className="rounded-full border-slate-300 px-6 text-sm font-semibold text-neutral-700 hover:bg-neutral-100"
              disabled={isSubmitting}
            >
              Cancelar
            </Button>
            <Button
              type="submit"
              disabled={!isFormValid || isSubmitting || machineInactive}
              className="rounded-full bg-neutral-900 px-6 text-sm font-semibold text-white hover:bg-neutral-900/90"
            >
              Registrar chamado
            </Button>
          </div>
        </form>
      </CardContent>
    </Card>
  )
}
