"use client";

import {
  useCallback,
  useEffect,
  useState,
  type ChangeEvent,
  type KeyboardEvent,
  type ReactElement,
  type SyntheticEvent,
} from "react";
import Link from "next/link";
import { UserPlus, UserX } from "lucide-react";
import { WorkspaceMemberRole } from "@mosaic/shared";
import { isValidEmail } from "@/components/workspace/validation";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import {
  AlertDialog,
  AlertDialogAction,
  AlertDialogCancel,
  AlertDialogContent,
  AlertDialogDescription,
  AlertDialogFooter,
  AlertDialogHeader,
  AlertDialogTitle,
} from "@/components/ui/alert-dialog";
import {
  deactivateUser,
  fetchAdminUsers,
  inviteUser,
  updateUser,
  type AdminUser,
  type AdminUsersResponse,
  type AdminWorkspaceMembership,
  type InviteUserDto,
  type UpdateUserDto,
} from "@/lib/api/admin";
import { useAuth } from "@/lib/auth/auth-context";
import { fetchUserWorkspaces, updateWorkspaceMemberRole } from "@/lib/api/workspaces";
import { SettingsAccessDenied } from "@/components/settings/SettingsAccessDenied";

const ROLE_PRIORITY: Record<WorkspaceMemberRole, number> = {
  [WorkspaceMemberRole.OWNER]: 4,
  [WorkspaceMemberRole.ADMIN]: 3,
  [WorkspaceMemberRole.MEMBER]: 2,
  [WorkspaceMemberRole.GUEST]: 1,
};

const INITIAL_INVITE_FORM = {
  email: "",
  role: WorkspaceMemberRole.MEMBER,
};

const INITIAL_DETAIL_FORM = {
  name: "",
  email: "",
  role: WorkspaceMemberRole.MEMBER,
  workspaceId: null as string | null,
  workspaceName: null as string | null,
};
const USERS_PAGE_SIZE = 50;

interface DetailInitialState {
  name: string;
  email: string;
  role: WorkspaceMemberRole;
  workspaceId: string | null;
}

function toRoleLabel(role: WorkspaceMemberRole): string {
  return `${role.charAt(0)}${role.slice(1).toLowerCase()}`;
}

function getPrimaryMembership(user: AdminUser): AdminWorkspaceMembership | null {
  const [firstMembership, ...restMemberships] = user.workspaceMemberships;
  if (!firstMembership) {
    return null;
  }

  return restMemberships.reduce((highest, membership) => {
    if (ROLE_PRIORITY[membership.role] > ROLE_PRIORITY[highest.role]) {
      return membership;
    }
    return highest;
  }, firstMembership);
}

