import Link from "next/link";
import { AlertTriangle, Database, LockKeyhole, Plus, Search, Shield, UsersRound } from "lucide-react";
import { redirect } from "next/navigation";
import { AppShell } from "@/components/app-shell";
import { Avatar } from "@/components/avatar";
import { StatusBadge } from "@/components/status-badge";
import { SYSTEM_PERMISSIONS } from "@/lib/access";
import { prisma } from "@/lib/prisma";
import { getShellContext } from "@/lib/shell";
import { requireCurrentUser, userIsAdmin } from "@/lib/session";
import { requireInitialSetup } from "@/lib/setup";
import { DataTable, EmptyState, MetricTile, PageHeader, Panel, StatusDot, Tabs } from "@/components/ui";
import { getAppSettings, type AppSettings } from "@/lib/settings";
import { updateInstanceSettings, updateSecuritySettings } from "@/lib/settings-actions";
import { banUser, createInstanceInvite, disableUser, enableUser, expireStaleInvites, grantAdminRole, removeUserFriendships, revokeAdminRole, revokeInvite } from "@/lib/admin-actions";
import { deleteRoom } from "@/lib/room-actions";
import { isInviteExpired } from "@/lib/invites";

export const dynamic = "force-dynamic";

const adminTabs = ["Users", "Rooms", "Roles", "Invites", "Instance", "Security"];

export default async function AdminPage({ searchParams }: { searchParams: Promise<{ tab?: string; q?: string; saved?: string }> }) {
  await requireInitialSetup();
  const user = await requireCurrentUser();

  if (!userIsAdmin(user)) {
    redirect("/dashboard");
  }

  const { tab = "Users", q = "", saved } = await searchParams;
  const activeTab = adminTabs.includes(tab) ? tab : "Users";
  const query = q.trim().toLowerCase();
  const shell = await getShellContext(user);

  const [users, rooms, roles, pendingRequests, appSettings, invites, auditEvents] = await Promise.all([
    prisma.user.findMany({
      include: {
        roles: { include: { role: true } },
        _count: { select: { ownedRooms: true, roomMembers: true, sentFriends: true, gotFriends: true } }
      },
      orderBy: { createdAt: "asc" }
    }),
    prisma.room.findMany({
      include: { owner: true, _count: { select: { members: true, mediaSources: true } } },
      orderBy: { updatedAt: "desc" }
    }),
    prisma.role.findMany({
      include: { _count: { select: { users: true, permissions: true } } },
      orderBy: { name: "asc" }
    }),
    prisma.friendship.count({ where: { status: "PENDING" } }),
    getAppSettings(),
    prisma.invite.findMany({ include: { room: true, creator: true }, orderBy: { createdAt: "desc" }, take: 50 }),
    prisma.auditEvent.findMany({ include: { actor: true, room: true }, orderBy: { createdAt: "desc" }, take: 20 })
  ]);
  const filteredUsers = query
    ? users.filter((account) =>
        [account.username, account.displayName || "", ...account.roles.map((role) => role.role.name)].join(" ").toLowerCase().includes(query)
      )
    : users;
  const filteredRooms = query
    ? rooms.filter((room) =>
        [room.name, room.slug, room.visibility, room.owner?.username || "", room.owner?.displayName || ""].join(" ").toLowerCase().includes(query)
      )
    : rooms;
  const filteredRoles = query
    ? roles.filter((role) => [role.name, role.description || "", role.scope].join(" ").toLowerCase().includes(query))
    : roles;

  return (
    <AppShell active="Admin" {...shell}>
      <PageHeader
        title="Admin"
        description="Operational management for accounts, rooms, roles, instance state, and security controls."
        meta={
          <>
            <StatusDot tone="good" label="admin session" />
            <StatusDot tone="good" label={`${users.length} users`} />
            <StatusDot tone={pendingRequests > 0 ? "warn" : "neutral"} label={`${pendingRequests} pending requests`} />
          </>
        }
        actions={
          <>
            <Link className="button" href="/admin?tab=Invites"><Plus size={16} /> Invite</Link>
            <Link className="button" href="/admin?tab=Security"><Shield size={16} /> Audit</Link>
          </>
        }
      />

      <section className="metrics-grid">
        <MetricTile label="Users" value={users.length} detail="local accounts" tone="good" />
        <MetricTile label="Rooms" value={rooms.length} detail="persistent room records" tone="info" />
        <MetricTile label="Roles" value={roles.length} detail="system and room scopes" />
        <MetricTile label="Permissions" value={SYSTEM_PERMISSIONS.length} detail="known permission keys" tone="warn" />
      </section>

      <Panel
        title="Admin Workspace"
        eyebrow="Management"
        actions={
          <form className="toolbar" action="/admin">
            <input type="hidden" name="tab" value={activeTab} />
            <label className="search-field">
              <Search size={15} />
              <input name="q" placeholder={`Search ${activeTab.toLowerCase()}`} defaultValue={q} />
            </label>
          </form>
        }
      >
        <Tabs active={activeTab} items={adminTabs.map((item) => ({ label: item, href: `/admin?tab=${encodeURIComponent(item)}` }))} />

        {activeTab === "Users" ? <UsersTable users={filteredUsers} currentUserId={user.id} /> : null}
        {activeTab === "Rooms" ? <RoomsTable rooms={filteredRooms} /> : null}
        {activeTab === "Roles" ? <RolesTable roles={filteredRoles} /> : null}
        {activeTab === "Invites" ? <InvitesPanel pendingRequests={pendingRequests} invites={invites} rooms={rooms} /> : null}
        {activeTab === "Instance" ? <InstancePanel userCount={users.length} roomCount={rooms.length} settings={appSettings} saved={saved} /> : null}
        {activeTab === "Security" ? <SecurityPanel settings={appSettings} saved={saved} auditEvents={auditEvents} /> : null}
      </Panel>
    </AppShell>
  );
}

