import Link from "next/link"
import { useEffect, useMemo, useState, type ReactNode, type ComponentType } from "react"
import { format } from "date-fns"
import { ptBR } from "date-fns/locale"
import {
  IconCalendar,
  IconClockHour4,
  IconFolders,
  IconNote,
  IconPaperclip,
  IconSquareCheck,
  IconStar,
  IconUserCircle,
  IconLink,
} from "@tabler/icons-react"

import type { TicketWithDetails } from "@/lib/schemas/ticket"
import { Card, CardContent } from "@/components/ui/card"
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
import { Separator } from "@/components/ui/separator"
import {
  Pagination,
  PaginationContent,
  PaginationEllipsis,
  PaginationItem,
  PaginationLink,
  PaginationNext,
  PaginationPrevious,
} from "@/components/ui/pagination"
import { TICKET_TIMELINE_LABELS } from "@/lib/ticket-timeline-labels"
import { formatTicketCustomFieldValue } from "@/lib/ticket-custom-fields"

const timelineIcons: Record<string, ComponentType<{ className?: string }>> = {
  CREATED: IconUserCircle,
  STATUS_CHANGED: IconSquareCheck,
  ASSIGNEE_CHANGED: IconUserCircle,
  COMMENT_ADDED: IconNote,
  COMMENT_EDITED: IconNote,
  WORK_STARTED: IconClockHour4,
  WORK_PAUSED: IconClockHour4,
  SUBJECT_CHANGED: IconNote,
  SUMMARY_CHANGED: IconNote,
  QUEUE_CHANGED: IconSquareCheck,
  PRIORITY_CHANGED: IconSquareCheck,
  ATTACHMENT_REMOVED: IconPaperclip,
  CATEGORY_CHANGED: IconFolders,
  REQUESTER_CHANGED: IconUserCircle,
  MANAGER_NOTIFIED: IconUserCircle,
  VISIT_SCHEDULED: IconCalendar,
  CSAT_RECEIVED: IconStar,
  CSAT_RATED: IconStar,
  TICKET_LINKED: IconLink,
}

const timelineLabels: Record<string, string> = TICKET_TIMELINE_LABELS

interface TicketTimelineProps {
  ticket: TicketWithDetails
}

const ITEMS_PER_PAGE = 10

