"use client"

// Medlemsstyring (ADR-022): invitere, endre rolle, fjerne/forlate. Rolle-
// grensene håndheves også server-side (app/routers/organizations.py) --
// UI-et her skjuler bare handlinger som uansett ville blitt avvist, for en
// tydeligere opplevelse, ikke som eneste håndhevelse.

import type React from "react"
import { useEffect, useState } from "react"
import Link from "next/link"
import { ArrowLeft, Mail, Trash2, UserPlus, Users } from "lucide-react"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"

type Role = "owner" | "admin" | "member"

type Membership = {
  id: string
  user_id: string
  email: string
  display_name: string
  role: Role
}

type Invitation = {
  id: string
  email: string
  role: Role
  expires_at: string
}

const ROLE_LABELS: Record<Role, string> = { owner: "Eier", admin: "Administrator", member: "Medlem" }

export function OrgMembers({ organizationId, orgName }: { organizationId: string; orgName: string }) {
  const [myUserId, setMyUserId] = useState<string | null>(null)
  const [myRole, setMyRole] = useState<Role | null>(null)
  const [members, setMembers] = useState<Membership[]>([])
  const [invitations, setInvitations] = useState<Invitation[]>([])
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState<string | null>(null)

  async function loadAll() {
    try {
      const [meRes, membersRes, invitationsRes] = await Promise.all([
        fetch("/auth/me", { credentials: "include" }),
        fetch(`/orgs/${organizationId}/memberships`, { credentials: "include" }),
        fetch(`/orgs/${organizationId}/invitations`, { credentials: "include" }),
      ])
      if (meRes.ok) {
        const me: { id: string; organizations: { organization_id: string; role: Role }[] } = await meRes.json()
        setMyUserId(me.id)
        setMyRole(me.organizations.find((o) => o.organization_id === organizationId)?.role ?? null)
      }
      if (membersRes.ok) setMembers(await membersRes.json())
      if (invitationsRes.ok) setInvitations(await invitationsRes.json())
    } catch {
      setError("Klarte ikke å laste medlemmer. Prøv å laste siden på nytt.")
    } finally {
      setLoading(false)
    }
  }

  useEffect(() => {
    void loadAll()
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [organizationId])

  async function inviteMember(email: string, role: Role) {
    setError(null)
    try {
      const res = await fetch(`/orgs/${organizationId}/invitations`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        credentials: "include",
        body: JSON.stringify({ email, role }),
      })
      if (!res.ok) {
        const body = await res.json().catch(() => null)
        throw new Error(body?.detail?.message ?? "Klarte ikke å sende invitasjonen.")
      }
      const created: Invitation = await res.json()
      setInvitations((prev) => [created, ...prev])
    } catch (err) {
      setError(err instanceof Error ? err.message : "Klarte ikke å sende invitasjonen.")
    }
  }

  async function revokeInvitation(id: string) {
    const res = await fetch(`/orgs/${organizationId}/invitations/${id}`, {
      method: "DELETE",
      credentials: "include",
    })
    if (res.ok || res.status === 204) {
      setInvitations((prev) => prev.filter((i) => i.id !== id))
    }
  }

  async function changeRole(membershipId: string, role: Role) {
    setError(null)
    try {
      const res = await fetch(`/orgs/${organizationId}/memberships/${membershipId}`, {
        method: "PATCH",
        headers: { "Content-Type": "application/json" },
        credentials: "include",
        body: JSON.stringify({ role }),
      })
      if (!res.ok) {
        const body = await res.json().catch(() => null)
        throw new Error(body?.detail?.message ?? "Klarte ikke å endre rollen.")
      }
      const updated: Membership = await res.json()
      setMembers((prev) => prev.map((m) => (m.id === updated.id ? updated : m)))
    } catch (err) {
      setError(err instanceof Error ? err.message : "Klarte ikke å endre rollen.")
    }
  }

  async function removeMember(membershipId: string, isSelf: boolean) {
    const confirmMsg = isSelf
      ? "Er du sikker på at du vil forlate organisasjonen?"
      : "Er du sikker på at du vil fjerne dette medlemmet?"
    if (!confirm(confirmMsg)) return
    setError(null)
    try {
      const res = await fetch(`/orgs/${organizationId}/memberships/${membershipId}`, {
        method: "DELETE",
        credentials: "include",
      })
      if (!res.ok && res.status !== 204) {
        const body = await res.json().catch(() => null)
        throw new Error(body?.detail?.message ?? "Klarte ikke å fjerne medlemmet.")
      }
      setMembers((prev) => prev.filter((m) => m.id !== membershipId))
      if (isSelf) window.location.href = "/dashboard"
    } catch (err) {
      setError(err instanceof Error ? err.message : "Klarte ikke å fjerne medlemmet.")
    }
  }

  const canInvite = myRole === "owner" || myRole === "admin"
  const inviteRoleOptions: Role[] = myRole === "owner" ? ["member", "admin", "owner"] : ["member"]

  if (loading) {
    return (
      <div className="flex min-h-[100dvh] flex-col items-center justify-center bg-background">
        <div
          aria-hidden="true"
          className="size-10 animate-spin rounded-full border-4 border-primary/20 border-t-primary"
        />
      </div>
    )
  }

  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="/dashboard"
            aria-label="Tilbake til dashbord"
            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-col">
            <span className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">
              Medlemmer
            </span>
            <h1 className="truncate text-xl font-extrabold tracking-tight text-foreground">{orgName}</h1>
          </div>
        </div>
      </header>

      <main className="mx-auto w-full max-w-2xl flex-1 px-5 py-6 sm:py-8">
        {error && (
          <p role="alert" className="mb-4 text-sm font-medium text-destructive">
            {error}
          </p>
        )}

        {canInvite && <InviteForm roleOptions={inviteRoleOptions} onInvite={inviteMember} />}

        <section className="mt-6 flex flex-col gap-3">
          <h2 className="flex items-center gap-2 text-sm font-bold uppercase tracking-wide text-muted-foreground">
            <Users aria-hidden="true" className="size-4" />
            Medlemmer ({members.length})
          </h2>
          {members.map((m) => (
            <MemberRow
              key={m.id}
              member={m}
              isSelf={m.user_id === myUserId}
              canManage={myRole === "owner"}
              onChangeRole={changeRole}
              onRemove={removeMember}
            />
          ))}
        </section>

        {invitations.length > 0 && (
          <section className="mt-6 flex flex-col gap-3">
            <h2 className="flex items-center gap-2 text-sm font-bold uppercase tracking-wide text-muted-foreground">
              <Mail aria-hidden="true" className="size-4" />
              Ventende invitasjoner ({invitations.length})
            </h2>
            {invitations.map((inv) => (
              <div
                key={inv.id}
                className="flex items-center justify-between gap-3 rounded-2xl border border-dashed border-border bg-card/50 p-4"
              >
                <div className="flex flex-col">
                  <span className="text-sm font-semibold text-foreground">{inv.email}</span>
                  <span className="text-xs text-muted-foreground">Invitert som {ROLE_LABELS[inv.role]}</span>
                </div>
                {(myRole === "owner" || (myRole === "admin" && inv.role === "member")) && (
                  <button
                    type="button"
                    onClick={() => void revokeInvitation(inv.id)}
                    aria-label={`Opphev invitasjon til ${inv.email}`}
                    className="flex size-9 items-center justify-center rounded-lg text-muted-foreground transition-colors hover:bg-accent/60 hover:text-destructive"
                  >
                    <Trash2 aria-hidden="true" className="size-4" />
                  </button>
                )}
              </div>
            ))}
          </section>
        )}
      </main>
    </div>
  )
}