function UsersTable({
  users,
  currentUserId
}: {
  users: Array<{
    id: string;
    username: string;
    displayName: string | null;
    avatarUrl: string | null;
    disabledAt: Date | null;
    createdAt: Date;
    roles: Array<{ roleId: string; role: { name: string } }>;
    _count: { ownedRooms: number; roomMembers: number; sentFriends: number; gotFriends: number };
  }>;
  currentUserId: string;
}) {
  return (
    <DataTable>
      <table className="table">
        <thead>
          <tr>
            <th>User</th>
            <th>Roles</th>
            <th>Rooms</th>
            <th>Friends</th>
            <th>Created</th>
            <th>Actions</th>
          </tr>
        </thead>
        <tbody>
          {users.map((account) => (
            <tr key={account.id}>
              <td>
                <div className="row-main">
                  <Avatar name={account.displayName || account.username} src={account.avatarUrl} size={30} />
                  <div className="row-title">
                    <strong>{account.displayName || account.username}</strong>
                    <span>@{account.username}</span>
                  </div>
                </div>
              </td>
              <td>
                <div className="status-row">
                  {account.roles.length === 0 ? <StatusBadge>user</StatusBadge> : null}
                  {account.roles.map((userRole) => (
                    <StatusBadge key={userRole.roleId} tone={userRole.role.name === "admin" ? "good" : undefined}>
                      {userRole.role.name}
                    </StatusBadge>
                  ))}
                </div>
              </td>
              <td>{account._count.ownedRooms + account._count.roomMembers}</td>
              <td>{account._count.sentFriends + account._count.gotFriends}</td>
              <td>{account.disabledAt ? <StatusBadge tone="danger">disabled</StatusBadge> : formatDate(account.createdAt)}</td>
              <td>
                <div className="row-actions">
                  {account.roles.some((role) => role.role.name === "admin") ? (
                    <form action={revokeAdminRole}>
                      <input type="hidden" name="userId" value={account.id} />
                      <button className="button compact-button" type="submit" disabled={account.id === currentUserId}>Revoke admin</button>
                    </form>
                  ) : (
                    <form action={grantAdminRole}>
                      <input type="hidden" name="userId" value={account.id} />
                      <button className="button compact-button" type="submit">Make admin</button>
                    </form>
                  )}
                  {account.disabledAt ? (
                    <form action={enableUser}>
                      <input type="hidden" name="userId" value={account.id} />
                      <button className="button compact-button" type="submit">Enable</button>
                    </form>
                  ) : (
                    <form action={disableUser}>
                      <input type="hidden" name="userId" value={account.id} />
                      <button className="button compact-button danger" type="submit" disabled={account.id === currentUserId}>Disable</button>
                    </form>
                  )}
                  <form action={removeUserFriendships}>
                    <input type="hidden" name="userId" value={account.id} />
                    <button className="button compact-button danger" type="submit" disabled={account.id === currentUserId || account._count.sentFriends + account._count.gotFriends === 0}>
                      Remove friends
                    </button>
                  </form>
                  <form action={banUser}>
                    <input type="hidden" name="userId" value={account.id} />
                    <button className="button compact-button danger" type="submit" disabled={account.id === currentUserId || Boolean(account.disabledAt)}>
                      Ban
                    </button>
                  </form>
                </div>
              </td>
            </tr>
          ))}
        </tbody>
      </table>
    </DataTable>
  );
}

