"use client"

import { type FormEvent, useCallback, useEffect, useMemo, useRef, useState } from "react"
import Link from "next/link"
import { AlertCircle, Loader2, MessageSquare, Phone, SquarePen, X } from "lucide-react"
import { usePathname } from "next/navigation"
import { AssistantAvatar } from "@/components/assistant-avatar"
import { FormInput } from "@/components/forms/form-input"
import { FormSelect } from "@/components/forms/form-select"
import { SmsConsentFields } from "@/components/forms/sms-consent-fields"
import { cn } from "@/lib/utils"
import {
  getSiteChatBootstrap,
  isSiteChatSuppressedRoute,
  SITE_CHAT_MAX_INPUT_CHARS,
} from "@/lib/site-chat/config"
import {
  CHAT_INTENT_OPTIONS,
  getBestIntentFormHref,
  getBestIntentFormLabel,
  isFreePlacementIntent,
  isRepairOrMovingIntent,
} from "@/lib/site-chat/intents"
import { SMS_CONSENT_VERSION } from "@/lib/sms-compliance"

type ChatRole = "user" | "assistant"

type ChatMessage = {
  id: string
  role: ChatRole
  content: string
}

type ChatVisitorProfile = {
  consentCapturedAt: string
  consentSourcePage: string
  consentVersion: string
  email: string
  intent: string
  marketingTextConsent: boolean
  name: string
  phone: string
  serviceTextConsent: boolean
}

type ChatLimitStatus = {
  ipRemaining: number
  sessionRemaining: number
  outputCharsRemaining: number
  requestResetAt: string
  outputResetAt: string
  blocked: boolean
}

type ChatApiResponse = {
  reply?: string
  error?: string
  sessionId?: string
  limits?: ChatLimitStatus
}

const CHAT_UNAVAILABLE_MESSAGE = "Jessica is temporarily unavailable right now. Please call or use the contact form."

const SESSION_STORAGE_KEY = "rmv-site-chat-session"
const PROFILE_STORAGE_KEY = "rmv-site-chat-profile"
const PANEL_MAX_HEIGHT = "min(40rem, calc(100vh - 7rem))"

function createMessage(role: ChatRole, content: string): ChatMessage {
  return {
    id: `${role}-${crypto.randomUUID()}`,
    role,
    content,
  }
}

function createEmptyProfileDraft(consentSourcePage: string): ChatVisitorProfile {
  return {
    name: "",
    phone: "",
    email: "",
    intent: "",
    serviceTextConsent: false,
    marketingTextConsent: false,
    consentVersion: SMS_CONSENT_VERSION,
    consentCapturedAt: "",
    consentSourcePage,
  }
}

function normalizeProfile(
  value: Partial<ChatVisitorProfile> | null | undefined,
  fallbackSourcePage: string,
): ChatVisitorProfile | null {
  if (!value) {
    return null
  }

  const profile = {
    name: String(value.name || "").replace(/\s+/g, " ").trim().slice(0, 80),
    phone: String(value.phone || "").replace(/\s+/g, " ").trim().slice(0, 40),
    email: String(value.email || "").replace(/\s+/g, " ").trim().slice(0, 120).toLowerCase(),
    intent: String(value.intent || "").replace(/\s+/g, " ").trim().slice(0, 80),
    serviceTextConsent: Boolean(value.serviceTextConsent),
    marketingTextConsent: Boolean(value.marketingTextConsent),
    consentVersion: String(value.consentVersion || SMS_CONSENT_VERSION).trim() || SMS_CONSENT_VERSION,
    consentCapturedAt:
      typeof value.consentCapturedAt === "string" && value.consentCapturedAt.trim()
        ? value.consentCapturedAt
        : new Date().toISOString(),
    consentSourcePage:
      typeof value.consentSourcePage === "string" && value.consentSourcePage.trim()
        ? value.consentSourcePage.trim()
        : fallbackSourcePage,
  }

  const digits = profile.phone.replace(/\D/g, "")
  const emailIsValid = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(profile.email)
  const timestampIsValid = !Number.isNaN(Date.parse(profile.consentCapturedAt))
  if (
    !profile.name ||
    !profile.phone ||
    !profile.email ||
    !profile.intent ||
    !profile.serviceTextConsent ||
    digits.length < 10 ||
    !emailIsValid ||
    !timestampIsValid
  ) {
    return null
  }

  return profile
}