function InviteForm({
  roleOptions,
  onInvite,
}: {
  roleOptions: Role[]
  onInvite: (email: string, role: Role) => void
}) {
  const [email, setEmail] = useState("")
  const [role, setRole] = useState<Role>(roleOptions[0])
  const [sending, setSending] = useState(false)

  async function handleSubmit(e: React.FormEvent) {
    e.preventDefault()
    if (!email.trim() || sending) return
    setSending(true)
    try {
      await onInvite(email.trim(), role)
      setEmail("")
    } finally {
      setSending(false)
    }
  }

  return (
    <form
      onSubmit={handleSubmit}
      className="flex flex-col gap-3 rounded-3xl border border-border bg-card p-4 shadow-sm shadow-black/5 sm:flex-row sm:items-end sm:p-5"
    >
      <div className="flex flex-1 flex-col gap-1.5">
        <Label htmlFor="invite-email" className="text-sm font-semibold">
          Inviter noen
        </Label>
        <Input
          id="invite-email"
          type="email"
          placeholder="epost@eksempel.no"
          value={email}
          onChange={(e) => setEmail(e.target.value)}
          className="h-11 rounded-xl"
        />
      </div>
      <div className="flex flex-col gap-1.5">
        <Label htmlFor="invite-role" className="text-sm font-semibold">
          Rolle
        </Label>
        <select
          id="invite-role"
          value={role}
          onChange={(e) => setRole(e.target.value as Role)}
          className="h-11 rounded-xl border border-border bg-card px-3 text-sm font-medium text-foreground outline-none focus-visible:ring-2 focus-visible:ring-ring"
        >
          {roleOptions.map((r) => (
            <option key={r} value={r}>
              {ROLE_LABELS[r]}
            </option>
          ))}
        </select>
      </div>
      <Button type="submit" disabled={!email.trim() || sending} className="h-11 shrink-0 rounded-xl font-semibold">
        <UserPlus aria-hidden="true" className="size-4" />
        {sending ? "Sender …" : "Inviter"}
      </Button>
    </form>
  )
}

