"use client";

import * as React from "react";
import { useParams } from "next/navigation";
import { useSession } from "next-auth/react";

// Membership-derived role drives which surfaces render (Invite button,
// pending-invites section, kebab menus). The server enforces the same
// rules on every mutation regardless of what the UI shows.
import { Copy, Loader2, MailCheck, MoreHorizontal, Trash2, UserCog } from "lucide-react";

import { cn } from "@/lib/utils";
import { api } from "@/lib/trpc";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Card, CardContent } from "@/components/ui/card";
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuLabel,
  DropdownMenuSeparator,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { InviteDialog } from "@/components/teams/invite-dialog";

type WorkspaceRole = "owner" | "admin" | "member";

function memberInitials(name: string | null | undefined, email: string) {
  const n = name?.trim();
  if (n) return n.slice(0, 1).toUpperCase();
  return email.trim().slice(0, 1).toUpperCase();
}

function formatRoleLabel(role: string) {
  const key = role.toLowerCase();
  const labels: Record<string, string> = {
    owner: "Owner",
    admin: "Admin",
    member: "Member",
  };
  return labels[key] ?? role.charAt(0).toUpperCase() + role.slice(1).toLowerCase();
}

function relativeFromNow(when: Date | string | null | undefined): string {
  if (!when) return "—";
  const target = when instanceof Date ? when.getTime() : new Date(when).getTime();
  const diff = target - Date.now();
  if (Number.isNaN(diff)) return "—";
  const sign = diff < 0 ? "ago" : "from now";
  const abs = Math.abs(diff);
  const min = Math.floor(abs / 60_000);
  if (min < 60) return `${min}m ${sign}`;
  const hr = Math.floor(min / 60);
  if (hr < 24) return `${hr}h ${sign}`;
  const day = Math.floor(hr / 24);
  return `${day}d ${sign}`;
}

function MemberCardSkeleton({ className }: { className?: string }) {
  return (
    <Card className={cn("overflow-hidden", className)}>
      <CardContent className="flex items-center gap-4 p-6">
        <div className="size-10 shrink-0 animate-pulse rounded-full bg-muted" />
        <div className="min-w-0 flex-1 space-y-2">
          <div className="h-4 w-32 animate-pulse rounded-md bg-muted" />
          <div className="h-3 w-48 max-w-full animate-pulse rounded-md bg-muted" />
        </div>
        <div className="h-5 w-16 shrink-0 animate-pulse rounded-full bg-muted" />
      </CardContent>
    </Card>
  );
}