function createIntroMessage(profile: ChatVisitorProfile) {
  const firstName = profile.name.split(" ")[0] || profile.name
  const intentLabel = profile.intent.toLowerCase()
  return createMessage("assistant", `Hi ${firstName}, I've got your ${intentLabel} request. How can I help?`)
}

function SupportHint({
  formHref,
  formLabel,
  intent,
  smsNumber,
  smsUrl,
}: {
  formHref: string
  formLabel: string
  intent: string
  smsNumber: string
  smsUrl: string
}) {
  if (isFreePlacementIntent(intent)) {
    return (
      <p className="text-xs leading-relaxed text-muted-foreground">
        Prefer a fuller intake? Use our{" "}
        <Link href={formHref} className="font-medium text-foreground underline decoration-primary/35 underline-offset-4 hover:decoration-primary">
          {formLabel}
        </Link>
        .
      </p>
    )
  }

  if (isRepairOrMovingIntent(intent)) {
    return (
      <p className="text-xs leading-relaxed text-muted-foreground">
        For repairs or moving, text photos or videos to{" "}
        <a href={smsUrl} className="font-medium text-foreground underline decoration-primary/35 underline-offset-4 hover:decoration-primary">
          {smsNumber}
        </a>{" "}
        or use the{" "}
        <Link href={formHref} className="font-medium text-foreground underline decoration-primary/35 underline-offset-4 hover:decoration-primary">
          {formLabel}
        </Link>
        .
      </p>
    )
  }

  return (
    <p className="text-xs leading-relaxed text-muted-foreground">
      Need a fuller request? Use the{" "}
      <Link href={formHref} className="font-medium text-foreground underline decoration-primary/35 underline-offset-4 hover:decoration-primary">
        {formLabel}
      </Link>
      .
    </p>
  )
}