function MemberRow({
  member,
  isSelf,
  canManage,
  onChangeRole,
  onRemove,
}: {
  member: Membership
  isSelf: boolean
  canManage: boolean
  onChangeRole: (id: string, role: Role) => void
  onRemove: (id: string, isSelf: boolean) => void
}) {
  // Selvbetjent nedgradering (aldri oppgradering, se app/routers/organizations.py)
  // -- viser kun rollene som faktisk er lavere enn nåværende for egen rad når
  // brukeren ikke er owner (owner kan endre fritt).
  const rank: Record<Role, number> = { member: 0, admin: 1, owner: 2 }
  const roleOptionsForRow: Role[] = canManage
    ? ["owner", "admin", "member"]
    : isSelf
      ? (["owner", "admin", "member"] as Role[]).filter((r) => rank[r] <= rank[member.role])
      : []
  const canEditRole = canManage || (isSelf && roleOptionsForRow.length > 1)
  const canRemove = canManage || isSelf

  return (
    <div className="flex items-center justify-between gap-3 rounded-2xl border border-border bg-card p-4 shadow-sm shadow-black/5">
      <div className="flex min-w-0 flex-col">
        <span className="truncate text-sm font-semibold text-foreground">
          {member.display_name}
          {isSelf && <span className="ml-1.5 text-xs font-medium text-muted-foreground">(deg)</span>}
        </span>
        <span className="truncate text-xs text-muted-foreground">{member.email}</span>
      </div>
      <div className="flex shrink-0 items-center gap-2">
        {canEditRole ? (
          <select
            value={member.role}
            onChange={(e) => onChangeRole(member.id, e.target.value as Role)}
            className="h-9 rounded-lg border border-border bg-card px-2 text-xs font-semibold text-foreground outline-none focus-visible:ring-2 focus-visible:ring-ring"
          >
            {roleOptionsForRow.map((r) => (
              <option key={r} value={r}>
                {ROLE_LABELS[r]}
              </option>
            ))}
          </select>
        ) : (
          <span className="rounded-full bg-secondary px-2.5 py-1 text-xs font-semibold text-secondary-foreground">
            {ROLE_LABELS[member.role]}
          </span>
        )}
        {canRemove && (
          <button
            type="button"
            onClick={() => onRemove(member.id, isSelf)}
            aria-label={isSelf ? "Forlat organisasjonen" : `Fjern ${member.display_name}`}
            className="flex size-9 items-center justify-center rounded-lg text-muted-foreground transition-colors hover:bg-accent/60 hover:text-destructive"
          >
            <Trash2 aria-hidden="true" className="size-4" />
          </button>
        )}
      </div>
    </div>
  )
}
