/* eslint-disable jsx-a11y/alt-text */
import path from "path"
import fs from "fs"
import { format } from "date-fns"
import { ptBR } from "date-fns/locale"
import sanitizeHtml from "sanitize-html"
import {
  Document,
  Font,
  Image,
  Page,
  StyleSheet,
  Text,
  View,
  renderToBuffer,
} from "@react-pdf/renderer"

import type { TicketWithDetails, TicketComment, TicketEvent } from "../../lib/schemas/ticket"
import { TICKET_TIMELINE_LABELS } from "../../lib/ticket-timeline-labels"

Font.register({ family: "Inter", fonts: [] })

const interRegular = path.join(process.cwd(), "Inter,Manrope", "Inter", "static", "Inter_24pt-Regular.ttf")
const interSemiBold = path.join(process.cwd(), "Inter,Manrope", "Inter", "static", "Inter_24pt-SemiBold.ttf")
const fallbackRegular = path.join(process.cwd(), "Inter,Manrope", "Inter", "static", "Inter_18pt-Regular.ttf")

try {
  if (fs.existsSync(interRegular)) {
    Font.register({ family: "Inter", src: interRegular })
  } else if (fs.existsSync(fallbackRegular)) {
    Font.register({ family: "Inter", src: fallbackRegular })
  }

  if (fs.existsSync(interSemiBold)) {
    Font.register({ family: "Inter-Semi", src: interSemiBold, fontWeight: 600 })
  }
} catch (error) {
  console.warn("[pdf] Não foi possível registrar fontes Inter, usando Helvetica", error)
}

const BASE_FONT = Font.getRegisteredFontFamilies().includes("Inter") ? "Inter" : "Helvetica"
const SEMI_FONT = Font.getRegisteredFontFamilies().includes("Inter-Semi") ? "Inter-Semi" : BASE_FONT

const styles = StyleSheet.create({
  page: {
    paddingTop: 32,
    paddingBottom: 32,
    paddingHorizontal: 36,
    fontFamily: BASE_FONT,
    backgroundColor: "#F8FAFC",
    color: "#0F172A",
    fontSize: 11,
  },
  header: {
    backgroundColor: "#FFFFFF",
    borderRadius: 12,
    borderColor: "#E2E8F0",
    borderWidth: 1,
    padding: 18,
    flexDirection: "row",
    gap: 16,
    alignItems: "center",
    marginBottom: 18,
  },
  headerText: {
    flex: 1,
    gap: 4,
  },
  headerTitle: {
    fontFamily: SEMI_FONT,
    fontSize: 20,
    color: "#0F172A",
  },
  headerSubtitle: {
    fontSize: 10,
    letterSpacing: 1,
    textTransform: "uppercase",
    color: "#64748B",
    fontFamily: SEMI_FONT,
  },
  statusBadge: {
    paddingHorizontal: 10,
    paddingVertical: 6,
    borderRadius: 999,
    fontSize: 10,
    fontFamily: SEMI_FONT,
    textTransform: "uppercase",
  },
  section: {
    marginBottom: 20,
    backgroundColor: "#FFFFFF",
    borderRadius: 12,
    borderColor: "#E2E8F0",
    borderWidth: 1,
    padding: 18,
  },
  sectionHeading: {
    marginBottom: 12,
    backgroundColor: "#FFFFFF",
    borderRadius: 12,
    borderColor: "#E2E8F0",
    borderWidth: 1,
    paddingHorizontal: 18,
    paddingVertical: 14,
  },
  cardGroup: {
    marginBottom: 20,
  },
  sectionTitle: {
    fontFamily: SEMI_FONT,
    fontSize: 13,
    color: "#1E293B",
    marginBottom: 10,
  },
  metaGrid: {
    flexDirection: "row",
    gap: 18,
  },
  metaColumn: {
    flex: 1,
    gap: 8,
  },
  metaItem: {
    gap: 4,
  },
  metaLabel: {
    fontSize: 9,
    letterSpacing: 1,
    color: "#64748B",
    textTransform: "uppercase",
    fontFamily: SEMI_FONT,
  },
  metaValue: {
    color: "#0F172A",
  },
  bodyText: {
    color: "#334155",
    lineHeight: 1.45,
  },
  chipList: {
    flexDirection: "row",
    flexWrap: "wrap",
    gap: 6,
    marginTop: 6,
  },
  chip: {
    backgroundColor: "#E2E8F0",
    borderRadius: 999,
    paddingHorizontal: 6,
    paddingVertical: 4,
    fontSize: 9,
    fontFamily: SEMI_FONT,
    color: "#475569",
  },
  card: {
    borderColor: "#E2E8F0",
    borderWidth: 1,
    borderRadius: 12,
    padding: 14,
    marginBottom: 12,
    backgroundColor: "#FFFFFF",
    gap: 6,
  },
  cardSpacing: {
    marginTop: 8,
  },
  cardHeader: {
    flexDirection: "row",
    justifyContent: "space-between",
    alignItems: "flex-start",
  },
  cardTitle: {
    fontFamily: SEMI_FONT,
    fontSize: 11,
    color: "#0F172A",
  },
  cardSubtitle: {
    color: "#64748B",
    fontSize: 9,
  },
  cardFooterTitle: {
    fontFamily: SEMI_FONT,
    fontSize: 9,
    marginTop: 6,
    color: "#475569",
  },
  timelineCard: {
    marginBottom: 10,
  },
  timelineDetails: {
    fontSize: 10,
    color: "#4B5563",
  },
})

