import Link from "next/link";
import { Search, UserMinus, UserPlus } from "lucide-react";
import { AppShell } from "@/components/app-shell";
import { Avatar } from "@/components/avatar";
import { StatusBadge } from "@/components/status-badge";
import { DataTable, EmptyState, PageHeader, Panel, StatusDot, Tabs } from "@/components/ui";
import { acceptFriendRequest, blockUser, cancelFriendRequest, declineFriendRequest, removeFriendship, sendFriendRequest, unblockUser } from "@/lib/friend-actions";
import { prisma } from "@/lib/prisma";
import { getShellContext } from "@/lib/shell";
import { requireCurrentUser } from "@/lib/session";
import { requireInitialSetup } from "@/lib/setup";

export const dynamic = "force-dynamic";

const tabs = ["Friends", "Incoming", "Outgoing", "Directory", "Blocked"];

type PersonSummary = {
  id: string;
  username: string;
  displayName: string | null;
  avatarUrl: string | null;
};

type FriendshipWithUsers = {
  id: string;
  requesterId: string;
  receiverId: string;
  status: string;
  requester: PersonSummary;
  receiver: PersonSummary;
};

type DirectoryUser = PersonSummary & {
  ownedRooms: Array<{ slug: string }>;
};

export default async function PeoplePage({ searchParams }: { searchParams: Promise<{ view?: string; q?: string }> }) {
  await requireInitialSetup();
  const user = await requireCurrentUser();
  const shell = await getShellContext(user);
  const { view = "Friends", q = "" } = await searchParams;
  const activeView = tabs.includes(view) ? view : "Friends";
  const query = q.trim().toLowerCase();

  const [users, friendships] = await Promise.all([
    prisma.user.findMany({
      where: { id: { not: user.id } },
      include: { ownedRooms: { select: { slug: true }, take: 1 } },
      orderBy: { username: "asc" }
    }),
    prisma.friendship.findMany({
      where: { OR: [{ requesterId: user.id }, { receiverId: user.id }] },
      include: { requester: true, receiver: true }
    })
  ]);

  const incoming = friendships.filter((item) => item.receiverId === user.id && item.status === "PENDING");
  const outgoing = friendships.filter((item) => item.requesterId === user.id && item.status === "PENDING");
  const accepted = friendships.filter((item) => item.status === "ACCEPTED");
  const blocked = friendships.filter((item) => item.status === "BLOCKED");
  const relationshipByUserId = new Map<string, (typeof friendships)[number]>();
  for (const friendship of friendships) {
    const otherId = friendship.requesterId === user.id ? friendship.receiverId : friendship.requesterId;
    relationshipByUserId.set(otherId, friendship);
  }

  const directory = users
    .filter((listedUser) =>
      query ? [listedUser.username, listedUser.displayName || ""].join(" ").toLowerCase().includes(query) : true
    )
    .map((listedUser) => ({ user: listedUser, relationship: relationshipByUserId.get(listedUser.id) }));
  const filteredIncoming = filterFriendships(incoming, user.id, query);
  const filteredOutgoing = filterFriendships(outgoing, user.id, query);
  const filteredAccepted = filterFriendships(accepted, user.id, query);
  const filteredBlocked = filterFriendships(blocked, user.id, query);
  const tabCounts: Record<string, number> = {
    Friends: accepted.length,
    Incoming: incoming.length,
    Outgoing: outgoing.length,
    Directory: users.length,
    Blocked: blocked.length
  };

  return (
    <AppShell active="People" {...shell}>
      <PageHeader
        title="People"
        description="Friends, requests, account directory, and access relationships for persistent rooms."
        meta={
          <>
            <StatusDot tone="good" label={`${accepted.length} friends`} />
            <StatusDot tone={incoming.length > 0 ? "warn" : "neutral"} label={`${incoming.length} incoming`} />
            <StatusDot tone={outgoing.length > 0 ? "warn" : "neutral"} label={`${outgoing.length} outgoing`} />
          </>
        }
      />

      <Panel
        title="People Directory"
        eyebrow="Social graph"
        actions={
          <form className="toolbar" action="/people">
            <input type="hidden" name="view" value={activeView} />
            <label className="search-field">
              <Search size={15} />
              <input name="q" placeholder="Search users" defaultValue={q} />
            </label>
          </form>
        }
      >
        <Tabs
          active={activeView}
          items={tabs.map((tab) => ({
            label: tab,
            href: `/people?view=${encodeURIComponent(tab)}`,
            count: tabCounts[tab]
          }))}
        />

        {activeView === "Friends" ? <FriendshipList currentUserId={user.id} friendships={filteredAccepted} empty="No accepted friends yet." /> : null}
        {activeView === "Incoming" ? <IncomingList requests={filteredIncoming} /> : null}
        {activeView === "Outgoing" ? <FriendshipList currentUserId={user.id} friendships={filteredOutgoing} empty="No outgoing friend requests." /> : null}
        {activeView === "Blocked" ? <FriendshipList currentUserId={user.id} friendships={filteredBlocked} empty="No blocked users." /> : null}
        {activeView === "Directory" ? <Directory rows={directory} currentUserId={user.id} /> : null}
      </Panel>
    </AppShell>
  );
}

function filterFriendships(items: FriendshipWithUsers[], currentUserId: string, query: string) {
  if (!query) return items;
  return items.filter((friendship) => {
    const person = friendship.requesterId === currentUserId ? friendship.receiver : friendship.requester;
    return [person.username, person.displayName || ""].join(" ").toLowerCase().includes(query);
  });
}