export default function TeamsPage() {
  const params = useParams();
  const utils = api.useUtils();
  const rawSlug = params?.workspaceSlug;
  const workspaceSlug = typeof rawSlug === "string" ? rawSlug : undefined;

  const enabled = Boolean(workspaceSlug);
  const membersQuery = api.workspaces.listMembers.useQuery(
    { workspace: workspaceSlug as string },
    { enabled },
  );

  // Caller's role lives on the members query — that's the source of truth for
  // who's in this workspace and at what level. resolve() returns the workspace
  // itself but not the membership-side role, so we derive it locally instead
  // of round-tripping a second procedure.
  const currentUserId = useSession().data?.user?.id;
  const callerRole = membersQuery.data?.find((m) => m.id === currentUserId)?.role as
    | WorkspaceRole
    | undefined;
  const canManage = callerRole === "owner" || callerRole === "admin";

  const invitesQuery = api.invites.list.useQuery(
    { workspace: workspaceSlug as string },
    { enabled: enabled && canManage },
  );

  const revokeMut = api.invites.revoke.useMutation({
    onSuccess: () => utils.invites.list.invalidate({ workspace: workspaceSlug }),
  });
  const updateRoleMut = api.workspaces.updateMemberRole.useMutation({
    onSuccess: () => utils.workspaces.listMembers.invalidate({ workspace: workspaceSlug }),
  });
  const removeMemberMut = api.workspaces.removeMember.useMutation({
    onSuccess: () => utils.workspaces.listMembers.invalidate({ workspace: workspaceSlug }),
  });

  const [copyFlash, setCopyFlash] = React.useState<string | null>(null);
  const copyInviteLink = async (token: string) => {
    const url = `${window.location.origin}/invite/${token}`;
    try {
      await navigator.clipboard.writeText(url);
      setCopyFlash(token);
      window.setTimeout(() => setCopyFlash(null), 1500);
    } catch {
      window.prompt("Copy this invite link:", url);
    }
  };

  if (!workspaceSlug) {
    return <p className="p-10 text-sm text-muted-foreground">Missing workspace.</p>;
  }

  const members = membersQuery.data ?? [];
  const ownerCount = members.filter((m) => m.role === "owner").length;

  return (
    <div className="mx-auto max-w-5xl px-8 py-10">
      <div className="mb-8 flex flex-wrap items-center justify-between gap-4">
        <h1 className="text-3xl font-bold tracking-tight">Teams</h1>
        {canManage ? <InviteDialog workspaceSlug={workspaceSlug} /> : null}
      </div>

      {/* --- Pending invites (admin/owner only) --- */}
      {canManage ? (
        <section className="mb-10">
          <div className="mb-3 flex items-center gap-2">
            <MailCheck className="size-4 text-muted-foreground" aria-hidden />
            <h2 className="text-sm font-semibold uppercase tracking-wide text-muted-foreground">
              Pending invites
            </h2>
          </div>
          {invitesQuery.isLoading ? (
            <p className="text-sm text-muted-foreground">Loading…</p>
          ) : !invitesQuery.data?.length ? (
            <p className="text-sm text-muted-foreground">
              No pending invites. Use the Invite button to add someone.
            </p>
          ) : (
            <ul className="space-y-2">
              {invitesQuery.data.map((inv) => (
                <li
                  key={inv.id}
                  className="flex items-center justify-between gap-4 rounded-md border border-border bg-card px-4 py-3 shadow-sm"
                >
                  <div className="min-w-0">
                    <p className="truncate text-sm font-medium">{inv.email}</p>
                    <p className="text-xs text-muted-foreground">
                      Invited as {formatRoleLabel(inv.role)} ·{" "}
                      <span title={new Date(inv.expiresAt).toLocaleString()}>
                        expires {relativeFromNow(inv.expiresAt)}
                      </span>
                    </p>
                  </div>
                  <div className="flex shrink-0 items-center gap-2">
                    <Button
                      type="button"
                      variant="outline"
                      size="sm"
                      onClick={() => copyInviteLink(inv.token)}
                    >
                      <Copy className="size-3.5" aria-hidden />
                      {copyFlash === inv.token ? "Copied" : "Copy link"}
                    </Button>
                    <Button
                      type="button"
                      variant="ghost"
                      size="sm"
                      onClick={() => revokeMut.mutate({ inviteId: inv.id })}
                      disabled={revokeMut.isPending}
                      className="text-destructive hover:bg-destructive/10 hover:text-destructive"
                    >
                      Revoke
                    </Button>
                  </div>
                </li>
              ))}
            </ul>
          )}
        </section>
      ) : null}

      {/* --- Members --- */}
      <div className="mb-3 flex items-center gap-2">
        <UserCog className="size-4 text-muted-foreground" aria-hidden />
        <h2 className="text-sm font-semibold uppercase tracking-wide text-muted-foreground">
          Members
        </h2>
      </div>
      {membersQuery.isLoading ? (
        <div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
          {Array.from({ length: 6 }).map((_, i) => (
            <MemberCardSkeleton key={i} />
          ))}
        </div>
      ) : !members.length ? (
        <div className="rounded-lg border border-dashed border-border bg-muted/30 p-12 text-center text-sm text-muted-foreground">
          No members in this workspace yet.
        </div>
      ) : (
        <div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
          {members.map((m) => {
            const displayName = m.name?.trim() || m.email;
            const isSelf = m.id === currentUserId;
            const isLastOwner = m.role === "owner" && ownerCount <= 1;
            const showActions = canManage && !isSelf;
            return (
              <Card key={m.id} className="overflow-hidden">
                <CardContent className="flex items-center gap-4 p-6">
                  <Avatar className="size-10 shrink-0">
                    {m.avatarUrl ? <AvatarImage src={m.avatarUrl} alt="" /> : null}
                    <AvatarFallback>
                      {memberInitials(m.name, m.email)}
                    </AvatarFallback>
                  </Avatar>
                  <div className="min-w-0 flex-1">
                    <p className="truncate font-medium">{displayName}</p>
                    <p className="truncate text-sm text-muted-foreground">{m.email}</p>
                  </div>
                  <Badge variant="secondary" className="shrink-0 capitalize">
                    {formatRoleLabel(m.role)}
                  </Badge>
                  {showActions ? (
                    <DropdownMenu>
                      <DropdownMenuTrigger asChild>
                        <Button
                          type="button"
                          variant="ghost"
                          size="icon"
                          aria-label={`Manage ${displayName}`}
                          className="size-8"
                        >
                          <MoreHorizontal className="size-4" aria-hidden />
                        </Button>
                      </DropdownMenuTrigger>
                      <DropdownMenuContent align="end" className="min-w-44">
                        <DropdownMenuLabel className="text-xs text-muted-foreground">
                          Change role
                        </DropdownMenuLabel>
                        {/* Only an owner can promote anyone to owner. */}
                        {callerRole === "owner" ? (
                          <DropdownMenuItem
                            disabled={m.role === "owner" || updateRoleMut.isPending}
                            onSelect={() =>
                              updateRoleMut.mutate({
                                workspace: workspaceSlug,
                                userId: m.id,
                                role: "owner",
                              })
                            }
                          >
                            Owner
                          </DropdownMenuItem>
                        ) : null}
                        <DropdownMenuItem
                          disabled={m.role === "admin" || updateRoleMut.isPending}
                          onSelect={() =>
                            updateRoleMut.mutate({
                              workspace: workspaceSlug,
                              userId: m.id,
                              role: "admin",
                            })
                          }
                        >
                          Admin
                        </DropdownMenuItem>
                        <DropdownMenuItem
                          disabled={
                            m.role === "member" ||
                            isLastOwner ||
                            updateRoleMut.isPending
                          }
                          onSelect={() =>
                            updateRoleMut.mutate({
                              workspace: workspaceSlug,
                              userId: m.id,
                              role: "member",
                            })
                          }
                        >
                          Member
                        </DropdownMenuItem>
                        <DropdownMenuSeparator />
                        <DropdownMenuItem
                          disabled={isLastOwner || removeMemberMut.isPending}
                          onSelect={() => {
                            if (
                              window.confirm(
                                `Remove ${displayName} from this workspace?`,
                              )
                            ) {
                              removeMemberMut.mutate({
                                workspace: workspaceSlug,
                                userId: m.id,
                              });
                            }
                          }}
                          className="text-destructive focus:bg-destructive/10 focus:text-destructive"
                        >
                          <Trash2 className="size-3.5" aria-hidden />
                          Remove
                        </DropdownMenuItem>
                      </DropdownMenuContent>
                    </DropdownMenu>
                  ) : null}
                </CardContent>
              </Card>
            );
          })}
        </div>
      )}

      {/* Surface any mutation errors at the page level so kebab/dialog actions
          that hit the last-owner guard or other validation failures don't
          fail silently. */}
      {(updateRoleMut.error ||
        removeMemberMut.error ||
        revokeMut.error) ? (
        <p className="mt-6 text-sm text-destructive" role="alert">
          {updateRoleMut.error?.message ??
            removeMemberMut.error?.message ??
            revokeMut.error?.message}
          {(updateRoleMut.error ||
            removeMemberMut.error ||
            revokeMut.error) && (
            <Button
              type="button"
              variant="ghost"
              size="sm"
              className="ml-2"
              onClick={() => {
                updateRoleMut.reset();
                removeMemberMut.reset();
                revokeMut.reset();
              }}
            >
              Dismiss
            </Button>
          )}
        </p>
      ) : null}

      {!canManage && callerRole === "member" ? (
        <p className="mt-10 rounded-md bg-muted/40 px-3 py-2 text-xs text-muted-foreground">
          You can see the team but only owners and admins can invite or change
          roles. Ask one of them if you need a change.
        </p>
      ) : null}
    </div>
  );
}