export function SiteChatWidget() {
  const pathname = usePathname()
  const bootstrap = useMemo(() => getSiteChatBootstrap(), [])
  const intentOptions = useMemo(
    () => CHAT_INTENT_OPTIONS.map((option) => ({ label: option, value: option })),
    [],
  )
  const isSuppressed = isSiteChatSuppressedRoute(pathname)
  const [isOpen, setIsOpen] = useState(false)
  const [messages, setMessages] = useState<ChatMessage[]>([])
  const [draft, setDraft] = useState("")
  const [profileDraft, setProfileDraft] = useState<ChatVisitorProfile>(() => createEmptyProfileDraft(pathname || "/"))
  const [profile, setProfile] = useState<ChatVisitorProfile | null>(null)
  const [error, setError] = useState<string | null>(null)
  const [profileError, setProfileError] = useState<string | null>(null)
  const [isSending, setIsSending] = useState(false)
  const [sessionId, setSessionId] = useState<string | null>(null)
  const [, setLimits] = useState<ChatLimitStatus | null>(null)
  const messagesEndRef = useRef<HTMLDivElement | null>(null)

  useEffect(() => {
    const storedSessionId = window.localStorage.getItem(SESSION_STORAGE_KEY)
    if (storedSessionId) {
      setSessionId(storedSessionId)
    }

    const rawProfile = window.localStorage.getItem(PROFILE_STORAGE_KEY)
    if (!rawProfile) {
      setProfileDraft(createEmptyProfileDraft(pathname || "/"))
      return
    }

    try {
      const parsedProfile = normalizeProfile(JSON.parse(rawProfile), pathname || "/")
      if (!parsedProfile) {
        window.localStorage.removeItem(PROFILE_STORAGE_KEY)
        setProfileDraft(createEmptyProfileDraft(pathname || "/"))
        return
      }

      setProfile(parsedProfile)
      setProfileDraft(parsedProfile)
      setMessages([createIntroMessage(parsedProfile)])
    } catch {
      window.localStorage.removeItem(PROFILE_STORAGE_KEY)
      setProfileDraft(createEmptyProfileDraft(pathname || "/"))
    }
  }, [pathname])

  useEffect(() => {
    messagesEndRef.current?.scrollIntoView({ behavior: "smooth", block: "end" })
  }, [messages.length])

  useEffect(() => {
    if (!isSuppressed) {
      return
    }

    setIsOpen(false)
  }, [isSuppressed])

  const activeIntent = profile?.intent || profileDraft.intent
  const formHref = getBestIntentFormHref(activeIntent)
  const formLabel = getBestIntentFormLabel(activeIntent)
  const profileDraftIsReady = Boolean(
    profileDraft.name.trim() &&
      profileDraft.phone.trim() &&
      profileDraft.email.trim() &&
      profileDraft.intent &&
      profileDraft.serviceTextConsent,
  )

  const handleProfileSubmit = useCallback(
    (event: FormEvent<HTMLFormElement>) => {
      event.preventDefault()
      const nextProfile = normalizeProfile(
        {
          ...profileDraft,
          consentCapturedAt: profileDraft.consentCapturedAt || new Date().toISOString(),
          consentSourcePage: pathname || "/",
          consentVersion: profileDraft.consentVersion || SMS_CONSENT_VERSION,
        },
        pathname || "/",
      )

      if (!nextProfile) {
        setProfileError("Enter a valid name, phone, email, intent, and required service SMS consent.")
        return
      }

      setProfile(nextProfile)
      setProfileDraft(nextProfile)
      setMessages([createIntroMessage(nextProfile)])
      setProfileError(null)
      setError(null)
      window.localStorage.setItem(PROFILE_STORAGE_KEY, JSON.stringify(nextProfile))
    },
    [pathname, profileDraft],
  )

  const handleProfileReset = useCallback(() => {
    setProfile(null)
    setProfileDraft(createEmptyProfileDraft(pathname || "/"))
    setMessages([])
    setProfileError(null)
    setError(null)
    window.localStorage.removeItem(PROFILE_STORAGE_KEY)
  }, [pathname])

  const handleSubmit = useCallback(
    async (event: FormEvent<HTMLFormElement>) => {
      event.preventDefault()

      if (!profile) {
        setError("Enter your details before chatting.")
        return
      }

      const trimmed = draft.trim()
      if (!trimmed || isSending) {
        return
      }

      const nextUserMessage = createMessage("user", trimmed)
      const nextMessages = [...messages, nextUserMessage].slice(-12)

      setMessages(nextMessages)
      setDraft("")
      setError(null)
      setIsSending(true)

      try {
        const response = await fetch("/api/chat", {
          method: "POST",
          headers: {
            "Content-Type": "application/json",
          },
          body: JSON.stringify({
            pathname,
            sessionId,
            visitor: profile,
            messages: nextMessages.map((message) => ({
              role: message.role,
              content: message.content,
            })),
          }),
        })

        const data = (await response.json()) as ChatApiResponse

        if (data.sessionId) {
          setSessionId(data.sessionId)
          window.localStorage.setItem(SESSION_STORAGE_KEY, data.sessionId)
        }

        if (data.limits) {
          setLimits(data.limits)
        }

        if (!response.ok || !data.reply) {
          throw new Error(data.error || CHAT_UNAVAILABLE_MESSAGE)
        }

        setMessages((current) => [...current, createMessage("assistant", data.reply || "")].slice(-12))
      } catch (chatError) {
        const message = chatError instanceof Error ? chatError.message : CHAT_UNAVAILABLE_MESSAGE
        setError(message)
        setMessages((current) => [
          ...current,
          createMessage("assistant", "I'm temporarily unavailable right now. Please call us or use the contact form."),
        ].slice(-12))
      } finally {
        setIsSending(false)
      }
    },
    [draft, isSending, messages, pathname, profile, sessionId],
  )

  if (isSuppressed) {
    return null
  }

  return (
    <div
      className="pointer-events-none fixed right-4 z-40 flex flex-col items-end gap-3"
      style={{ bottom: "calc(env(safe-area-inset-bottom, 0px) + 1rem)" }}
    >
      {isOpen ? (
        <div
          data-testid="site-chat-panel"
          className="pointer-events-auto flex w-[min(24rem,calc(100vw-1.5rem))] flex-col overflow-hidden rounded-[1.75rem] border border-border/70 bg-background/95 shadow-[0_24px_80px_rgba(0,0,0,0.2)] backdrop-blur-xl"
          style={{ maxHeight: PANEL_MAX_HEIGHT }}
        >
          <div className="flex items-start justify-between border-b border-border/70 px-4 py-4">
            <div className="flex items-center gap-3">
              <AssistantAvatar src={bootstrap.avatarSrc} alt={bootstrap.assistantName} sizeClassName="h-11 w-11" />
              <div>
                <p className="text-base font-semibold text-foreground">{bootstrap.assistantName}</p>
                <p className="text-xs text-muted-foreground">Text support</p>
              </div>
            </div>
            <button
              type="button"
              onClick={() => setIsOpen(false)}
              className="inline-flex h-10 w-10 items-center justify-center rounded-full border border-border bg-background text-foreground transition hover:border-primary/50 hover:text-primary focus-visible:outline-none focus-visible:ring-4 focus-visible:ring-primary/20"
              aria-label="Close chat"
            >
              <X className="h-4 w-4" />
            </button>
          </div>

          {!profile ? (
            <div className="min-h-0 overflow-y-auto px-4 py-4">
              <form onSubmit={handleProfileSubmit} className="space-y-4">
                <div className="rounded-[1.5rem] border border-border/70 bg-background/80 p-4 shadow-sm">
                  <p className="text-sm font-medium text-foreground">Start with your details</p>
                  <p className="mt-1 text-xs leading-relaxed text-muted-foreground">
                    We use this to route the conversation to the right team member.
                  </p>

                  <div className="mt-4 space-y-4">
                    <FormInput
                      id="site-chat-name"
                      label="Name"
                      value={profileDraft.name}
                      onChange={(event) => setProfileDraft((current) => ({ ...current, name: event.target.value }))}
                      autoComplete="name"
                      required
                    />
                    <FormInput
                      id="site-chat-phone"
                      label="Phone"
                      value={profileDraft.phone}
                      onChange={(event) => setProfileDraft((current) => ({ ...current, phone: event.target.value }))}
                      autoComplete="tel"
                      inputMode="tel"
                      type="tel"
                      required
                    />
                    <FormInput
                      id="site-chat-email"
                      label="Email"
                      value={profileDraft.email}
                      onChange={(event) => setProfileDraft((current) => ({ ...current, email: event.target.value }))}
                      autoComplete="email"
                      inputMode="email"
                      type="email"
                      required
                    />
                    <FormSelect
                      id="site-chat-intent"
                      label="Intent"
                      value={profileDraft.intent}
                      onChange={(event) => setProfileDraft((current) => ({ ...current, intent: event.target.value }))}
                      options={intentOptions}
                      placeholder="Choose one"
                      required
                    />
                  </div>
                </div>

                <div className="rounded-[1.5rem] border border-border/70 bg-background/80 p-4 shadow-sm">
                  <p className="text-sm font-medium text-foreground">Text updates</p>
                  <p className="mt-1 text-xs leading-relaxed text-muted-foreground">
                    Required service consent covers scheduling, support, repairs, moving, and follow-up texts for this request.
                  </p>
                  <div className="mt-4">
                    <SmsConsentFields
                      idPrefix="site-chat"
                      mode="chat"
                      serviceChecked={profileDraft.serviceTextConsent}
                      marketingChecked={profileDraft.marketingTextConsent}
                      onServiceChange={(checked) =>
                        setProfileDraft((current) => ({
                          ...current,
                          serviceTextConsent: checked,
                          consentVersion: SMS_CONSENT_VERSION,
                          consentSourcePage: pathname || "/",
                        }))
                      }
                      onMarketingChange={() => undefined}
                      serviceError={profileError && !profileDraft.serviceTextConsent ? profileError : undefined}
                    />
                  </div>
                </div>

                <div className="flex flex-col gap-2 sm:flex-row">
                  <button
                    type="submit"
                    disabled={!profileDraftIsReady}
                    className="inline-flex min-h-11 flex-1 items-center justify-center gap-2 rounded-full bg-primary px-4 text-sm font-medium text-primary-foreground transition hover:bg-primary/90 disabled:cursor-not-allowed disabled:opacity-60"
                  >
                    <MessageSquare className="h-4 w-4" />
                    Start chat
                  </button>

                  <a
                    href={bootstrap.callUrl}
                    className="inline-flex min-h-11 items-center justify-center gap-2 rounded-full border border-border bg-background px-4 text-sm font-medium text-foreground transition hover:border-primary/50 hover:text-primary"
                  >
                    <Phone className="h-4 w-4" />
                    Call
                  </a>
                </div>

                <SupportHint
                  formHref={formHref}
                  formLabel={formLabel}
                  intent={activeIntent}
                  smsNumber={bootstrap.smsNumber}
                  smsUrl={bootstrap.smsUrl}
                />
              </form>

              {profileError ? (
                <div className="mt-3 rounded-2xl border border-destructive/20 bg-destructive/5 px-3 py-3 text-sm text-destructive">
                  <div className="flex items-start gap-2">
                    <AlertCircle className="mt-0.5 h-4 w-4 shrink-0" />
                    <p>{profileError}</p>
                  </div>
                </div>
              ) : null}
            </div>
          ) : (
            <>
              <div className="flex items-center justify-between border-b border-border/60 bg-muted/30 px-4 py-3 text-xs text-muted-foreground">
                <span>
                  Chatting as <span className="font-medium text-foreground">{profile.name}</span>
                </span>
                <button
                  type="button"
                  onClick={handleProfileReset}
                  className="inline-flex items-center gap-1 font-medium text-foreground transition hover:text-primary"
                >
                  <SquarePen className="h-3.5 w-3.5" />
                  Edit details
                </button>
              </div>

              <div className="max-h-[22rem] overflow-y-auto px-4 py-4">
                <div className="space-y-3">
                  {messages.map((message) => (
                    <div key={message.id} className="space-y-1">
                      <div className="text-[11px] font-medium uppercase tracking-[0.12em] text-muted-foreground">
                        {message.role === "assistant" ? bootstrap.assistantName : profile.name}
                      </div>
                      <div
                        className={cn(
                          "max-w-[92%] rounded-2xl px-3 py-2 text-sm shadow-sm",
                          message.role === "assistant"
                            ? "bg-muted text-foreground"
                            : "ml-auto bg-primary text-primary-foreground",
                        )}
                      >
                        {message.content}
                      </div>
                    </div>
                  ))}

                  <div ref={messagesEndRef} />
                </div>
              </div>

              <div className="border-t border-border/70 bg-background/95 px-4 py-4">
                <form onSubmit={handleSubmit} className="space-y-3">
                  <label htmlFor="site-chat-input" className="text-sm font-semibold text-foreground">
                    Message
                  </label>

                  <textarea
                    id="site-chat-input"
                    data-testid="site-chat-input"
                    value={draft}
                    onChange={(event) => setDraft(event.target.value.slice(0, SITE_CHAT_MAX_INPUT_CHARS))}
                    placeholder="Describe what you need"
                    rows={3}
                    disabled={isSending}
                    className="min-h-24 w-full rounded-2xl border border-border/70 bg-background px-4 py-3 text-sm text-foreground outline-none transition placeholder:text-muted-foreground focus:border-primary focus:ring-4 focus:ring-primary/15 disabled:cursor-not-allowed disabled:opacity-60"
                  />

                  <SupportHint
                    formHref={formHref}
                    formLabel={formLabel}
                    intent={profile.intent}
                    smsNumber={bootstrap.smsNumber}
                    smsUrl={bootstrap.smsUrl}
                  />

                  <div className="flex flex-col gap-2 sm:flex-row">
                    <button
                      type="submit"
                      data-testid="site-chat-send"
                      disabled={isSending || !draft.trim()}
                      className="inline-flex min-h-11 flex-1 items-center justify-center gap-2 rounded-full bg-primary px-4 text-sm font-medium text-primary-foreground transition hover:bg-primary/90 disabled:cursor-not-allowed disabled:opacity-60"
                    >
                      {isSending ? <Loader2 className="h-4 w-4 animate-spin" /> : <MessageSquare className="h-4 w-4" />}
                      {isSending ? "Sending..." : "Send"}
                    </button>

                    <a
                      href={bootstrap.callUrl}
                      className="inline-flex min-h-11 items-center justify-center gap-2 rounded-full border border-border bg-background px-4 text-sm font-medium text-foreground transition hover:border-primary/50 hover:text-primary"
                    >
                      <Phone className="h-4 w-4" />
                      Call
                    </a>
                  </div>
                </form>

                {error ? (
                  <div className="mt-3 rounded-2xl border border-destructive/20 bg-destructive/5 px-3 py-3 text-sm text-destructive">
                    <div className="flex items-start gap-2">
                      <AlertCircle className="mt-0.5 h-4 w-4 shrink-0" />
                      <p>{error}</p>
                    </div>
                  </div>
                ) : null}
              </div>
            </>
          )}
        </div>
      ) : null}

      {!isOpen ? (
        <button
          type="button"
          data-testid="site-chat-launcher"
          onClick={() => setIsOpen(true)}
          className="pointer-events-auto inline-flex h-14 w-14 items-center justify-center rounded-full border border-white/70 bg-background/95 shadow-[0_20px_60px_rgba(0,0,0,0.18)] transition hover:-translate-y-0.5 hover:shadow-[0_24px_68px_rgba(0,0,0,0.22)] focus-visible:outline-none focus-visible:ring-4 focus-visible:ring-primary/20"
          aria-label={`Open chat with ${bootstrap.assistantName}`}
        >
          <AssistantAvatar src={bootstrap.avatarSrc} alt={bootstrap.assistantName} sizeClassName="h-12 w-12" />
        </button>
      ) : null}
    </div>
  )
}