function FriendshipList({
  currentUserId,
  friendships,
  empty
}: {
  currentUserId: string;
  friendships: FriendshipWithUsers[];
  empty: string;
}) {
  if (friendships.length === 0) {
    return <EmptyState title={empty} description="Use the directory tab to discover accounts." />;
  }

  return (
    <div className="people-list">
      {friendships.map((friendship) => {
        const person = friendship.requesterId === currentUserId ? friendship.receiver : friendship.requester;
        return (
          <div className="row" key={friendship.id}>
            <div className="row-main">
              <Avatar name={person.displayName || person.username} src={person.avatarUrl} />
              <div className="row-title">
                <strong>{person.displayName || person.username}</strong>
                <span>@{person.username}</span>
              </div>
            </div>
            <div className="row-actions">
              <StatusBadge tone={friendship.status === "ACCEPTED" ? "good" : "warn"}>{friendship.status.toLowerCase()}</StatusBadge>
              {friendship.status === "PENDING" && friendship.requesterId === currentUserId ? (
                <form action={cancelFriendRequest}>
                  <input type="hidden" name="friendshipId" value={friendship.id} />
                  <button className="button compact-button" type="submit">Cancel</button>
                </form>
              ) : null}
              {friendship.status === "BLOCKED" ? (
                <form action={unblockUser}>
                  <input type="hidden" name="friendshipId" value={friendship.id} />
                  <button className="button compact-button" type="submit">Unblock</button>
                </form>
              ) : null}
              {friendship.status === "ACCEPTED" ? (
                <>
                  <form action={removeFriendship}>
                    <input type="hidden" name="friendshipId" value={friendship.id} />
                    <button className="button compact-button" type="submit">
                      <UserMinus size={14} /> Remove
                    </button>
                  </form>
                  <form action={blockUser}>
                    <input type="hidden" name="targetId" value={person.id} />
                    <button className="button compact-button danger" type="submit">Block</button>
                  </form>
                </>
              ) : null}
            </div>
          </div>
        );
      })}
    </div>
  );
}

function IncomingList({ requests }: { requests: FriendshipWithUsers[] }) {
  if (requests.length === 0) {
    return <EmptyState title="No incoming requests" description="New friend requests will require explicit approval here." />;
  }

  return (
    <div className="people-list">
      {requests.map((request) => (
        <div className="row" key={request.id}>
          <div className="row-main">
            <Avatar name={request.requester.displayName || request.requester.username} src={request.requester.avatarUrl} />
            <div className="row-title">
              <strong>{request.requester.displayName || request.requester.username}</strong>
              <span>@{request.requester.username}</span>
            </div>
          </div>
          <div className="row-actions">
            <form action={acceptFriendRequest}>
              <input type="hidden" name="friendshipId" value={request.id} />
              <button className="button primary compact-button" type="submit">Accept</button>
            </form>
            <form action={declineFriendRequest}>
              <input type="hidden" name="friendshipId" value={request.id} />
              <button className="button compact-button" type="submit">Decline</button>
            </form>
          </div>
        </div>
      ))}
    </div>
  );
}

function Directory({
  rows,
  currentUserId
}: {
  rows: Array<{
    user: DirectoryUser;
    relationship?: FriendshipWithUsers;
  }>;
  currentUserId: string;
}) {
  if (rows.length === 0) {
    return <EmptyState title="No users registered" description="New accounts will appear here after registration." />;
  }

  return (
    <DataTable>
      <table className="table">
        <thead>
          <tr>
            <th>User</th>
            <th>Room</th>
            <th>Relationship</th>
            <th />
          </tr>
        </thead>
        <tbody>
          {rows.map(({ user, relationship }) => {
            const roomSlug = user.ownedRooms[0]?.slug;
            const accepted = relationship?.status === "ACCEPTED";
            const blocked = relationship?.status === "BLOCKED";
            return (
              <tr key={user.id}>
                <td>
                  <div className="row-main">
                    <Avatar name={user.displayName || user.username} src={user.avatarUrl} size={30} />
                    <div className="row-title">
                      <strong>{user.displayName || user.username}</strong>
                      <span>@{user.username}</span>
                    </div>
                  </div>
                </td>
                <td>{roomSlug && accepted ? <Link className="text-link" href={`/rooms/${encodeURIComponent(roomSlug)}`}>Open personal room</Link> : "Locked"}</td>
                <td><StatusBadge tone={accepted ? "good" : relationship ? "warn" : undefined}>{relationship?.status.toLowerCase() || "none"}</StatusBadge></td>
                <td>
                  {!relationship ? (
                    <div className="row-actions">
                      <form action={sendFriendRequest}>
                        <input type="hidden" name="receiverId" value={user.id} />
                        <button className="button primary compact-button" type="submit">
                          <UserPlus size={14} /> Add
                        </button>
                      </form>
                      <form action={blockUser}>
                        <input type="hidden" name="targetId" value={user.id} />
                        <button className="button compact-button danger" type="submit">Block</button>
                      </form>
                    </div>
                  ) : blocked && relationship.requesterId === currentUserId ? (
                    <form action={unblockUser}>
                      <input type="hidden" name="friendshipId" value={relationship.id} />
                      <button className="button compact-button" type="submit">Unblock</button>
                    </form>
                  ) : null}
                </td>
              </tr>
            );
          })}
        </tbody>
      </table>
    </DataTable>
  );
}