const statusStyles: Record<string, { backgroundColor: string; color: string; label: string }> = {
  PENDING: { backgroundColor: "#F1F5F9", color: "#0F172A", label: "Pendente" },
  AWAITING_ATTENDANCE: { backgroundColor: "#E0F2FE", color: "#0369A1", label: "Aguardando atendimento" },
  PAUSED: { backgroundColor: "#FEF3C7", color: "#92400E", label: "Pausado" },
  RESOLVED: { backgroundColor: "#DCFCE7", color: "#166534", label: "Resolvido" },
}

const priorityLabel: Record<string, string> = {
  LOW: "Baixa",
  MEDIUM: "Média",
  HIGH: "Alta",
  URGENT: "Urgente",
  CRITICAL: "Crítica",
}

const channelLabel: Record<string, string> = {
  EMAIL: "E-mail",
  PHONE: "Telefone",
  CHAT: "Chat",
  PORTAL: "Portal",
  WEB: "Portal",
  API: "API",
  SOCIAL: "Redes sociais",
  OTHER: "Outro",
  WHATSAPP: "WhatsApp",
  MANUAL: "Manual",
}

const sanitizeOptions: sanitizeHtml.IOptions = {
  allowedTags: ["p", "br", "strong", "em", "u", "s", "ul", "ol", "li", "blockquote"],
  allowedAttributes: {},
  selfClosing: ["br"],
  allowVulnerableTags: false,
}

function formatDateTime(date: Date | null | undefined) {
  if (!date) return "—"
  return format(date, "dd/MM/yyyy HH:mm", { locale: ptBR })
}