export function TicketTimeline({ ticket }: TicketTimelineProps) {
  const formatDuration = (durationMs: number) => {
    if (!durationMs || durationMs <= 0) return "0s"
    const totalSeconds = Math.floor(durationMs / 1000)
    const hours = Math.floor(totalSeconds / 3600)
    const minutes = Math.floor((totalSeconds % 3600) / 60)
    const seconds = totalSeconds % 60
    if (hours > 0) {
      return `${hours}h ${minutes.toString().padStart(2, "0")}m`
    }
    if (minutes > 0) {
      return `${minutes}m ${seconds.toString().padStart(2, "0")}s`
    }
    return `${seconds}s`
  }

  const [page, setPage] = useState(1)

  const totalItems = ticket.timeline.length
  const totalPages = Math.max(1, Math.ceil(totalItems / ITEMS_PER_PAGE))
  const currentPage = Math.min(page, totalPages)
  const pageOffset = (currentPage - 1) * ITEMS_PER_PAGE

  const currentEvents = useMemo(
    () => ticket.timeline.slice(pageOffset, pageOffset + ITEMS_PER_PAGE),
    [pageOffset, ticket.timeline]
  )

  const paginationRange = useMemo(() => {
    if (totalPages <= 7) {
      return Array.from({ length: totalPages }, (_, index) => index + 1)
    }
    const range: Array<number | "ellipsis-left" | "ellipsis-right"> = [1]
    const left = Math.max(2, currentPage - 1)
    const right = Math.min(totalPages - 1, currentPage + 1)
    if (left > 2) {
      range.push("ellipsis-left")
    }
    for (let i = left; i <= right; i += 1) {
      range.push(i)
    }
    if (right < totalPages - 1) {
      range.push("ellipsis-right")
    }
    range.push(totalPages)
    return range
  }, [currentPage, totalPages])

  const rangeStart = totalItems === 0 ? 0 : pageOffset + 1
  const rangeEnd = totalItems === 0 ? 0 : Math.min(pageOffset + ITEMS_PER_PAGE, totalItems)

  useEffect(() => {
    setPage(1)
  }, [ticket.id])

  useEffect(() => {
    if (page > totalPages) {
      setPage(totalPages)
    }
  }, [page, totalPages])

  if (totalItems === 0) {
    return (
      <Card className="rounded-2xl border border-slate-200 bg-white shadow-sm">
        <CardContent className="px-4 py-10">
          <p className="text-center text-sm text-neutral-500">
            Nenhum evento registrado neste ticket ainda.
          </p>
        </CardContent>
      </Card>
    )
  }

  return (
    <Card className="rounded-2xl border border-slate-200 bg-white shadow-sm">
      <CardContent className="space-y-6 px-4 pb-6">
        <div className="flex flex-wrap items-center justify-between gap-3 border-b border-slate-200 pb-4">
          <div>
            <h3 className="text-base font-semibold text-neutral-900">Linha do tempo</h3>
            <p className="text-sm text-neutral-500">
              Mostrando {rangeStart}-{rangeEnd} de {totalItems} eventos
            </p>
          </div>
          {totalPages > 1 ? (
            <Pagination>
              <PaginationContent>
                <PaginationItem>
                  <PaginationPrevious
                    disabled={currentPage === 1}
                    onClick={() => setPage((previous) => Math.max(1, previous - 1))}
                  />
                </PaginationItem>
                {paginationRange.map((item, index) => {
                  if (typeof item === "number") {
                    return (
                      <PaginationItem key={`page-${item}`}>
                        <PaginationLink
                          href="#"
                          isActive={item === currentPage}
                          onClick={(event) => {
                            event.preventDefault()
                            setPage(item)
                          }}
                        >
                          {item}
                        </PaginationLink>
                      </PaginationItem>
                    )
                  }
                  return (
                    <PaginationItem key={`ellipsis-${item}-${index}`}>
                      <PaginationEllipsis />
                    </PaginationItem>
                  )
                })}
                <PaginationItem>
                  <PaginationNext
                    disabled={currentPage === totalPages}
                    onClick={() => setPage((previous) => Math.min(totalPages, previous + 1))}
                  />
                </PaginationItem>
              </PaginationContent>
            </Pagination>
          ) : null}
        </div>

        {currentEvents.map((entry, index) => {
          const Icon = timelineIcons[entry.type] ?? IconClockHour4
          const isLastGlobal = pageOffset + index === totalItems - 1
          return (
            <div key={entry.id} className="relative pl-11">
              {!isLastGlobal && (
                <span className="absolute left-[14px] top-6 h-full w-px bg-slate-200" aria-hidden />
              )}
              <span className="absolute left-0 top-0 flex size-8 items-center justify-center rounded-full border border-slate-200 bg-white text-neutral-700 shadow-sm">
                <Icon className="size-4" />
              </span>
              <div className="flex flex-col gap-2">
                <div className="flex flex-wrap items-center gap-x-3 gap-y-1">
                  <span className="text-sm font-semibold text-neutral-900">
                    {timelineLabels[entry.type] ?? entry.type}
                  </span>
                  {entry.payload?.actorName ? (
                    <span className="flex items-center gap-1 text-xs text-neutral-500">
                      <Avatar className="size-5 border border-slate-200">
                        <AvatarImage src={entry.payload?.actorAvatar as string | undefined} alt={String(entry.payload?.actorName ?? "")} />
                        <AvatarFallback>
                          {String(entry.payload?.actorName ?? "").split(" ").slice(0, 2).map((part: string) => part[0]).join("").toUpperCase()}
                        </AvatarFallback>
                      </Avatar>
                      por {String(entry.payload?.actorName ?? "")}
                    </span>
                  ) : null}
                  <span className="text-xs text-neutral-500">
                    {format(entry.createdAt, "dd MMM yyyy HH:mm", { locale: ptBR })}
                  </span>
                </div>
                {(() => {
                  const payload = (entry.payload || {}) as {
                    toLabel?: string
                    to?: string
                    assigneeName?: string
                    assigneeId?: string
                    queueName?: string
                    queueId?: string
                    requesterName?: string
                    authorName?: string
                    authorId?: string
                    actorName?: string
                    actorId?: string
                    from?: string
                    attachmentName?: string
                    sessionDurationMs?: number
                    categoryName?: string
                    subcategoryName?: string
                    pauseReason?: string
                    pauseReasonLabel?: string
                    pauseNote?: string
                    managerName?: string
                    managerUserName?: string
                    manager?: string
                    managerId?: string
                    managerUserId?: string
                    scheduledFor?: number | string
                    scheduledAt?: number | string
                    score?: number
                    rating?: number
                    maxScore?: number
                    max?: number
                  }

                  let message: ReactNode = null
                  if (entry.type === "TICKET_LINKED") {
                    const payloadLink = payload as {
                      linkedTicketId?: string
                      linkedReference?: number | string | null
                      linkedSubject?: string | null
                      kind?: string | null
                    }
                    const linkedTicketId =
                      typeof payloadLink.linkedTicketId === "string" && payloadLink.linkedTicketId.trim().length > 0
                        ? payloadLink.linkedTicketId.trim()
                        : null
                    const referenceValue = payloadLink.linkedReference
                    const referenceLabelRaw =
                      typeof referenceValue === "number"
                        ? referenceValue.toString()
                        : typeof referenceValue === "string"
                          ? referenceValue.trim()
                          : null
                    const referenceLabel = referenceLabelRaw && referenceLabelRaw.length > 0 ? referenceLabelRaw : null
                    const linkContent = referenceLabel ? `#${referenceLabel}` : "Ver ticket"
                    const subject =
                      typeof payloadLink.linkedSubject === "string" && payloadLink.linkedSubject.trim().length > 0
                        ? payloadLink.linkedSubject.trim()
                        : null
                    const kindRaw =
                      typeof payloadLink.kind === "string" && payloadLink.kind.trim().length > 0
                        ? payloadLink.kind.trim()
                        : "related"
                    const labelPrefix =
                      kindRaw === "resolution_parent"
                        ? "Ticket vinculado a este chamado"
                        : kindRaw === "resolved_with"
                          ? "Ticket resolvido com"
                          : "Ticket vinculado"
                    message = (
                      <div className="space-y-1">
                        <span className="block text-sm text-neutral-600">
                          <span className="font-semibold text-neutral-800">{labelPrefix}</span>{" "}
                          {linkedTicketId ? (
                            <Link
                              href={`/tickets/${linkedTicketId}`}
                              className="font-semibold text-primary transition hover:text-primary/80 hover:underline"
                            >
                              {linkContent}
                            </Link>
                          ) : (
                            <span className="font-medium text-neutral-800">{linkContent}</span>
                          )}
                          {subject ? <span className="text-neutral-500"> — {subject}</span> : null}
                        </span>
                      </div>
                    )
                  }
                  if (entry.type === "CUSTOM_FIELDS_UPDATED") {
                    type FieldPayload = {
                      fieldKey?: string
                      label?: string
                      type?: string
                      previousValue?: unknown
                      nextValue?: unknown
                      previousDisplayValue?: string | null
                      nextDisplayValue?: string | null
                      changeType?: string
                    }
                    const payloadFields = Array.isArray((payload as { fields?: unknown }).fields)
                      ? ((payload as { fields?: FieldPayload[] }).fields ?? [])
                      : []
                    const hasValueDetails = payloadFields.some((field) => {
                      if (!field) return false
                      return (
                        Object.prototype.hasOwnProperty.call(field, "previousValue") ||
                        Object.prototype.hasOwnProperty.call(field, "nextValue") ||
                        Object.prototype.hasOwnProperty.call(field, "previousDisplayValue") ||
                        Object.prototype.hasOwnProperty.call(field, "nextDisplayValue")
                      )
                    })
                    if (hasValueDetails && payloadFields.length > 0) {
                      message = (
                        <div className="space-y-1">
                          <span className="block text-sm font-semibold text-neutral-800">
                            Campos personalizados atualizados
                          </span>
                          <ul className="mt-1 space-y-0.5 text-xs text-neutral-600">
                            {payloadFields.map((field, index) => {
                              const label =
                                typeof field?.label === "string" && field.label.trim().length > 0
                                  ? field.label.trim()
                                  : `Campo ${index + 1}`
                              const baseType =
                                typeof field?.type === "string" && field.type.trim().length > 0
                                  ? field.type
                                  : "text"
                              const previousFormatted = formatTicketCustomFieldValue({
                                type: baseType,
                                value: field?.previousValue,
                                displayValue:
                                  typeof field?.previousDisplayValue === "string" && field.previousDisplayValue.trim().length > 0
                                    ? field.previousDisplayValue
                                    : undefined,
                              })
                              const nextFormatted = formatTicketCustomFieldValue({
                                type: baseType,
                                value: field?.nextValue,
                                displayValue:
                                  typeof field?.nextDisplayValue === "string" && field.nextDisplayValue.trim().length > 0
                                    ? field.nextDisplayValue
                                    : undefined,
                              })
                              return (
                                <li key={`${entry.id}-${field?.fieldKey ?? label}`}>
                                  <span className="font-semibold text-neutral-800">{label}</span>{" "}
                                  <span className="text-neutral-500">
                                    {previousFormatted} → {nextFormatted}
                                  </span>
                                </li>
                              )
                            })}
                          </ul>
                        </div>
                      )
                    } else {
                      const fieldLabels = payloadFields
                        .map((field) => (typeof field?.label === "string" ? field.label.trim() : ""))
                        .filter((label) => label.length > 0)
                      message = (
                        <div className="space-y-1">
                          <span className="block text-sm text-neutral-600">
                            <span className="font-semibold text-neutral-800">Campos personalizados atualizados</span>
                            {fieldLabels.length > 0 ? (
                              <span className="text-neutral-500"> ({fieldLabels.join(", ")})</span>
                            ) : null}
                          </span>
                        </div>
                      )
                    }
                  }
                  if (entry.type === "STATUS_CHANGED" && (payload.toLabel || payload.to)) {
                    message = "Status alterado para " + (payload.toLabel || payload.to)
                  }
                  if (entry.type === "ASSIGNEE_CHANGED") {
                    const nextAssigneeRaw = payload.assigneeName ?? payload.assigneeId ?? null
                    const previousAssigneeRaw = (payload as { previousAssigneeName?: unknown }).previousAssigneeName ?? null
                    const nextAssignee =
                      typeof nextAssigneeRaw === "string" && nextAssigneeRaw.trim().length > 0
                        ? nextAssigneeRaw.trim()
                        : typeof nextAssigneeRaw === "number"
                          ? String(nextAssigneeRaw)
                          : null
                    const previousAssignee =
                      typeof previousAssigneeRaw === "string" && previousAssigneeRaw.trim().length > 0
                        ? previousAssigneeRaw.trim()
                        : null
                    const reasonRaw = (payload as { reason?: unknown }).reason
                    const reason =
                      typeof reasonRaw === "string" && reasonRaw.trim().length > 0
                        ? reasonRaw.trim()
                        : null
                    message = (
                      <div className="space-y-1">
                        <span className="block text-sm text-neutral-600">
                          <span className="font-semibold text-neutral-800">Responsável alterado</span>
                          {nextAssignee ? (
                            <>
                              {" "}
                              para <span className="font-semibold text-neutral-900">{nextAssignee}</span>
                            </>
                          ) : (
                            <>.</>
                          )}
                          {previousAssignee ? (
                            <span className="text-neutral-500"> (antes: {previousAssignee})</span>
                          ) : null}
                        </span>
                        {reason ? (
                          <p className="whitespace-pre-line rounded-lg bg-slate-100 px-3 py-2 text-xs text-neutral-600">
                            {reason}
                          </p>
                        ) : null}
                      </div>
                    )
                  }
                  if (entry.type === "QUEUE_CHANGED" && (payload.queueName || payload.queueId)) {
                    message = "Fila alterada" + (payload.queueName ? " para " + payload.queueName : "")
                  }
                  if (entry.type === "REQUESTER_CHANGED") {
                    const payloadRequest = payload as {
                      requesterName?: string | null
                      requesterEmail?: string | null
                      requesterId?: string | null
                      companyName?: string | null
                    }
                    const name = payloadRequest.requesterName?.trim()
                    const email = payloadRequest.requesterEmail?.trim()
                    const fallback = payloadRequest.requesterId ?? null
                    const identifier = name ? (email ? `${name} · ${email}` : name) : email ?? fallback
                    const company = payloadRequest.companyName?.trim()
                    if (identifier && company) {
                      message = `Solicitante alterado para ${identifier} • Empresa: ${company}`
                    } else if (identifier) {
                      message = `Solicitante alterado para ${identifier}`
                    } else if (company) {
                      message = `Solicitante associado à empresa ${company}`
                    } else {
                      message = "Solicitante alterado"
                    }
                  }
                  if (entry.type === "PRIORITY_CHANGED" && (payload.toLabel || payload.to)) {
                    message = "Prioridade alterada para " + (payload.toLabel || payload.to)
                  }
                  if (entry.type === "CREATED" && payload.requesterName) {
                    message = "Criado por " + payload.requesterName
                  }
                  if (entry.type === "COMMENT_ADDED" && (payload.authorName || payload.authorId)) {
                    message = "Comentário adicionado" + (payload.authorName ? " por " + payload.authorName : "")
                  }
                  if (entry.type === "COMMENT_EDITED" && (payload.actorName || payload.actorId || payload.authorName)) {
                    const name = payload.actorName ?? payload.authorName
                    message = "Comentário editado" + (name ? " por " + name : "")
                  }
                  if (entry.type === "SUBJECT_CHANGED" && (payload.to || payload.toLabel)) {
                    message = "Assunto alterado" + (payload.to ? " para \"" + payload.to + "\"" : "")
                  }
                  if (entry.type === "SUMMARY_CHANGED") {
                    message = "Resumo atualizado"
                  }
                  if (entry.type === "ATTACHMENT_REMOVED" && payload.attachmentName) {
                    message = `Anexo removido: ${payload.attachmentName}`
                  }
                  if (entry.type === "WORK_PAUSED") {
                    const parts: string[] = []
                    if (payload.pauseReasonLabel || payload.pauseReason) {
                      parts.push(`Motivo: ${payload.pauseReasonLabel ?? payload.pauseReason}`)
                    }
                    if (typeof payload.sessionDurationMs === "number") {
                      parts.push(`Tempo registrado: ${formatDuration(payload.sessionDurationMs)}`)
                    }
                    message = (
                      <div className="space-y-1">
                        <span>{parts.length > 0 ? parts.join(" • ") : "Atendimento pausado"}</span>
                        {payload.pauseNote ? (
                          <span className="block text-xs text-neutral-500">Observação: {payload.pauseNote}</span>
                        ) : null}
                      </div>
                    )
                  }
                  if (entry.type === "CATEGORY_CHANGED") {
                    if (payload.categoryName || payload.subcategoryName) {
                      message = `Categoria alterada para ${payload.categoryName ?? ""}${
                        payload.subcategoryName ? ` • ${payload.subcategoryName}` : ""
                      }`
                    } else {
                      message = "Categoria removida"
                    }
                  }
                  if (entry.type === "MANAGER_NOTIFIED") {
                    const manager =
                      payload.managerName ??
                      payload.managerUserName ??
                      payload.manager ??
                      payload.managerId ??
                      payload.managerUserId
                    message = manager ? `Gestor notificado: ${manager}` : "Gestor notificado"
                  }
                  if (entry.type === "VISIT_SCHEDULED") {
                    const scheduledRaw = payload.scheduledFor ?? payload.scheduledAt
                    let formatted: string | null = null
                    if (typeof scheduledRaw === "number" || typeof scheduledRaw === "string") {
                      const date = new Date(scheduledRaw)
                      if (!Number.isNaN(date.getTime())) {
                        formatted = format(date, "dd MMM yyyy HH:mm", { locale: ptBR })
                      }
                    }
                    message = formatted ? `Visita agendada para ${formatted}` : "Visita agendada"
                  }
                  if (entry.type === "CSAT_RECEIVED") {
                    message = "CSAT recebido"
                  }
                  if (entry.type === "CSAT_RATED") {
                    const rawScoreSource = (payload as { score?: unknown; rating?: unknown }) ?? {}
                    const rawScore =
                      typeof rawScoreSource.score === "number"
                        ? rawScoreSource.score
                        : typeof rawScoreSource.rating === "number"
                          ? rawScoreSource.rating
                          : null
                    const rawMaxSource = (payload as { maxScore?: unknown; max?: unknown }) ?? {}
                    const rawMax =
                      typeof rawMaxSource.maxScore === "number"
                        ? rawMaxSource.maxScore
                        : typeof rawMaxSource.max === "number"
                          ? rawMaxSource.max
                          : undefined
                    const safeMax = rawMax && Number.isFinite(rawMax) && rawMax > 0 ? Math.round(rawMax) : 5
                    const safeScore =
                      typeof rawScore === "number" && Number.isFinite(rawScore)
                        ? Math.max(1, Math.min(safeMax, Math.round(rawScore)))
                        : null
                    const rawComment = (payload as { comment?: unknown })?.comment
                    const comment =
                      typeof rawComment === "string" && rawComment.trim().length > 0
                        ? rawComment.trim()
                        : null
                    message = (
                      <div className="space-y-1">
                        <span>
                          CSAT avaliado:{" "}
                          <span className="font-semibold text-neutral-900">
                            {safeScore ?? "—"}/{safeMax}
                          </span>
                        </span>
                        <div className="flex items-center gap-1 text-amber-500">
                          {Array.from({ length: safeMax }).map((_, index) => (
                            <IconStar
                              key={index}
                              className="size-3.5"
                              strokeWidth={1.5}
                              fill={safeScore !== null && index < safeScore ? "currentColor" : "none"}
                            />
                          ))}
                        </div>
                        {comment ? (
                          <span className="block rounded-lg bg-slate-100 px-3 py-1 text-xs text-neutral-600">
                            “{comment}”
                          </span>
                        ) : null}
                      </div>
                    )
                  }
                  if (!message) return null

                  return (
                    <div className="rounded-xl border border-slate-200 bg-white px-3 py-2 text-sm text-neutral-600">{message}</div>
                  )
                })()}
              </div>
            </div>
          )
        })}
        <Separator className="bg-slate-200" />
      </CardContent>
    </Card>
  )
}
