"use client"

import { useMemo, useState } from "react"
import { useQuery } from "convex/react"
import { api } from "@/convex/_generated/api"
import type { Id } from "@/convex/_generated/dataModel"
import { DEFAULT_TENANT_ID } from "@/lib/constants"
import { mapTicketsFromServerList } from "@/lib/mappers/ticket"
import type { Ticket } from "@/lib/schemas/ticket"
import { useAuth } from "@/lib/auth-client"
import Link from "next/link"
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
import { Empty, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTitle } from "@/components/ui/empty"
import { Spinner } from "@/components/ui/spinner"
import { Button } from "@/components/ui/button"
import { PortalTicketCard } from "@/components/portal/portal-ticket-card"
import {
  PortalTicketFilters,
  defaultPortalTicketFilters,
  type PortalTicketFiltersState,
} from "@/components/portal/portal-ticket-filters"

export function PortalTicketList() {
  const { convexUserId, session, machineContext } = useAuth()

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

  const ticketsRaw = useQuery(
    api.tickets.list,
    viewerId
      ? {
          tenantId: session?.user.tenantId ?? DEFAULT_TENANT_ID,
          viewerId,
          limit: 100,
        }
      : "skip"
  )

  const tickets = useMemo(() => {
    if (!ticketsRaw) return []
    return mapTicketsFromServerList((ticketsRaw as unknown[]) ?? [])
  }, [ticketsRaw])

  const [filters, setFilters] = useState<PortalTicketFiltersState>(defaultPortalTicketFilters)

  const queueOptions = useMemo(() => {
    const set = new Set<string>()
    ;(tickets as Ticket[]).forEach((ticket) => {
      if (ticket.queue) {
        set.add(ticket.queue)
      }
    })
    return Array.from(set).sort((a, b) => a.localeCompare(b, "pt-BR"))
  }, [tickets])

  const companyOptions = useMemo(() => {
    const set = new Set<string>()
    ;(tickets as Ticket[]).forEach((ticket) => {
      const name = ticket.company?.name
      if (name) set.add(name)
    })
    return Array.from(set).sort((a, b) => a.localeCompare(b, "pt-BR"))
  }, [tickets])

  const categoryOptions = useMemo(() => {
    const map = new Map<string, string>()
    ;(tickets as Ticket[]).forEach((ticket) => {
      if (ticket.category?.id && ticket.category.name) {
        map.set(ticket.category.id, ticket.category.name)
      }
    })
    return Array.from(map.entries())
      .map(([id, name]) => ({ id, name }))
      .sort((a, b) => a.name.localeCompare(b.name, "pt-BR"))
  }, [tickets])

  const assigneeOptions = useMemo(() => {
    const map = new Map<string, string>()
    ;(tickets as Ticket[]).forEach((ticket) => {
      if (ticket.assignee?.id && ticket.assignee.name) {
        map.set(ticket.assignee.id, ticket.assignee.name)
      }
    })
    return Array.from(map.entries())
      .map(([id, name]) => ({ id, name }))
      .sort((a, b) => a.name.localeCompare(b.name, "pt-BR"))
  }, [tickets])

  const lastResolvedNoCsat = useMemo(() => {
    const resolved = (tickets as Ticket[])
      .filter((t) => t.status === "RESOLVED" && (t.csatScore == null))
      .sort((a, b) => (b.resolvedAt?.getTime?.() ?? 0) - (a.resolvedAt?.getTime?.() ?? 0))
    return resolved[0] ?? null
  }, [tickets])

  const parseDateInput = (value: string | null, options?: { endOfDay?: boolean }) => {
    if (!value) return null
    const [year, month, day] = value.split("-").map((part) => Number(part))
    if (!year || !month || !day) return null
    const date = new Date(
      year,
      month - 1,
      day,
      options?.endOfDay ? 23 : 0,
      options?.endOfDay ? 59 : 0,
      options?.endOfDay ? 59 : 0,
      options?.endOfDay ? 999 : 0
    )
    if (Number.isNaN(date.getTime())) return null
    return date
  }

  const filteredTickets = useMemo(() => {
    const fromDate = parseDateInput(filters.dateFrom)
    const toDate = parseDateInput(filters.dateTo, { endOfDay: true })
    return (tickets as Ticket[])
      .filter((ticket) => {
        if (filters.queue && ticket.queue !== filters.queue) return false
        if (filters.company && ticket.company?.name !== filters.company) return false
        if (filters.categoryId && ticket.category?.id !== filters.categoryId) return false
        if (filters.assigneeId && ticket.assignee?.id !== filters.assigneeId) return false
        const isResolved = ticket.status === "RESOLVED"
        if (filters.status === "active" && isResolved) return false
        if (filters.status === "resolved" && !isResolved) return false
        const createdAt = ticket.createdAt instanceof Date ? ticket.createdAt : new Date(ticket.createdAt)
        if (fromDate && createdAt < fromDate) return false
        if (toDate && createdAt > toDate) return false
        return true
      })
      .sort((a, b) => {
        const aDate = a.createdAt instanceof Date ? a.createdAt.getTime() : new Date(a.createdAt).getTime()
        const bDate = b.createdAt instanceof Date ? b.createdAt.getTime() : new Date(b.createdAt).getTime()
        return filters.sort === "oldest" ? aDate - bDate : bDate - aDate
      })
  }, [filters, tickets])

  const handleFiltersChange = (partial: Partial<PortalTicketFiltersState>) => {
    setFilters((prev) => ({ ...prev, ...partial }))
  }

  const handleResetFilters = () => {
    setFilters(defaultPortalTicketFilters)
  }

  const isLoading = Boolean(viewerId && ticketsRaw === undefined)

  if (isLoading) {
    return (
      <Card className="rounded-2xl border border-slate-200 bg-white shadow-sm">
        <CardContent className="flex h-56 flex-col items-center justify-center gap-3 px-5 text-center">
          <div className="inline-flex size-12 items-center justify-center rounded-full border border-slate-200 bg-slate-50">
            <Spinner className="size-5 text-neutral-600" />
          </div>
          <div className="space-y-1">
            <CardTitle className="text-lg font-semibold text-neutral-900">Carregando chamados...</CardTitle>
            <p className="text-sm text-neutral-600">
              Estamos buscando seus chamados mais recentes. Isso deve levar apenas alguns instantes.
            </p>
          </div>
        </CardContent>
      </Card>
    )
  }

  if (!viewerId || !tickets.length) {
    return (
      <Card className="rounded-2xl border border-slate-200 bg-white shadow-sm">
        <CardHeader className="px-5 py-5">
          <CardTitle className="text-lg font-semibold text-neutral-900">Meus chamados</CardTitle>
        </CardHeader>
        <CardContent className="px-5 pb-6">
          <Empty>
            <EmptyHeader>
              <EmptyMedia variant="icon">
                <span className="inline-block size-3 rounded-full border border-slate-300 bg-[#00e8ff]" />
              </EmptyMedia>
              <EmptyTitle className="text-neutral-900">Nenhum ticket encontrado</EmptyTitle>
              <EmptyDescription className="text-neutral-600">
                Ajuste os filtros ou crie um novo ticket.
              </EmptyDescription>
            </EmptyHeader>
            <div className="mt-4">
              <Button asChild className="rounded-full bg-neutral-900 px-4 text-sm font-semibold text-white hover:bg-neutral-900/90">
                <Link href="/portal/tickets/new">Novo ticket</Link>
              </Button>
            </div>
          </Empty>
        </CardContent>
      </Card>
    )
  }

  return (
    <div className="space-y-4">
      <div className="flex items-center justify-between">
        <div>
          <h2 className="text-lg font-semibold text-neutral-900">Meus chamados</h2>
          <p className="text-sm text-neutral-600">Acompanhe seus tickets e veja as últimas atualizações.</p>
        </div>
      </div>
      {lastResolvedNoCsat ? (
        <div className="rounded-xl border border-amber-200 bg-amber-50 px-4 py-3 text-sm text-amber-800">
          Como foi seu último atendimento? Avalie o chamado #{lastResolvedNoCsat.reference}.{' '}
          <Link href={`/portal/tickets/${lastResolvedNoCsat.id}#csat`} className="font-semibold underline">
            Avaliar agora
          </Link>
        </div>
      ) : null}
      <PortalTicketFilters
        filters={filters}
        onFiltersChange={handleFiltersChange}
        onReset={handleResetFilters}
        queues={queueOptions}
        companies={companyOptions}
        categories={categoryOptions}
        assignees={assigneeOptions}
      />
      {filteredTickets.length === 0 ? (
        <Card className="rounded-2xl border border-slate-200 bg-white py-8 text-center shadow-sm">
          <CardContent className="space-y-3">
            <CardTitle className="text-lg font-semibold text-neutral-900">Nenhum ticket corresponde aos filtros</CardTitle>
            <p className="text-sm text-neutral-600">
              Ajuste as opções acima ou limpe os filtros para visualizar novamente.
            </p>
            <Button variant="outline" onClick={handleResetFilters} className="mt-2 rounded-full">
              Limpar filtros
            </Button>
          </CardContent>
        </Card>
      ) : (
        <div className="grid gap-4">
          {filteredTickets.map((ticket) => (
            <PortalTicketCard key={ticket.id} ticket={ticket} />
          ))}
        </div>
      )}
    </div>
  )
}
