"use client"

import { useCallback, useEffect, useMemo, useState } from "react"
import { useMutation, useQuery } from "convex/react"
import { api } from "@/convex/_generated/api"
import type { Id } from "@/convex/_generated/dataModel"
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog"
import { Button } from "@/components/ui/button"
import { Spinner } from "@/components/ui/spinner"
import { RichTextEditor, sanitizeEditorHtml, stripLeadingEmptyParagraphs } from "@/components/ui/rich-text-editor"
import { toast } from "sonner"
import { Checkbox } from "@/components/ui/checkbox"
import { Label } from "@/components/ui/label"
import { Input } from "@/components/ui/input"
import { Textarea } from "@/components/ui/textarea"

type ClosingTemplate = { id: string; title: string; body: string }

const DEFAULT_PHONE_NUMBER = "(11) 4173-5368"
const DEFAULT_COMPANY_NAME = "Rever Tecnologia"

const sanitizeTemplate = (html: string) => stripLeadingEmptyParagraphs(sanitizeEditorHtml(html.trim()))

export type AdjustWorkSummaryResult = {
  ticketId: Id<"tickets">
  totalWorkedMs: number
  internalWorkedMs: number
  externalWorkedMs: number
  serverNow?: number
  perAgentTotals?: Array<{
    agentId: string
    agentName: string | null
    agentEmail: string | null
    avatarUrl: string | null
    totalWorkedMs: number
    internalWorkedMs: number
    externalWorkedMs: number
  }>
}

const DEFAULT_CLOSING_TEMPLATES: ClosingTemplate[] = [
  {
    id: "default-standard",
    title: "Encerramento padrão",
    body: sanitizeTemplate(`
      <p>Olá {{cliente}},</p>
      <p>A equipe da ${DEFAULT_COMPANY_NAME} agradece o contato. Este ticket está sendo encerrado.</p>
      <p>Se surgirem novas questões, você pode reabrir o ticket em até 7 dias ou nos contatar pelo número <strong>${DEFAULT_PHONE_NUMBER}</strong>. Obrigado.</p>
      <p>{{agente}} · ${DEFAULT_COMPANY_NAME}</p>
    `),
  },
  {
    id: "default-no-contact",
    title: "Tentativa de contato sem sucesso",
    body: sanitizeTemplate(`
      <p>Prezado(a) {{cliente}},</p>
      <p>Realizamos uma tentativa de contato, mas não obtivemos sucesso.</p>
      <p>Por favor, retorne assim que possível para seguirmos com as verificações necessárias.</p>
      <p>Este ticket será encerrado após 3 tentativas realizadas sem sucesso.</p>
      <p>Telefone para contato: <strong>${DEFAULT_PHONE_NUMBER}</strong>.</p>
      <p>{{agente}} · ${DEFAULT_COMPANY_NAME}</p>
    `),
  },
  {
    id: "default-closed-after-attempts",
    title: "Encerramento após 3 tentativas",
    body: sanitizeTemplate(`
      <p>Prezado(a) {{cliente}},</p>
      <p>Esse ticket está sendo encerrado pois realizamos 3 tentativas sem retorno.</p>
      <p>Você pode reabrir este ticket em até 7 dias ou entrar em contato pelo telefone <strong>${DEFAULT_PHONE_NUMBER}</strong> quando preferir.</p>
      <p>{{agente}} · ${DEFAULT_COMPANY_NAME}</p>
    `),
  },
]

function applyTemplatePlaceholders(html: string, customerName?: string | null, agentName?: string | null) {
  const normalizedCustomer = customerName?.trim()
  const customerFallback = normalizedCustomer && normalizedCustomer.length > 0 ? normalizedCustomer : "cliente"
  const normalizedAgent = agentName?.trim()
  const agentFallback = normalizedAgent && normalizedAgent.length > 0 ? normalizedAgent : "Equipe Rever"
  return html
    .replace(/{{\s*(cliente|customer|customername|nome|nomecliente)\s*}}/gi, customerFallback)
    .replace(/{{\s*(agente|agent|atendente|responsavel|usu[aá]rio|usuario)\s*}}/gi, agentFallback)
    .replace(/{{\s*(empresa|company|companhia)\s*}}/gi, DEFAULT_COMPANY_NAME)
}

