"use client"

import { useEffect, useMemo, useState } from "react"
import { useMutation } from "convex/react"
import { useRouter } from "next/navigation"
import { Star } from "lucide-react"
import { formatDistanceToNowStrict } from "date-fns"
import { ptBR } from "date-fns/locale"
import { toast } from "sonner"

import { api } from "@/convex/_generated/api"
import type { Id } from "@/convex/_generated/dataModel"
import { useAuth } from "@/lib/auth-client"
import type { TicketWithDetails } from "@/lib/schemas/ticket"
import { cn } from "@/lib/utils"
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card"
import { Button } from "@/components/ui/button"
import { Textarea } from "@/components/ui/textarea"

type TicketCsatCardProps = {
  ticket: TicketWithDetails
}

function formatRelative(timestamp: Date | null | undefined) {
  if (!timestamp) return null
  try {
    return formatDistanceToNowStrict(timestamp, { locale: ptBR, addSuffix: true })
  } catch {
    return null
  }
}

export function TicketCsatCard({ ticket }: TicketCsatCardProps) {
  const router = useRouter()
  const { session, convexUserId, role: authRole, machineContext } = useAuth()
  const submitCsat = useMutation(api.tickets.submitCsat)

  const deriveViewerRole = () => {
    const authRoleNormalized = authRole?.toLowerCase()?.trim()
    const machinePersona = machineContext?.persona ?? session?.user.machinePersona ?? null
    const assignedRole = machineContext?.assignedUserRole ?? null
    const sessionRole = session?.user.role?.toLowerCase()?.trim()

    if (authRoleNormalized && authRoleNormalized !== "machine") {
      return authRoleNormalized.toUpperCase()
    }

    if (authRoleNormalized === "machine" && machinePersona) {
      return machinePersona.toUpperCase()
    }

    if (machinePersona) {
      return machinePersona.toUpperCase()
    }

    if (assignedRole) {
      return assignedRole.toUpperCase()
    }

    if (sessionRole && sessionRole !== "machine") {
      return sessionRole.toUpperCase()
    }

    if (sessionRole === "machine") {
      return "COLLABORATOR"
    }

    return "COLLABORATOR"
  }

  const viewerRole = deriveViewerRole()

  const viewerEmail = session?.user.email?.trim().toLowerCase() ?? ""
  const viewerId = convexUserId as Id<"users"> | undefined

  const requesterEmail = ticket.requester.email.trim().toLowerCase()
  const isRequesterById = viewerId ? ticket.requester.id === viewerId : false
  const isRequesterByEmail = viewerEmail && requesterEmail ? viewerEmail === requesterEmail : false
  const isRequester = isRequesterById || isRequesterByEmail
  const isResolved = ticket.status === "RESOLVED"

  const initialScore = typeof ticket.csatScore === "number" ? ticket.csatScore : 0
  const initialComment = ticket.csatComment ?? ""
  const maxScore = typeof ticket.csatMaxScore === "number" && ticket.csatMaxScore > 0 ? ticket.csatMaxScore : 5

  const [score, setScore] = useState<number>(initialScore)
  const [comment, setComment] = useState<string>(initialComment)
  const [hasSubmitted, setHasSubmitted] = useState<boolean>(initialScore > 0)
  const [ratedAt, setRatedAt] = useState<Date | null>(ticket.csatRatedAt ?? null)
  const [hoverScore, setHoverScore] = useState<number | null>(null)
  const [submitting, setSubmitting] = useState(false)

  const ratedAtTimestamp = ticket.csatRatedAt ? ticket.csatRatedAt.getTime() : null

  useEffect(() => {
    setScore((prev) => (prev === initialScore ? prev : initialScore))
    setComment((prev) => (prev === initialComment ? prev : initialComment))
    const nextRatedAt = ratedAtTimestamp == null ? null : new Date(ratedAtTimestamp)
    setRatedAt((prev) => {
      if (prev === nextRatedAt) return prev
      if (prev && nextRatedAt && prev.getTime() === nextRatedAt.getTime()) return prev
      return nextRatedAt
    })
    const nextHasSubmitted = initialScore > 0
    setHasSubmitted((prev) => (prev === nextHasSubmitted ? prev : nextHasSubmitted))
  }, [initialScore, initialComment, ratedAtTimestamp])

  const effectiveScore = hasSubmitted ? score : hoverScore ?? score
  const viewerIsAdmin = viewerRole === "ADMIN"
  const viewerIsStaff =
    viewerRole === "MANAGER" || viewerRole === "AGENT" || viewerIsAdmin
  const collaboratorCanView = !viewerIsStaff && isRequester
  const adminCanInspect = viewerIsAdmin && ticket.status !== "PENDING"
  const canSubmit =
    Boolean(viewerId && viewerRole === "COLLABORATOR" && isRequester && isResolved && !hasSubmitted)
  const hasRating = hasSubmitted
  const showCard = adminCanInspect || collaboratorCanView

  const ratedAtRelative = useMemo(() => formatRelative(ratedAt), [ratedAt])

  if (!showCard) {
    return null
  }

  const handleSubmit = async () => {
    if (!viewerId) {
      toast.error("Sessão não autenticada.")
      return
    }
    if (!canSubmit) {
      toast.error("Você não pode avaliar este chamado.")
      return
    }
    if (score < 1) {
      toast.error("Selecione uma nota de 1 a 5 estrelas.")
      return
    }
    if (comment.length > 2000) {
      toast.error("Reduza o comentário para no máximo 2000 caracteres.")
      return
    }
    try {
      setSubmitting(true)
      const result = await submitCsat({
        ticketId: ticket.id as Id<"tickets">,
        actorId: viewerId,
        score,
        maxScore,
        comment: comment.trim() ? comment.trim() : undefined,
      })
      if (result?.score) {
        setScore(result.score)
      }
      if (typeof result?.comment === "string") {
        setComment(result.comment)
      }
      if (result?.ratedAt) {
        const ratedAtDate = new Date(result.ratedAt)
        if (!Number.isNaN(ratedAtDate.getTime())) {
          setRatedAt(ratedAtDate)
        }
      }
      setHasSubmitted(true)
      toast.success("Avaliação registrada. Obrigado pelo feedback!")
      router.refresh()
    } catch (error) {
      console.error("Failed to submit CSAT", error)
      toast.error("Não foi possível registrar a avaliação. Tente novamente.")
    } finally {
      setSubmitting(false)
      setHoverScore(null)
    }
  }

  const stars = Array.from({ length: maxScore }, (_, index) => index + 1)

  return (
    <Card id="csat" className="rounded-2xl border border-slate-200 bg-gradient-to-br from-white via-white to-slate-50 shadow-sm">
      <CardHeader className="px-4 pt-5 pb-3">
        <div className="flex items-start justify-between gap-3">
          <div className="space-y-1">
            <CardTitle className="text-lg font-semibold text-neutral-900">Avaliação do atendimento</CardTitle>
            <CardDescription className="text-sm text-neutral-600">
              Conte como foi sua experiência com este chamado.
            </CardDescription>
          </div>
          {hasRating && collaboratorCanView ? (
            <div className="flex items-center gap-1 rounded-full bg-emerald-50 px-3 py-1 text-xs font-medium text-emerald-700">
              Obrigado pelo feedback!
            </div>
          ) : null}
        </div>
      </CardHeader>
      <CardContent className="space-y-4 px-4 pb-2">
        <div className="flex flex-wrap items-center gap-2">
          {stars.map((value) => {
            const filled = value <= effectiveScore
            return (
              <button
                key={value}
                type="button"
                className={cn(
                  "flex size-10 items-center justify-center rounded-full border transition",
                  canSubmit
                    ? filled
                      ? "border-amber-300 bg-amber-50 text-amber-500 hover:border-amber-400 hover:bg-amber-100"
                      : "border-slate-200 bg-white text-slate-300 hover:border-amber-200 hover:bg-amber-50 hover:text-amber-400"
                    : filled
                      ? "border-amber-200 bg-amber-50 text-amber-500"
                      : "border-slate-200 bg-white text-slate-300"
                )}
                onMouseEnter={() => (canSubmit ? setHoverScore(value) : undefined)}
                onMouseLeave={() => (canSubmit ? setHoverScore(null) : undefined)}
                onClick={() => (canSubmit ? setScore(value) : undefined)}
                disabled={!canSubmit}
                aria-label={`${value} estrela${value > 1 ? "s" : ""}`}
              >
                <Star
                  className="size-5"
                  strokeWidth={1.5}
                  fill={(canSubmit && value <= (hoverScore ?? score)) || (!canSubmit && value <= score) ? "currentColor" : "none"}
                />
              </button>
            )
          })}
        </div>
        {hasRating ? (
          <p className="text-sm text-neutral-600">
            Nota final:{" "}
            <span className="font-semibold text-neutral-900">
              {score}/{maxScore}
            </span>
            {ratedAtRelative ? ` • ${ratedAtRelative}` : null}
          </p>
        ) : null}
        {canSubmit ? (
          <div className="space-y-2">
            <label htmlFor="csat-comment" className="text-sm font-medium text-neutral-800">
              Deixe um comentário (opcional)
            </label>
            <Textarea
              id="csat-comment"
              placeholder="O que funcionou bem? Algo poderia ser melhor?"
              value={comment}
              onChange={(event) => setComment(event.target.value)}
              maxLength={2000}
              className="min-h-[90px] resize-y"
            />
            <div className="flex justify-end text-xs text-neutral-500">{comment.length}/2000</div>
          </div>
        ) : hasRating && comment ? (
          <div className="rounded-xl border border-slate-200 bg-white px-3 py-2 text-sm text-neutral-700">
            <p className="whitespace-pre-line">{comment}</p>
          </div>
        ) : null}
        {viewerIsAdmin && !hasRating ? (
          <p className="rounded-lg border border-dashed border-slate-200 bg-slate-50 px-3 py-2 text-sm text-neutral-500">
            Nenhuma avaliação registrada para este chamado até o momento.
          </p>
        ) : null}
        {!isResolved && viewerRole === "COLLABORATOR" && isRequester && !hasSubmitted ? (
          <p className="rounded-lg border border-dashed border-slate-200 bg-slate-50 px-3 py-2 text-sm text-neutral-500">
            Assim que o chamado for encerrado, você poderá registrar sua avaliação aqui.
          </p>
        ) : null}
      </CardContent>
      {canSubmit ? (
        <CardFooter className="flex flex-col gap-2 px-4 pb-4 sm:flex-row sm:items-center sm:justify-between">
          <p className="text-xs text-neutral-500">
            Sua avaliação ajuda a equipe a melhorar continuamente o atendimento.
          </p>
          <Button type="button" onClick={handleSubmit} disabled={submitting || score < 1}>
            {submitting ? "Enviando..." : "Enviar avaliação"}
          </Button>
        </CardFooter>
      ) : null}
    </Card>
  )
}