export default function UsersSettingsPage(): ReactElement {
  const { user: authUser } = useAuth();

  const [users, setUsers] = useState<AdminUser[]>([]);
  const [meta, setMeta] = useState<AdminUsersResponse["meta"] | null>(null);
  const [page, setPage] = useState<number>(1);
  const [isLoading, setIsLoading] = useState<boolean>(true);
  const [isRefreshing, setIsRefreshing] = useState<boolean>(false);
  const [error, setError] = useState<string | null>(null);

  const [defaultWorkspaceId, setDefaultWorkspaceId] = useState<string | null>(null);
  const [isAdmin, setIsAdmin] = useState<boolean | null>(null);

  const [isInviteOpen, setIsInviteOpen] = useState<boolean>(false);
  const [inviteForm, setInviteForm] = useState(INITIAL_INVITE_FORM);
  const [inviteError, setInviteError] = useState<string | null>(null);
  const [isInviting, setIsInviting] = useState<boolean>(false);

  const [detailTarget, setDetailTarget] = useState<AdminUser | null>(null);
  const [detailForm, setDetailForm] = useState(INITIAL_DETAIL_FORM);
  const [detailInitial, setDetailInitial] = useState<DetailInitialState | null>(null);
  const [detailError, setDetailError] = useState<string | null>(null);
  const [isSavingDetails, setIsSavingDetails] = useState<boolean>(false);

  const [deactivateTarget, setDeactivateTarget] = useState<AdminUser | null>(null);
  const [isDeactivating, setIsDeactivating] = useState<boolean>(false);

  const loadUsers = useCallback(
    async (showLoadingState: boolean): Promise<void> => {
      try {
        if (showLoadingState) {
          setIsLoading(true);
        } else {
          setIsRefreshing(true);
        }

        const response = await fetchAdminUsers(page, USERS_PAGE_SIZE);
        const lastValidPage = Math.max(1, response.meta.totalPages);

        if (page > lastValidPage) {
          setPage(lastValidPage);
          return;
        }

        setUsers(response.data);
        setMeta(response.meta);
        setError(null);
      } catch (err: unknown) {
        setError(err instanceof Error ? err.message : "Failed to load admin users");
      } finally {
        setIsLoading(false);
        setIsRefreshing(false);
      }
    },
    [page]
  );

  useEffect(() => {
    fetchUserWorkspaces()
      .then((workspaces) => {
        const adminRoles: WorkspaceMemberRole[] = [
          WorkspaceMemberRole.OWNER,
          WorkspaceMemberRole.ADMIN,
        ];

        setDefaultWorkspaceId(workspaces[0]?.id ?? null);
        setIsAdmin(workspaces.some((workspace) => adminRoles.includes(workspace.role)));
      })
      .catch(() => {
        setDefaultWorkspaceId(null);
        setIsAdmin(true); // fail open
      });
  }, []);

  useEffect(() => {
    if (isAdmin !== true) {
      return;
    }

    void loadUsers(true);
  }, [isAdmin, loadUsers, page]);

  function resetInviteForm(): void {
    setInviteForm(INITIAL_INVITE_FORM);
    setInviteError(null);
  }

  function openUserDetails(user: AdminUser): void {
    const primaryMembership = getPrimaryMembership(user);

    const nextDetailForm = {
      name: user.name,
      email: user.email,
      role: primaryMembership?.role ?? WorkspaceMemberRole.MEMBER,
      workspaceId: primaryMembership?.workspaceId ?? null,
      workspaceName: primaryMembership?.workspaceName ?? null,
    };

    setDetailTarget(user);
    setDetailForm(nextDetailForm);
    setDetailInitial({
      name: nextDetailForm.name,
      email: nextDetailForm.email,
      role: nextDetailForm.role,
      workspaceId: nextDetailForm.workspaceId,
    });
    setDetailError(null);
  }

  function resetUserDetails(): void {
    setDetailTarget(null);
    setDetailForm(INITIAL_DETAIL_FORM);
    setDetailInitial(null);
    setDetailError(null);
  }

  function handleUserRowKeyDown(event: KeyboardEvent<HTMLDivElement>, user: AdminUser): void {
    if (event.key === "Enter" || event.key === " ") {
      event.preventDefault();
      openUserDetails(user);
    }
  }

  async function handleInviteSubmit(event: SyntheticEvent): Promise<void> {
    event.preventDefault();
    setInviteError(null);

    const email = inviteForm.email.trim();
    if (!email) {
      setInviteError("Email is required.");
      return;
    }

    if (!isValidEmail(email)) {
      setInviteError("Please enter a valid email address.");
      return;
    }

    const dto: InviteUserDto = {
      email,
      role: inviteForm.role,
    };

    if (defaultWorkspaceId) {
      dto.workspaceId = defaultWorkspaceId;
    }

    try {
      setIsInviting(true);
      await inviteUser(dto);
      setIsInviteOpen(false);
      resetInviteForm();
      await loadUsers(false);
    } catch (err: unknown) {
      setInviteError(err instanceof Error ? err.message : "Failed to invite user");
    } finally {
      setIsInviting(false);
    }
  }

  async function handleDetailSubmit(event: SyntheticEvent): Promise<void> {
    event.preventDefault();

    if (detailTarget === null || detailInitial === null) {
      return;
    }

    const name = detailForm.name.trim();
    const email = detailForm.email.trim();

    if (!name) {
      setDetailError("Name is required.");
      return;
    }

    if (!email) {
      setDetailError("Email is required.");
      return;
    }

    if (!isValidEmail(email)) {
      setDetailError("Please enter a valid email address.");
      return;
    }

    const didUpdateUser = name !== detailInitial.name || email !== detailInitial.email;
    const didUpdateRole =
      detailForm.workspaceId !== null &&
      detailForm.workspaceId === detailInitial.workspaceId &&
      detailForm.role !== detailInitial.role;

    if (!didUpdateUser && !didUpdateRole) {
      resetUserDetails();
      return;
    }

    try {
      setIsSavingDetails(true);
      setDetailError(null);

      if (didUpdateUser) {
        const dto: UpdateUserDto = {};

        if (name !== detailInitial.name) {
          dto.name = name;
        }

        if (email !== detailInitial.email) {
          dto.email = email;
        }

        await updateUser(detailTarget.id, dto);
      }

      if (didUpdateRole && detailForm.workspaceId !== null) {
        await updateWorkspaceMemberRole(detailForm.workspaceId, detailTarget.id, {
          role: detailForm.role,
        });
      }

      resetUserDetails();
      await loadUsers(false);
    } catch (err: unknown) {
      setDetailError(err instanceof Error ? err.message : "Failed to update user");
    } finally {
      setIsSavingDetails(false);
    }
  }

  async function confirmDeactivate(): Promise<void> {
    if (!deactivateTarget) {
      return;
    }

    if (authUser?.id === deactivateTarget.id) {
      setDeactivateTarget(null);
      setError("You cannot deactivate your own account.");
      return;
    }

    try {
      setIsDeactivating(true);
      await deactivateUser(deactivateTarget.id);
      setDeactivateTarget(null);
      await loadUsers(false);
      setError(null);
    } catch (err: unknown) {
      setError(err instanceof Error ? err.message : "Failed to deactivate user");
    } finally {
      setIsDeactivating(false);
    }
  }

  if (isAdmin === null) {
    return (
      <Card className="max-w-2xl mx-auto mt-8">
        <CardContent className="py-12 text-center text-muted-foreground">
          Checking permissions...
        </CardContent>
      </Card>
    );
  }

  if (!isAdmin) {
    return <SettingsAccessDenied message="You need Admin or Owner role to manage users." />;
  }

  return (
    <div className="max-w-6xl mx-auto p-6 space-y-6">
      <div className="flex items-start justify-between gap-4">
        <div>
          <div className="flex items-center gap-3">
            <h1 className="text-3xl font-bold">Users</h1>
            {meta ? <Badge variant="outline">{meta.total} total</Badge> : null}
          </div>
          <p className="text-muted-foreground mt-1">Invite and manage workspace users</p>
        </div>

        <div className="flex items-center gap-2">
          <Button
            variant="outline"
            onClick={() => {
              void loadUsers(false);
            }}
            disabled={isLoading || isRefreshing}
          >
            {isRefreshing ? "Refreshing..." : "Refresh"}
          </Button>

          <Dialog
            open={isInviteOpen}
            onOpenChange={(open) => {
              if (!open && !isInviting) {
                resetInviteForm();
              }
              setIsInviteOpen(open);
            }}
          >
            <DialogTrigger asChild>
              <Button>
                <UserPlus className="h-4 w-4 mr-2" />
                Invite User
              </Button>
            </DialogTrigger>
            <DialogContent>
              <DialogHeader>
                <DialogTitle>Invite User</DialogTitle>
                <DialogDescription>
                  Invite a new user and assign their role for your default workspace.
                </DialogDescription>
              </DialogHeader>

              <form
                onSubmit={(event) => {
                  void handleInviteSubmit(event);
                }}
                className="space-y-4"
              >
                <div className="space-y-2">
                  <Label htmlFor="invite-email">Email</Label>
                  <Input
                    id="invite-email"
                    type="email"
                    value={inviteForm.email}
                    onChange={(event: ChangeEvent<HTMLInputElement>) => {
                      setInviteForm((prev) => ({ ...prev, email: event.target.value }));
                    }}
                    placeholder="user@example.com"
                    maxLength={255}
                    required
                  />
                </div>

                <div className="space-y-2">
                  <Label htmlFor="invite-role">Role</Label>
                  <Select
                    value={inviteForm.role}
                    onValueChange={(value) => {
                      setInviteForm((prev) => ({ ...prev, role: value as WorkspaceMemberRole }));
                    }}
                  >
                    <SelectTrigger id="invite-role">
                      <SelectValue placeholder="Select role" />
                    </SelectTrigger>
                    <SelectContent>
                      {Object.values(WorkspaceMemberRole).map((role) => (
                        <SelectItem key={role} value={role}>
                          {toRoleLabel(role)}
                        </SelectItem>
                      ))}
                    </SelectContent>
                  </Select>
                  {defaultWorkspaceId ? (
                    <p className="text-xs text-muted-foreground">Role will be applied on invite.</p>
                  ) : (
                    <p className="text-xs text-muted-foreground">
                      No default workspace found. User will be invited without workspace assignment.
                    </p>
                  )}
                </div>

                {inviteError ? (
                  <p className="text-sm text-destructive" role="alert">
                    {inviteError}
                  </p>
                ) : null}

                <DialogFooter>
                  <Button
                    type="button"
                    variant="outline"
                    onClick={() => {
                      if (!isInviting) {
                        setIsInviteOpen(false);
                        resetInviteForm();
                      }
                    }}
                    disabled={isInviting}
                  >
                    Cancel
                  </Button>
                  <Button type="submit" disabled={isInviting}>
                    {isInviting ? "Inviting..." : "Send Invite"}
                  </Button>
                </DialogFooter>
              </form>
            </DialogContent>
          </Dialog>
        </div>
      </div>

      <div>
        <Link href="/settings" className="text-sm text-blue-600 hover:text-blue-700">
          ← Back to Settings
        </Link>
      </div>

      {isLoading ? (
        <Card>
          <CardContent className="py-12 text-center text-muted-foreground">
            Loading users...
          </CardContent>
        </Card>
      ) : error ? (
        <Card>
          <CardContent className="py-4">
            <p className="text-sm text-destructive" role="alert">
              {error}
            </p>
          </CardContent>
        </Card>
      ) : users.length === 0 ? (
        <Card>
          <CardHeader>
            <CardTitle>No Users Yet</CardTitle>
            <CardDescription>Invite the first user to get started.</CardDescription>
          </CardHeader>
        </Card>
      ) : (
        <Card>
          <CardHeader>
            <CardTitle>User Directory</CardTitle>
            <CardDescription>Click a user to view details or edit profile fields.</CardDescription>
          </CardHeader>
          <CardContent className="space-y-3">
            {users.map((user) => {
              const primaryMembership = getPrimaryMembership(user);
              const isActive = user.deactivatedAt === null;
              const isCurrentUser = authUser?.id === user.id;

              return (
                <div
                  key={user.id}
                  className="rounded-md border p-4 flex flex-col gap-3 md:flex-row md:items-center md:justify-between cursor-pointer hover:bg-muted/30"
                  role="button"
                  tabIndex={0}
                  onClick={() => {
                    openUserDetails(user);
                  }}
                  onKeyDown={(event) => {
                    handleUserRowKeyDown(event, user);
                  }}
                >
                  <div className="space-y-1 min-w-0">
                    <p className="font-semibold truncate">
                      {user.name || "Unnamed User"}
                      {isCurrentUser ? (
                        <span className="ml-2 text-xs font-normal text-muted-foreground">
                          (You)
                        </span>
                      ) : null}
                    </p>
                    <p className="text-sm text-muted-foreground truncate">{user.email}</p>
                  </div>

                  <div className="flex items-center gap-2 flex-wrap md:justify-end">
                    <Badge variant="outline">
                      {primaryMembership ? toRoleLabel(primaryMembership.role) : "No role"}
                    </Badge>
                    <Badge variant={isActive ? "secondary" : "destructive"}>
                      {isActive ? "Active" : "Inactive"}
                    </Badge>
                    {isActive && !isCurrentUser ? (
                      <Button
                        variant="destructive"
                        size="sm"
                        onClick={(event) => {
                          event.stopPropagation();
                          setDeactivateTarget(user);
                        }}
                      >
                        <UserX className="h-4 w-4 mr-2" />
                        Deactivate
                      </Button>
                    ) : null}
                  </div>
                </div>
              );
            })}

            {meta && meta.totalPages > 1 ? (
              <div className="flex items-center justify-between pt-3 mt-1 border-t">
                <p className="text-sm text-muted-foreground">
                  Page {page} of {meta.totalPages}
                </p>
                <div className="flex gap-2">
                  <Button
                    variant="outline"
                    size="sm"
                    disabled={page === 1}
                    onClick={() => {
                      setPage((previousPage) => Math.max(1, previousPage - 1));
                    }}
                  >
                    Previous
                  </Button>
                  <Button
                    variant="outline"
                    size="sm"
                    disabled={page >= meta.totalPages}
                    onClick={() => {
                      setPage((previousPage) => Math.min(meta.totalPages, previousPage + 1));
                    }}
                  >
                    Next
                  </Button>
                </div>
              </div>
            ) : null}
          </CardContent>
        </Card>
      )}

      <Dialog
        open={detailTarget !== null}
        onOpenChange={(open) => {
          if (!open && !isSavingDetails) {
            resetUserDetails();
          }
        }}
      >
        <DialogContent>
          <DialogHeader>
            <DialogTitle>User Details</DialogTitle>
            <DialogDescription>
              Edit profile details for {detailTarget?.email ?? "selected user"}.
            </DialogDescription>
          </DialogHeader>

          <form
            onSubmit={(event) => {
              void handleDetailSubmit(event);
            }}
            className="space-y-4"
          >
            <div className="space-y-2">
              <Label htmlFor="detail-name">Name</Label>
              <Input
                id="detail-name"
                value={detailForm.name}
                onChange={(event: ChangeEvent<HTMLInputElement>) => {
                  setDetailForm((prev) => ({ ...prev, name: event.target.value }));
                }}
                placeholder="Full name"
                maxLength={255}
                disabled={isSavingDetails}
                required
              />
            </div>

            <div className="space-y-2">
              <Label htmlFor="detail-email">Email</Label>
              <Input
                id="detail-email"
                type="email"
                value={detailForm.email}
                onChange={(event: ChangeEvent<HTMLInputElement>) => {
                  setDetailForm((prev) => ({ ...prev, email: event.target.value }));
                }}
                placeholder="user@example.com"
                maxLength={255}
                disabled={isSavingDetails}
                required
              />
            </div>

            <div className="space-y-2">
              <Label htmlFor="detail-role">Role</Label>
              <Select
                value={detailForm.role}
                disabled={detailForm.workspaceId === null || isSavingDetails}
                onValueChange={(value) => {
                  setDetailForm((prev) => ({ ...prev, role: value as WorkspaceMemberRole }));
                }}
              >
                <SelectTrigger id="detail-role">
                  <SelectValue placeholder="Select role" />
                </SelectTrigger>
                <SelectContent>
                  {Object.values(WorkspaceMemberRole).map((role) => (
                    <SelectItem key={role} value={role}>
                      {toRoleLabel(role)}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
              {detailForm.workspaceName ? (
                <p className="text-xs text-muted-foreground">
                  Role updates apply to: {detailForm.workspaceName}
                </p>
              ) : (
                <p className="text-xs text-muted-foreground">
                  This user has no workspace membership. Role cannot be updated.
                </p>
              )}
            </div>

            {detailError !== null ? (
              <p className="text-sm text-destructive" role="alert">
                {detailError}
              </p>
            ) : null}

            <DialogFooter>
              <Button
                type="button"
                variant="outline"
                onClick={() => {
                  if (!isSavingDetails) {
                    resetUserDetails();
                  }
                }}
                disabled={isSavingDetails}
              >
                Cancel
              </Button>
              <Button type="submit" disabled={isSavingDetails}>
                {isSavingDetails ? "Saving..." : "Save Changes"}
              </Button>
            </DialogFooter>
          </form>
        </DialogContent>
      </Dialog>

      <AlertDialog
        open={deactivateTarget !== null}
        onOpenChange={(open) => {
          if (!open && !isDeactivating) {
            setDeactivateTarget(null);
          }
        }}
      >
        <AlertDialogContent>
          <AlertDialogHeader>
            <AlertDialogTitle>Deactivate User</AlertDialogTitle>
            <AlertDialogDescription>
              Deactivate {deactivateTarget?.email}? They will no longer be able to access the
              system.
            </AlertDialogDescription>
          </AlertDialogHeader>
          <AlertDialogFooter>
            <AlertDialogCancel disabled={isDeactivating}>Cancel</AlertDialogCancel>
            <AlertDialogAction
              disabled={isDeactivating}
              onClick={() => {
                void confirmDeactivate();
              }}
            >
              {isDeactivating ? "Deactivating..." : "Deactivate"}
            </AlertDialogAction>
          </AlertDialogFooter>
        </AlertDialogContent>
      </AlertDialog>
    </div>
  );
}
