"use client"

import type React from "react"
import { useEffect, useRef, useState } from "react"
import Link from "next/link"
import { ArrowLeft, ImagePlus, Lock, Send, Trash2, X } from "lucide-react"
import { Button } from "@/components/ui/button"
import { cn } from "@/lib/utils"

// --- Types (matcher API-kontrakten i app/routers/messaging.py) -------------

type ApiMessage = {
  id: string
  author_user_id: string
  author_display_name: string
  body: string | null
  image_url: string | null
  created_at: string
}

const TIME_FMT = new Intl.DateTimeFormat("no-NO", { hour: "2-digit", minute: "2-digit" })

function wsUrl(path: string): string {
  const protocol = window.location.protocol === "https:" ? "wss:" : "ws:"
  return `${protocol}//${window.location.host}${path}`
}

export function TeamChat({
  organizationId,
  tournamentId,
  teamId,
  teamName,
  tournamentName,
}: {
  organizationId: string
  tournamentId: string
  teamId: string
  teamName: string
  tournamentName: string
}) {
  const [currentUserId, setCurrentUserId] = useState<string | null>(null)
  const [messages, setMessages] = useState<ApiMessage[]>([])
  const [loading, setLoading] = useState(true)
  const [accessError, setAccessError] = useState<string | null>(null)
  const [error, setError] = useState<string | null>(null)
  const [text, setText] = useState("")
  const [image, setImage] = useState<File | null>(null)
  const [sending, setSending] = useState(false)
  const bottomRef = useRef<HTMLDivElement>(null)
  const fileInputRef = useRef<HTMLInputElement>(null)

  useEffect(() => {
    let cancelled = false
    async function load() {
      try {
        const [meRes, messagesRes] = await Promise.all([
          fetch("/auth/me", { credentials: "include" }),
          fetch(`/orgs/${organizationId}/teams/${teamId}/messages`, { credentials: "include" }),
        ])
        if (meRes.ok) {
          const me: { id: string } = await meRes.json()
          if (!cancelled) setCurrentUserId(me.id)
        }
        if (messagesRes.status === 403) {
          if (!cancelled) {
            setAccessError(
              "Du er ikke rostret på dette laget -- lagchatten er privat, kun for spillerne på laget (ikke engang organisasjonens eiere/administratorer har tilgang).",
            )
          }
          return
        }
        if (!messagesRes.ok) throw new Error(`messages: ${messagesRes.status}`)
        const data: ApiMessage[] = await messagesRes.json()
        if (!cancelled) setMessages(data)
      } catch {
        if (!cancelled) setAccessError("Klarte ikke å laste chatten. Prøv å laste siden på nytt.")
      } finally {
        if (!cancelled) setLoading(false)
      }
    }
    void load()
    return () => {
      cancelled = true
    }
  }, [organizationId, teamId])

  useEffect(() => {
    if (accessError) return
    const socket = new WebSocket(wsUrl(`/ws/orgs/${organizationId}/teams/${teamId}/messages`))
    socket.onmessage = (event) => {
      try {
        const msg: ApiMessage = JSON.parse(event.data)
        setMessages((prev) => (prev.some((m) => m.id === msg.id) ? prev : [...prev, msg]))
      } catch {
        // ignorer ugyldig payload
      }
    }
    return () => socket.close()
  }, [organizationId, teamId, accessError])

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

  async function send(e: React.FormEvent) {
    e.preventDefault()
    if (!text.trim() && !image) return
    setSending(true)
    setError(null)
    try {
      const form = new FormData()
      if (text.trim()) form.set("body", text.trim())
      if (image) form.set("image", image)
      const res = await fetch(`/orgs/${organizationId}/teams/${teamId}/messages`, {
        method: "POST",
        credentials: "include",
        body: form,
      })
      if (!res.ok) throw new Error(`send: ${res.status}`)
      const msg: ApiMessage = await res.json()
      setMessages((prev) => (prev.some((m) => m.id === msg.id) ? prev : [...prev, msg]))
      setText("")
      setImage(null)
      if (fileInputRef.current) fileInputRef.current.value = ""
    } catch {
      setError("Klarte ikke å sende meldingen. Prøv igjen.")
    } finally {
      setSending(false)
    }
  }

  async function remove(messageId: string) {
    setError(null)
    try {
      const res = await fetch(`/orgs/${organizationId}/teams/${teamId}/messages/${messageId}`, {
        method: "DELETE",
        credentials: "include",
      })
      if (!res.ok && res.status !== 204) throw new Error(`delete: ${res.status}`)
      setMessages((prev) => prev.filter((m) => m.id !== messageId))
    } catch {
      setError("Klarte ikke å slette meldingen. Prøv igjen.")
    }
  }

  const backHref = `/tournaments/${tournamentId}?org=${organizationId}&name=${encodeURIComponent(tournamentName)}`

  return (
    <div className="flex min-h-[100dvh] flex-col bg-background">
      <header className="sticky top-0 z-10 border-b border-border bg-background/80 backdrop-blur">
        <div className="mx-auto flex w-full max-w-2xl items-center gap-3 px-5 py-4">
          <Link
            href={backHref}
            aria-label="Tilbake til lag og spillere"
            className="flex size-10 shrink-0 items-center justify-center rounded-xl border border-border bg-card text-muted-foreground transition-colors hover:bg-accent/50 hover:text-foreground"
          >
            <ArrowLeft aria-hidden="true" className="size-5" />
          </Link>
          <div className="flex min-w-0 flex-1 flex-col">
            <span className="flex items-center gap-1.5 text-xs font-semibold uppercase tracking-wide text-muted-foreground">
              <Lock aria-hidden="true" className="size-3" />
              Privat lagchat
            </span>
            <h1 className="truncate text-xl font-extrabold tracking-tight text-foreground">{teamName}</h1>
          </div>
        </div>
      </header>

      {loading ? (
        <div className="flex flex-1 items-center justify-center">
          <div
            aria-hidden="true"
            className="size-10 animate-spin rounded-full border-4 border-primary/20 border-t-primary"
          />
        </div>
      ) : accessError ? (
        <div className="flex flex-1 flex-col items-center justify-center gap-3 px-5 text-center">
          <div className="flex size-14 items-center justify-center rounded-2xl bg-muted">
            <Lock aria-hidden="true" className="size-7 text-muted-foreground" />
          </div>
          <p className="max-w-sm text-sm leading-relaxed text-muted-foreground text-pretty">{accessError}</p>
        </div>
      ) : (
        <>
          <main className="mx-auto flex w-full max-w-2xl flex-1 flex-col gap-3 px-5 py-6">
            {messages.length === 0 && (
              <p className="mt-8 text-center text-sm text-muted-foreground">
                Ingen meldinger ennå -- her er kun laget deres, ingen andre kan lese med.
              </p>
            )}
            {messages.map((m) => {
              const own = m.author_user_id === currentUserId
              return (
                <div key={m.id} className={cn("flex flex-col gap-1", own ? "items-end" : "items-start")}>
                  <div
                    className={cn(
                      "group relative max-w-[80%] rounded-2xl px-4 py-2.5 shadow-sm shadow-black/5",
                      own ? "bg-primary text-primary-foreground" : "border border-border bg-card text-foreground",
                    )}
                  >
                    {!own && (
                      <span className="mb-0.5 block text-xs font-bold opacity-70">{m.author_display_name}</span>
                    )}
                    {m.image_url && (
                      // eslint-disable-next-line @next/next/no-img-element -- images.unoptimized er alt satt
                      <img
                        src={m.image_url}
                        alt=""
                        className="mb-1.5 max-h-64 w-full rounded-xl object-cover"
                      />
                    )}
                    {m.body && <p className="text-[15px] leading-relaxed text-pretty">{m.body}</p>}
                    {own && (
                      <button
                        type="button"
                        onClick={() => remove(m.id)}
                        aria-label="Slett melding"
                        className="absolute -left-9 top-1/2 flex size-7 -translate-y-1/2 items-center justify-center rounded-lg text-muted-foreground opacity-0 transition-opacity hover:text-destructive group-hover:opacity-100"
                      >
                        <Trash2 aria-hidden="true" className="size-4" />
                      </button>
                    )}
                  </div>
                  <span className="px-1 text-[11px] text-muted-foreground">
                    {TIME_FMT.format(new Date(m.created_at))}
                  </span>
                </div>
              )
            })}
            <div ref={bottomRef} />
          </main>

          <div className="sticky bottom-0 border-t border-border bg-background/95 backdrop-blur">
            <form onSubmit={send} className="mx-auto flex w-full max-w-2xl flex-col gap-2 px-5 py-3">
              {error && (
                <p role="alert" className="text-xs font-medium text-destructive">
                  {error}
                </p>
              )}
              {image && (
                <div className="flex items-center gap-2 self-start rounded-xl bg-muted px-3 py-1.5 text-xs font-medium text-foreground">
                  {image.name}
                  <button
                    type="button"
                    onClick={() => {
                      setImage(null)
                      if (fileInputRef.current) fileInputRef.current.value = ""
                    }}
                    aria-label="Fjern bilde"
                  >
                    <X aria-hidden="true" className="size-3.5" />
                  </button>
                </div>
              )}
              <div className="flex items-center gap-2">
                <input
                  ref={fileInputRef}
                  type="file"
                  accept="image/jpeg,image/png,image/webp,image/gif"
                  className="hidden"
                  onChange={(e) => setImage(e.target.files?.[0] ?? null)}
                />
                <Button
                  type="button"
                  variant="ghost"
                  size="icon"
                  onClick={() => fileInputRef.current?.click()}
                  aria-label="Legg ved bilde"
                  className="size-11 shrink-0 rounded-2xl text-muted-foreground"
                >
                  <ImagePlus aria-hidden="true" className="size-5" />
                </Button>
                <input
                  value={text}
                  onChange={(e) => setText(e.target.value)}
                  placeholder="Skriv en melding …"
                  className="h-11 flex-1 rounded-2xl border border-input bg-background px-4 text-base outline-none focus-visible:ring-2 focus-visible:ring-ring"
                />
                <Button
                  type="submit"
                  size="icon"
                  disabled={sending || (!text.trim() && !image)}
                  aria-label="Send"
                  className="size-11 shrink-0 rounded-2xl"
                >
                  <Send aria-hidden="true" className="size-5" />
                </Button>
              </div>
            </form>
          </div>
        </>
      )}
    </div>
  )
}