function RoomsTable({
  rooms
}: {
  rooms: Array<{
    id: string;
    slug: string;
    name: string;
    visibility: string;
    isPersonal: boolean;
    updatedAt: Date;
    owner: { username: string; displayName: string | null } | null;
    _count: { members: number; mediaSources: number };
  }>;
}) {
  return (
    <DataTable>
      <table className="table">
        <thead>
          <tr>
            <th>Room</th>
            <th>Owner</th>
            <th>Access</th>
            <th>State</th>
            <th>Updated</th>
            <th />
          </tr>
        </thead>
        <tbody>
          {rooms.map((room) => (
            <tr key={room.id}>
              <td>
                <div className="row-title">
                  <strong>{room.name}</strong>
                  <span>/{room.slug}</span>
                </div>
              </td>
              <td>{room.owner?.displayName || room.owner?.username || "Unassigned"}</td>
              <td><StatusBadge>{room.visibility.toLowerCase().replace("_", " ")}</StatusBadge></td>
              <td>{room._count.members + 1} users / {room._count.mediaSources} media</td>
              <td>{formatDate(room.updatedAt)}</td>
              <td>
                <div className="row-actions">
                  <Link className="button compact-button" href={`/rooms/${encodeURIComponent(room.slug)}`}>Open</Link>
                  {!room.isPersonal ? (
                    <form action={deleteRoom}>
                      <input type="hidden" name="roomId" value={room.id} />
                      <button className="button compact-button danger" type="submit">Delete</button>
                    </form>
                  ) : (
                    <StatusBadge>personal</StatusBadge>
                  )}
                </div>
              </td>
            </tr>
          ))}
        </tbody>
      </table>
    </DataTable>
  );
}

function RolesTable({
  roles
}: {
  roles: Array<{
    id: string;
    name: string;
    description: string | null;
    scope: string;
    _count: { users: number; permissions: number };
  }>;
}) {
  return roles.length === 0 ? (
    <EmptyState title="No roles defined" />
  ) : (
    <div className="split-grid">
      <Panel title="Roles" eyebrow="Assignments">
        {roles.map((role) => (
          <div className="row" key={role.id}>
            <div className="row-title">
              <strong>{role.name}</strong>
              <span>{role.description || `${role.scope.toLowerCase()} role`}</span>
            </div>
            <StatusBadge>{role._count.users} users / {role._count.permissions} permissions</StatusBadge>
          </div>
        ))}
      </Panel>
      <Panel title="Permissions" eyebrow="Known keys">
        {SYSTEM_PERMISSIONS.map((permission) => (
          <div className="row" key={permission}>
            <div className="row-title">
              <strong>{permission}</strong>
              <span>Assignable to system roles</span>
            </div>
            <StatusBadge>Enabled</StatusBadge>
          </div>
        ))}
      </Panel>
    </div>
  );
}