function sanitizeToPlainText(html?: string | null) {
  if (!html) return ""
  const stripped = sanitizeHtml(html, sanitizeOptions)
  return stripped
    .replace(/<br\s*\/>/gi, "\n")
    .replace(/<\/p>/gi, "\n\n")
    .replace(/<[^>]+>/g, "")
    .replace(/&nbsp;/g, " ")
    .replace(/&amp;/g, "&")
    .replace(/&lt;/g, "<")
    .replace(/&gt;/g, ">")
    .replace(/&quot;/g, '"')
    .replace(/&#39;/g, "'")
    .trim()
}

function buildTimelineMessage(type: string, payload: Record<string, unknown> | null | undefined): string | null {
  const p = payload ?? {}
  const to = (p.toLabel as string | undefined) ?? (p.to as string | undefined)
  const assignee = (p.assigneeName as string | undefined) ?? (p.assigneeId as string | undefined)
  const queue = (p.queueName as string | undefined) ?? (p.queueId as string | undefined)
  const requester = p.requesterName as string | undefined
  const author = (p.authorName as string | undefined) ?? (p.authorId as string | undefined)
  const actor = (p.actorName as string | undefined) ?? (p.actorId as string | undefined)
  const attachmentName = p.attachmentName as string | undefined
  const subjectTo = p.to as string | undefined
  const pauseReason = (p.pauseReasonLabel as string | undefined) ?? (p.pauseReason as string | undefined)
  const pauseNote = p.pauseNote as string | undefined
  const sessionDuration = (p.sessionDurationMs as number | undefined) ?? null
  const sessionText = sessionDuration ? formatDurationMs(sessionDuration) : null
  const categoryName = p.categoryName as string | undefined
  const subcategoryName = p.subcategoryName as string | undefined

  switch (type) {
    case "STATUS_CHANGED":
      return to ? `Status alterado para ${to}` : "Status alterado"
    case "ASSIGNEE_CHANGED":
      return assignee ? `Responsável alterado para ${assignee}` : "Responsável alterado"
    case "QUEUE_CHANGED":
      return queue ? `Fila alterada para ${queue}` : "Fila alterada"
    case "PRIORITY_CHANGED":
      return to ? `Prioridade alterada para ${to}` : "Prioridade alterada"
    case "CREATED":
      return requester ? `Criado por ${requester}` : "Criado"
    case "COMMENT_ADDED":
      return author ? `Comentário adicionado por ${author}` : "Comentário adicionado"
    case "COMMENT_EDITED": {
      const who = actor ?? author
      return who ? `Comentário editado por ${who}` : "Comentário editado"
    }
    case "SUBJECT_CHANGED":
      return subjectTo ? `Assunto alterado para "${subjectTo}"` : "Assunto alterado"
    case "SUMMARY_CHANGED":
      return "Resumo atualizado"
    case "ATTACHMENT_REMOVED":
      return attachmentName ? `Anexo removido: ${attachmentName}` : "Anexo removido"
    case "WORK_PAUSED": {
      const parts: string[] = []
      if (pauseReason) parts.push(`Motivo: ${pauseReason}`)
      if (sessionText) parts.push(`Tempo registrado: ${sessionText}`)
      if (pauseNote) parts.push(`Observação: ${pauseNote}`)
      return parts.length > 0 ? parts.join(" • ") : "Atendimento pausado"
    }
    case "WORK_STARTED":
      return "Atendimento iniciado"
    case "CATEGORY_CHANGED": {
      if (categoryName || subcategoryName) {
        return `Categoria alterada para ${categoryName ?? ""}${subcategoryName ? ` • ${subcategoryName}` : ""}`.trim()
      }
      return "Categoria removida"
    }
    case "MANAGER_NOTIFIED":
      return "Gestor notificado"
    case "VISIT_SCHEDULED":
      return "Visita agendada"
    case "CSAT_RECEIVED":
      return "CSAT recebido"
    case "CSAT_RATED":
      return "CSAT avaliado"
    default:
      return null
  }
}

function formatDurationMs(ms: number) {
  if (!ms || ms <= 0) return "0s"
  const totalSeconds = Math.floor(ms / 1000)
  const hours = Math.floor(totalSeconds / 3600)
  const minutes = Math.floor((totalSeconds % 3600) / 60)
  const seconds = totalSeconds % 60
  if (hours > 0) return `${hours}h ${String(minutes).padStart(2, "0")}m`
  if (minutes > 0) return `${minutes}m ${String(seconds).padStart(2, "0")}s`
  return `${seconds}s`
}

function stringifyPayload(payload: unknown) {
  if (!payload) return null
  try {
    return JSON.stringify(payload, null, 2)
  } catch {
    return String(payload)
  }
}

const statusInfo = (status: string) => statusStyles[status] ?? statusStyles.PENDING

function TicketPdfDocument({ ticket, logoDataUrl }: { ticket: TicketWithDetails; logoDataUrl?: string | null }) {
  const status = statusInfo(ticket.status)
  const requester = ticket.requester
  const assignee = ticket.assignee
  const comments = [...ticket.comments]
    .sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime())
    .map((comment) => ({
      ...comment,
      safeBody: sanitizeToPlainText(comment.body) || "Sem texto",
    })) as Array<TicketComment & { safeBody: string }>

  const timeline = [...ticket.timeline]
    .sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime())
    .map((event) => {
      const label = TICKET_TIMELINE_LABELS[event.type] ?? event.type
      const details = buildTimelineMessage(event.type, event.payload)
      const raw = details ?? stringifyPayload(event.payload)
      return {
        ...event,
        label,
        description: raw,
      }
    }) as Array<TicketEvent & { label: string; description: string | null }>

  const leftMeta = [
    { label: "Status", value: status.label },
    { label: "Prioridade", value: priorityLabel[ticket.priority] ?? ticket.priority },
    { label: "Canal", value: channelLabel[ticket.channel] ?? ticket.channel ?? "—" },
    { label: "Fila", value: ticket.queue ?? "—" },
  ]

  if (ticket.company?.name) {
    leftMeta.push({ label: "Empresa", value: ticket.company.name })
  }
  if (ticket.category?.name) {
    leftMeta.push({
      label: "Categoria",
      value: ticket.subcategory?.name ? `${ticket.category.name} • ${ticket.subcategory.name}` : ticket.category.name,
    })
  }
  if (ticket.tags?.length) {
    leftMeta.push({ label: "Tags", value: ticket.tags.join(", ") })
  }

  const rightMeta = [
    { label: "Solicitante", value: `${requester.name} (${requester.email})` },
    { label: "Responsável", value: assignee ? `${assignee.name} (${assignee.email})` : "Não atribuído" },
    { label: "Criado em", value: formatDateTime(ticket.createdAt) },
    { label: "Atualizado em", value: formatDateTime(ticket.updatedAt) },
  ]
  if (ticket.resolvedAt) {
    rightMeta.push({ label: "Resolvido em", value: formatDateTime(ticket.resolvedAt) })
  }

  const description = sanitizeToPlainText(ticket.description)

  return (
    <Document title={`Ticket #${ticket.reference}`}>
      <Page size="A4" style={styles.page}>
        <View style={styles.header}>
          {logoDataUrl ? <Image src={logoDataUrl} style={{ width: 72, height: 72, borderRadius: 12 }} /> : null}
          <View style={styles.headerText}>
            <Text style={styles.headerSubtitle}>Ticket #{ticket.reference}</Text>
            <Text style={styles.headerTitle}>{ticket.subject}</Text>
          </View>
          <View style={{ paddingLeft: 6 }}>
            <Text
              style={{
                ...styles.statusBadge,
                backgroundColor: status.backgroundColor,
                color: status.color,
              }}
            >
              {status.label}
            </Text>
          </View>
        </View>

        <View style={styles.section}>
          <View style={styles.metaGrid}>
            <View style={styles.metaColumn}>
              {leftMeta.map((item) => (
                <View key={item.label} style={styles.metaItem}>
                  <Text style={styles.metaLabel}>{item.label}</Text>
                  <Text style={styles.metaValue}>{item.value}</Text>
                </View>
              ))}
            </View>
            <View style={styles.metaColumn}>
              {rightMeta.map((item) => (
                <View key={item.label} style={styles.metaItem}>
                  <Text style={styles.metaLabel}>{item.label}</Text>
                  <Text style={styles.metaValue}>{item.value}</Text>
                </View>
              ))}
            </View>
          </View>
        </View>

        {ticket.summary ? (
          <View style={styles.section}>
            <Text style={styles.sectionTitle}>Resumo</Text>
            <Text style={styles.bodyText}>{ticket.summary}</Text>
          </View>
        ) : null}

        {description ? (
          <View style={styles.section}>
            <Text style={styles.sectionTitle}>Descrição</Text>
            <Text style={styles.bodyText}>{description}</Text>
          </View>
        ) : null}

        {ticket.tags && ticket.tags.length > 0 ? (
          <View style={styles.section}>
            <Text style={styles.sectionTitle}>Etiquetas</Text>
            <View style={styles.chipList}>
              {ticket.tags.map((tag) => (
                <Text key={tag} style={styles.chip}>
                  {tag}
                </Text>
              ))}
            </View>
          </View>
        ) : null}

        {comments.length > 0 ? (
          <>
            <View style={styles.sectionHeading}>
              <Text style={{ ...styles.sectionTitle, marginBottom: 0 }}>Comentários</Text>
            </View>
            <View style={styles.cardGroup}>
              {comments.map((comment, index) => (
                <View
                  key={comment.id}
                  style={index > 0 ? [styles.card, styles.cardSpacing] : [styles.card]}
                  wrap={false}
                >
                  <View style={styles.cardHeader}>
                    <View>
                      <Text style={styles.cardTitle}>{comment.author.name}</Text>
                      <Text style={styles.cardSubtitle}>
                        {formatDateTime(comment.createdAt)} • {comment.visibility === "PUBLIC" ? "Público" : "Interno"}
                      </Text>
                    </View>
                  </View>
                  <Text style={styles.bodyText}>{comment.safeBody}</Text>
                  {comment.attachments.length > 0 ? (
                    <View>
                      <Text style={styles.cardFooterTitle}>Anexos</Text>
                      {comment.attachments.map((attachment) => (
                        <Text key={attachment.id} style={{ fontSize: 9, color: "#475569" }}>
                          • {attachment.name ?? attachment.id}
                        </Text>
                      ))}
                    </View>
                  ) : null}
                </View>
              ))}
            </View>
          </>
        ) : null}

        {timeline.length > 0 ? (
          <>
            <View style={styles.sectionHeading}>
              <Text style={{ ...styles.sectionTitle, marginBottom: 0 }}>Linha do tempo</Text>
            </View>
            <View style={styles.cardGroup}>
              {timeline.map((event, index) => (
                <View
                  key={event.id}
                  style={
                    index > 0
                      ? [styles.card, styles.timelineCard, styles.cardSpacing]
                      : [styles.card, styles.timelineCard]
                  }
                  wrap={false}
                >
                  <Text style={styles.cardTitle}>{event.label}</Text>
                  <Text style={styles.cardSubtitle}>{formatDateTime(event.createdAt)}</Text>
                  {event.description ? (
                    <Text style={styles.timelineDetails}>{event.description}</Text>
                  ) : null}
                </View>
              ))}
            </View>
          </>
        ) : null}
      </Page>
    </Document>
  )
}

export async function renderTicketPdfBuffer({
  ticket,
  logoDataUrl,
}: {
  ticket: TicketWithDetails
  logoDataUrl?: string | null
}) {
  const doc = <TicketPdfDocument ticket={ticket} logoDataUrl={logoDataUrl} />
  const buffer = await renderToBuffer(doc)
  return buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer)
}