const splitDuration = (ms: number) => {
  const safeMs = Number.isFinite(ms) && ms > 0 ? ms : 0
  const totalMinutes = Math.round(safeMs / 60000)
  const hours = Math.floor(totalMinutes / 60)
  const minutes = totalMinutes % 60
  return { hours, minutes }
}

const formatDurationLabel = (ms: number) => {
  const { hours, minutes } = splitDuration(ms)
  if (hours > 0 && minutes > 0) return `${hours}h ${minutes}min`
  if (hours > 0) return `${hours}h`
  return `${minutes}min`
}

export function CloseTicketDialog({
  open,
  onOpenChange,
  ticketId,
  tenantId,
  actorId,
  requesterName,
  agentName,
  onSuccess,
  workSummary,
  onWorkSummaryAdjusted,
  canAdjustTime = false,
}: {
  open: boolean
  onOpenChange: (open: boolean) => void
  ticketId: string
  tenantId: string
  actorId: Id<"users"> | null
  requesterName?: string | null
  agentName?: string | null
  onSuccess: () => void
  workSummary?: {
    totalWorkedMs: number
    internalWorkedMs: number
    externalWorkedMs: number
  } | null
  onWorkSummaryAdjusted?: (result: AdjustWorkSummaryResult) => void
  canAdjustTime?: boolean
}) {
  const updateStatus = useMutation(api.tickets.updateStatus)
  const addComment = useMutation(api.tickets.addComment)
  const adjustWorkSummary = useMutation(api.tickets.adjustWorkSummary)

  const closingTemplateArgs =
    actorId && open ? { tenantId, viewerId: actorId, kind: "closing" as const } : undefined
  const closingTemplatesRemote = useQuery(
    actorId && open ? api.commentTemplates.list : undefined,
    closingTemplateArgs
  )
  const closingTemplates = Array.isArray(closingTemplatesRemote)
    ? (closingTemplatesRemote as { id: string; title: string; body: string }[])
    : undefined

  const templatesLoading = Boolean(actorId && open && !Array.isArray(closingTemplatesRemote))
  const templates = useMemo<ClosingTemplate[]>(() => {
    if (closingTemplates && closingTemplates.length > 0) {
      return closingTemplates.map((t) => ({ id: t.id, title: t.title, body: t.body }))
    }
    return DEFAULT_CLOSING_TEMPLATES
  }, [closingTemplates])

  const [selectedTemplateId, setSelectedTemplateId] = useState<string | null>(null)
  const [message, setMessage] = useState<string>("")
  const [isSubmitting, setIsSubmitting] = useState(false)
  const [shouldAdjustTime, setShouldAdjustTime] = useState<boolean>(false)
  const [internalHours, setInternalHours] = useState<string>("0")
  const [internalMinutes, setInternalMinutes] = useState<string>("0")
  const [externalHours, setExternalHours] = useState<string>("0")
  const [externalMinutes, setExternalMinutes] = useState<string>("0")
  const [adjustReason, setAdjustReason] = useState<string>("")
  const enableAdjustment = Boolean(canAdjustTime && workSummary)

  const hydrateTemplateBody = useCallback((templateHtml: string) => {
    const withPlaceholders = applyTemplatePlaceholders(templateHtml, requesterName, agentName)
    return stripLeadingEmptyParagraphs(sanitizeEditorHtml(withPlaceholders))
  }, [requesterName, agentName])

  useEffect(() => {
    if (open) return
    setSelectedTemplateId(null)
    setMessage("")
    setIsSubmitting(false)
    setShouldAdjustTime(false)
    setAdjustReason("")
    setInternalHours("0")
    setInternalMinutes("0")
    setExternalHours("0")
    setExternalMinutes("0")
  }, [open])

  useEffect(() => {
    if (!open) return
    if (templates.length > 0 && !selectedTemplateId && !message) {
      const first = templates[0]
      const hydrated = hydrateTemplateBody(first.body)
      setSelectedTemplateId(first.id)
      setMessage(hydrated)
    }
  }, [open, templates, selectedTemplateId, message, hydrateTemplateBody])

  useEffect(() => {
    if (!open || !enableAdjustment || !shouldAdjustTime) return
    const internal = splitDuration(workSummary?.internalWorkedMs ?? 0)
    const external = splitDuration(workSummary?.externalWorkedMs ?? 0)
    setInternalHours(internal.hours.toString())
    setInternalMinutes(internal.minutes.toString())
    setExternalHours(external.hours.toString())
    setExternalMinutes(external.minutes.toString())
  }, [
    open,
    enableAdjustment,
    shouldAdjustTime,
    workSummary?.internalWorkedMs,
    workSummary?.externalWorkedMs,
  ])

  useEffect(() => {
    if (!shouldAdjustTime) {
      setAdjustReason("")
    }
  }, [shouldAdjustTime])

  const handleTemplateSelect = (template: ClosingTemplate) => {
    setSelectedTemplateId(template.id)
    setMessage(hydrateTemplateBody(template.body))
  }

  const handleSubmit = async () => {
    if (!actorId) {
      toast.error("É necessário estar autenticado para encerrar o ticket.")
      return
    }

    const applyAdjustment = enableAdjustment && shouldAdjustTime
    let targetInternalMs = 0
    let targetExternalMs = 0
    let trimmedReason = ""

    if (applyAdjustment) {
      const parsePart = (value: string, label: string) => {
        const trimmed = value.trim()
        if (trimmed.length === 0) return 0
        if (!/^\d+$/u.test(trimmed)) {
          toast.error(`Informe um número válido para ${label}.`)
          return null
        }
        return Number.parseInt(trimmed, 10)
      }

      const internalHoursValue = parsePart(internalHours, "horas internas")
      if (internalHoursValue === null) return
      const internalMinutesValue = parsePart(internalMinutes, "minutos internos")
      if (internalMinutesValue === null) return
      if (internalMinutesValue >= 60) {
        toast.error("Os minutos internos devem estar entre 0 e 59.")
        return
      }

      const externalHoursValue = parsePart(externalHours, "horas externas")
      if (externalHoursValue === null) return
      const externalMinutesValue = parsePart(externalMinutes, "minutos externos")
      if (externalMinutesValue === null) return
      if (externalMinutesValue >= 60) {
        toast.error("Os minutos externos devem estar entre 0 e 59.")
        return
      }

      targetInternalMs = (internalHoursValue * 60 + internalMinutesValue) * 60000
      targetExternalMs = (externalHoursValue * 60 + externalMinutesValue) * 60000
      trimmedReason = adjustReason.trim()
      if (trimmedReason.length < 5) {
        toast.error("Descreva o motivo do ajuste (mínimo de 5 caracteres).")
        return
      }
    }

    toast.dismiss("close-ticket")
    setIsSubmitting(true)
    toast.loading(applyAdjustment ? "Ajustando tempo e encerrando ticket..." : "Encerrando ticket...", { id: "close-ticket" })
    try {
      if (applyAdjustment) {
        const result = (await adjustWorkSummary({
          ticketId: ticketId as unknown as Id<"tickets">,
          actorId,
          internalWorkedMs: targetInternalMs,
          externalWorkedMs: targetExternalMs,
          reason: trimmedReason,
        })) as AdjustWorkSummaryResult
        onWorkSummaryAdjusted?.(result)
      }

      await updateStatus({ ticketId: ticketId as unknown as Id<"tickets">, status: "RESOLVED", actorId })
      const withPlaceholders = applyTemplatePlaceholders(message, requesterName, agentName)
      const sanitized = stripLeadingEmptyParagraphs(sanitizeEditorHtml(withPlaceholders))
      const hasContent = sanitized.replace(/<[^>]*>/g, "").trim().length > 0
      if (hasContent) {
        await addComment({
          ticketId: ticketId as unknown as Id<"tickets">,
          authorId: actorId,
          visibility: "PUBLIC",
          body: sanitized,
          attachments: [],
        })
      }
      toast.success("Ticket encerrado com sucesso!", { id: "close-ticket" })
      onOpenChange(false)
      onSuccess()
    } catch (error) {
      console.error(error)
      toast.error(applyAdjustment ? "Não foi possível ajustar o tempo ou encerrar o ticket." : "Não foi possível encerrar o ticket.", {
        id: "close-ticket",
      })
    } finally {
      setIsSubmitting(false)
    }
  }

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="max-w-2xl max-h-[90vh] overflow-y-auto">
        <DialogHeader>
          <DialogTitle>Encerrar ticket</DialogTitle>
          <DialogDescription>
            Confirme a mensagem de encerramento que será enviada ao cliente. Você pode personalizar o texto antes de concluir.
          </DialogDescription>
        </DialogHeader>
        <div className="space-y-4">
          <div className="space-y-2">
            <p className="text-sm font-medium text-neutral-800">Modelos rápidos</p>
            {templatesLoading ? (
              <div className="flex items-center gap-2 text-sm text-neutral-600">
                <Spinner className="size-4" /> Carregando templates...
              </div>
            ) : (
              <div className="flex flex-wrap gap-2">
                {templates.map((template) => (
                  <Button
                    key={template.id}
                    type="button"
                    variant={selectedTemplateId === template.id ? "default" : "outline"}
                    size="sm"
                    onClick={() => handleTemplateSelect(template)}
                  >
                    {template.title}
                  </Button>
                ))}
              </div>
            )}
            <p className="text-xs text-neutral-500">
              Use <code className="rounded bg-slate-100 px-1 py-0.5">{"{{cliente}}"}</code> dentro do template para inserir automaticamente o nome do solicitante.
            </p>
          </div>
          <div className="space-y-2">
            <p className="text-sm font-medium text-neutral-800">Mensagem de encerramento</p>
            <RichTextEditor
              value={message}
              onChange={setMessage}
              minHeight={220}
              placeholder="Escreva uma mensagem final para o cliente..."
            />
            <p className="text-xs text-neutral-500">Você pode editar o conteúdo antes de enviar. Deixe em branco para encerrar sem comentário adicional.</p>
          </div>
        </div>
        {enableAdjustment ? (
          <div className="rounded-xl border border-slate-200 bg-slate-50 px-4 py-4">
            <div className="flex flex-wrap items-center justify-between gap-3">
              <div>
                <p className="text-sm font-semibold text-neutral-800">Ajustar tempo antes de encerrar</p>
                <p className="text-xs text-neutral-500">
                  Atualize o tempo registrado e informe um motivo para o ajuste. O comentário fica visível apenas para a equipe.
                </p>
              </div>
              <div className="flex items-center gap-2">
                <Checkbox
                  id="toggle-time-adjustment"
                  checked={shouldAdjustTime}
                  onCheckedChange={(checked) => setShouldAdjustTime(Boolean(checked))}
                  disabled={isSubmitting}
                />
                <Label htmlFor="toggle-time-adjustment" className="text-sm font-medium text-neutral-800">
                  Incluir ajuste
                </Label>
              </div>
            </div>
            {shouldAdjustTime ? (
              <div className="mt-4 space-y-4">
                <div className="grid gap-4 sm:grid-cols-2">
                  <div className="space-y-2">
                    <p className="text-xs font-semibold uppercase tracking-wide text-neutral-500">Tempo interno</p>
                    <div className="grid grid-cols-2 gap-2">
                      <div className="space-y-1">
                        <Label htmlFor="adjust-internal-hours" className="text-xs text-neutral-600">
                          Horas
                        </Label>
                        <Input
                          id="adjust-internal-hours"
                          type="number"
                          min={0}
                          step={1}
                          inputMode="numeric"
                          value={internalHours}
                          onChange={(event) => setInternalHours(event.target.value)}
                          disabled={isSubmitting}
                        />
                      </div>
                      <div className="space-y-1">
                        <Label htmlFor="adjust-internal-minutes" className="text-xs text-neutral-600">
                          Minutos
                        </Label>
                        <Input
                          id="adjust-internal-minutes"
                          type="number"
                          min={0}
                          max={59}
                          step={1}
                          inputMode="numeric"
                          value={internalMinutes}
                          onChange={(event) => setInternalMinutes(event.target.value)}
                          disabled={isSubmitting}
                        />
                      </div>
                    </div>
                    <p className="text-xs text-neutral-500">
                      Atual: {formatDurationLabel(workSummary?.internalWorkedMs ?? 0)}
                    </p>
                  </div>
                  <div className="space-y-2">
                    <p className="text-xs font-semibold uppercase tracking-wide text-neutral-500">Tempo externo</p>
                    <div className="grid grid-cols-2 gap-2">
                      <div className="space-y-1">
                        <Label htmlFor="adjust-external-hours" className="text-xs text-neutral-600">
                          Horas
                        </Label>
                        <Input
                          id="adjust-external-hours"
                          type="number"
                          min={0}
                          step={1}
                          inputMode="numeric"
                          value={externalHours}
                          onChange={(event) => setExternalHours(event.target.value)}
                          disabled={isSubmitting}
                        />
                      </div>
                      <div className="space-y-1">
                        <Label htmlFor="adjust-external-minutes" className="text-xs text-neutral-600">
                          Minutos
                        </Label>
                        <Input
                          id="adjust-external-minutes"
                          type="number"
                          min={0}
                          max={59}
                          step={1}
                          inputMode="numeric"
                          value={externalMinutes}
                          onChange={(event) => setExternalMinutes(event.target.value)}
                          disabled={isSubmitting}
                        />
                      </div>
                    </div>
                    <p className="text-xs text-neutral-500">
                      Atual: {formatDurationLabel(workSummary?.externalWorkedMs ?? 0)}
                    </p>
                  </div>
                </div>
                <div className="space-y-1.5">
                  <Label htmlFor="adjust-reason" className="text-xs text-neutral-600">
                    Motivo do ajuste
                  </Label>
                  <Textarea
                    id="adjust-reason"
                    value={adjustReason}
                    onChange={(event) => setAdjustReason(event.target.value)}
                    placeholder="Descreva por que o tempo precisa ser ajustado..."
                    rows={3}
                    disabled={isSubmitting}
                  />
                  <p className="text-xs text-neutral-500">
                    Registre o motivo para fins de auditoria interna. Informe valores em minutos quando menor que 1 hora.
                  </p>
                </div>
              </div>
            ) : null}
          </div>
        ) : null}
        <DialogFooter className="flex flex-wrap justify-between gap-3 pt-4">
          <div className="text-xs text-neutral-500">
            O comentário será público e ficará registrado no histórico do ticket.
          </div>
          <div className="flex items-center gap-2">
            <Button
              type="button"
              variant="ghost"
              onClick={() => onOpenChange(false)}
              disabled={isSubmitting}
            >
              Cancelar
            </Button>
            <Button
              type="button"
              variant="outline"
              onClick={() => {
                setMessage("")
                setSelectedTemplateId(null)
              }}
              disabled={isSubmitting}
            >
              Limpar mensagem
            </Button>
            <Button type="button" onClick={handleSubmit} disabled={isSubmitting || !actorId}>
              {isSubmitting ? <Spinner className="size-4 text-white" /> : "Encerrar ticket"}
            </Button>
          </div>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  )
}