function InvitesPanel({
  pendingRequests,
  invites,
  rooms
}: {
  pendingRequests: number;
  invites: Array<{
    id: string;
    code: string;
    status: string;
    expiresAt: Date | null;
    createdAt: Date;
    room: { id: string; name: string; slug: string } | null;
    creator: { username: string; displayName: string | null } | null;
  }>;
  rooms: Array<{ id: string; name: string; slug: string }>;
}) {
  const expiredInviteCount = invites.filter((invite) => invite.status === "ACTIVE" && isInviteExpired(invite.expiresAt)).length;

  return (
    <div className="split-grid">
      <Panel title="Create Invite" eyebrow="Access">
        <form className="form compact-form" action={createInstanceInvite}>
          <label>
            Room access
            <select className="input" name="roomId" defaultValue="">
              <option value="">Instance registration only</option>
              {rooms.map((room) => (
                <option value={room.id} key={room.id}>{room.name} /{room.slug}</option>
              ))}
            </select>
          </label>
          <label>
            Expires after days
            <input className="input" name="expiresDays" type="number" min="0" max="365" defaultValue="7" />
          </label>
          <button className="button primary" type="submit">Create invite</button>
        </form>
      </Panel>
      <Panel title="Invites" eyebrow={`${invites.length} recent`}>
        {expiredInviteCount > 0 ? (
          <form action={expireStaleInvites} className="inline-form">
            <button className="button compact-button" type="submit">Mark {expiredInviteCount} expired</button>
          </form>
        ) : null}
        {invites.length === 0 ? (
          <EmptyState title="No invites yet" description="Create an invite to allow registration or room access workflows." />
        ) : (
          <div className="settings-list">
            {invites.map((invite) => {
              const expired = isInviteExpired(invite.expiresAt);
              const label = expired && invite.status === "ACTIVE" ? "expired" : invite.status.toLowerCase();
              return (
                <div className="setting-row" key={invite.id}>
                  <span>
                    <strong>{invite.code}</strong>
                    <small>
                      {invite.room ? `${invite.room.name} /${invite.room.slug}` : "Instance invite"} - created {formatDate(invite.createdAt)}
                      {invite.expiresAt ? ` - expires ${formatDate(invite.expiresAt)}` : " - no expiry"}
                    </small>
                  </span>
                  <StatusBadge tone={invite.status === "ACTIVE" && !expired ? "good" : "warn"}>{label}</StatusBadge>
                  {invite.status === "ACTIVE" && !expired ? (
                    <form action={revokeInvite}>
                      <input type="hidden" name="inviteId" value={invite.id} />
                      <button className="button compact-button danger" type="submit">Revoke</button>
                    </form>
                  ) : null}
                </div>
              );
            })}
          </div>
        )}
      </Panel>
      <Panel title="Friend Requests" eyebrow="Instance">
        <div className="setting-row">
          <UsersRound size={16} />
          <span>
            <strong>{pendingRequests} pending friend requests</strong>
            <small>Handled by each receiving user in People.</small>
          </span>
        </div>
      </Panel>
    </div>
  );
}

function InstancePanel({ userCount, roomCount, settings, saved }: { userCount: number; roomCount: number; settings: AppSettings; saved?: string }) {
  return (
    <div className="split-grid">
      <Panel title="Instance Settings" eyebrow="Site-wide">
        {saved ? <p className="form-success">Instance settings saved.</p> : null}
        <form className="form compact-form" action={updateInstanceSettings}>
          <label>
            Instance name
            <input className="input" name="instanceName" defaultValue={settings.instanceName} maxLength={80} />
          </label>
          <label>
            Description
            <textarea className="input textarea" name="instanceDescription" defaultValue={settings.instanceDescription} maxLength={240} />
          </label>
          <label>
            Default room visibility
            <select className="input" name="defaultRoomVisibility" defaultValue={settings.defaultRoomVisibility}>
              <option value="FRIENDS">Friends-only</option>
              <option value="PUBLIC">Public</option>
              <option value="EXPLICIT">Explicit members</option>
              <option value="ROLE_RESTRICTED">Role restricted</option>
            </select>
          </label>
          <label>
            Avatar upload limit in MB
            <input className="input" name="maxAvatarUploadMb" type="number" min="1" max="10" defaultValue={settings.maxAvatarUploadMb} />
          </label>
          <fieldset className="checkbox-grid">
            <legend>Allowed media providers</legend>
            {["YOUTUBE", "TWITCH", "DIRECT"].map((provider) => (
              <label key={provider}>
                <input name="allowedProviders" type="checkbox" value={provider} defaultChecked={settings.allowedProviders.includes(provider)} />
                {provider}
              </label>
            ))}
          </fieldset>
          <button className="button primary" type="submit">Save instance settings</button>
        </form>
      </Panel>
      <Panel title="Runtime" eyebrow="Container">
        <div className="settings-list">
          <Setting icon={<Database size={16} />} label="Database" value="Postgres via DATABASE_URL" />
          <Setting icon={<Shield size={16} />} label="Sessions" value="Signed HTTP-only cookie" />
          <Setting icon={<UsersRound size={16} />} label="Accounts" value={`${userCount} users`} />
          <Setting icon={<Database size={16} />} label="Rooms" value={`${roomCount} rooms`} />
        </div>
      </Panel>
      <Panel title="Health" eyebrow="Status">
        <div className="settings-list">
          <StatusDot tone="good" label="Admin page rendered" />
          <StatusDot tone="good" label="Database query succeeded" />
          <StatusDot tone="info" label="Socket endpoint configured at /api/socket" />
        </div>
      </Panel>
    </div>
  );
}

function SecurityPanel({
  settings,
  saved,
  auditEvents
}: {
  settings: AppSettings;
  saved?: string;
  auditEvents: Array<{
    id: string;
    action: string;
    createdAt: Date;
    actor: { username: string; displayName: string | null } | null;
    room: { slug: string; name: string } | null;
  }>;
}) {
  return (
    <div className="split-grid">
      <Panel title="Security Controls" eyebrow="Policy">
        {saved ? <p className="form-success">Security settings saved.</p> : null}
        <form className="form compact-form" action={updateSecuritySettings}>
          <label>
            Registration mode
            <select className="input" name="registrationMode" defaultValue={settings.registrationMode}>
              <option value="OPEN">Open registration</option>
              <option value="INVITE_ONLY">Invite only</option>
              <option value="DISABLED">Disabled</option>
            </select>
          </label>
          <div className="settings-list">
            <Setting icon={<LockKeyhole size={16} />} label="Password storage" value="bcrypt hash" />
            <Setting icon={<Shield size={16} />} label="Admin check" value="Server-side role lookup" />
            <Setting icon={<AlertTriangle size={16} />} label="Registration mode" value={settings.registrationMode.toLowerCase().replace("_", " ")} />
          </div>
          <button className="button primary" type="submit">Save security settings</button>
        </form>
      </Panel>
      <Panel title="Danger Zone" eyebrow="Destructive">
        <div className="settings-list">
          <StatusDot tone="good" label="User disable actions enabled" />
          <StatusDot tone="good" label="Non-personal room deletion enabled" />
          <StatusDot tone="good" label="Registration mode controls enabled" />
        </div>
      </Panel>
      <Panel title="Audit Events" eyebrow="Recent">
        {auditEvents.length === 0 ? (
          <EmptyState title="No audit events yet" description="Admin, room, queue, and chat actions will appear here." />
        ) : (
          <div className="settings-list">
            {auditEvents.map((event) => (
              <div className="setting-row" key={event.id}>
                <span>
                  <strong>{event.action}</strong>
                  <small>{event.actor?.displayName || event.actor?.username || "System"} - {event.room?.slug || "instance"} - {formatDate(event.createdAt)}</small>
                </span>
              </div>
            ))}
          </div>
        )}
      </Panel>
    </div>
  );
}

function Setting({ icon, label, value }: { icon: React.ReactNode; label: string; value: string }) {
  return (
    <div className="setting-row">
      {icon}
      <span>
        <strong>{label}</strong>
        <small>{value}</small>
      </span>
    </div>
  );
}

function formatDate(date: Date) {
  return new Intl.DateTimeFormat("en", { month: "short", day: "numeric", year: "numeric" }).format(date);
}
