"use client";

import type { ReactElement, SyntheticEvent } from "react";

import { useCallback, useEffect, useMemo, useState } from "react";
import Link from "next/link";
import { UserPlus, UserX } from "lucide-react";
import { WorkspaceMemberRole } from "@mosaic/shared";
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 {
  AlertDialog,
  AlertDialogAction,
  AlertDialogCancel,
  AlertDialogContent,
  AlertDialogDescription,
  AlertDialogFooter,
  AlertDialogHeader,
  AlertDialogTitle,
} from "@/components/ui/alert-dialog";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import {
  addWorkspaceMember,
  createWorkspace,
  fetchUserWorkspaces,
  fetchWorkspaceMembers,
  removeWorkspaceMember,
  type UserWorkspace,
  type WorkspaceMemberEntry,
} from "@/lib/api/workspaces";
import { fetchAdminUsers, type AdminUser } from "@/lib/api/admin";

function getErrorMessage(error: unknown, fallback: string): string {
  if (error instanceof Error) {
    return error.message;
  }

  return fallback;
}

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

interface RemoveMemberTarget {
  userId: string;
  email: string;
}

const ROLE_BADGE_CLASS: Record<WorkspaceMemberRole, string> = {
  [WorkspaceMemberRole.OWNER]: "border-purple-200 bg-purple-50 text-purple-700",
  [WorkspaceMemberRole.ADMIN]: "border-blue-200 bg-blue-50 text-blue-700",
  [WorkspaceMemberRole.MEMBER]: "border-green-200 bg-green-50 text-green-700",
  [WorkspaceMemberRole.GUEST]: "border-gray-200 bg-gray-50 text-gray-700",
};

export default function WorkspacesPage(): ReactElement {
  const [workspaces, setWorkspaces] = useState<UserWorkspace[]>([]);
  const [selectedWorkspaceId, setSelectedWorkspaceId] = useState<string | null>(null);

  const [isLoading, setIsLoading] = useState(true);
  const [loadError, setLoadError] = useState<string | null>(null);

  const [isCreating, setIsCreating] = useState(false);
  const [newWorkspaceName, setNewWorkspaceName] = useState("");
  const [createError, setCreateError] = useState<string | null>(null);

  const [members, setMembers] = useState<WorkspaceMemberEntry[]>([]);
  const [isMembersLoading, setIsMembersLoading] = useState(false);
  const [membersError, setMembersError] = useState<string | null>(null);

  const [isAddMemberOpen, setIsAddMemberOpen] = useState(false);
  const [isAddingMember, setIsAddingMember] = useState(false);
  const [addMemberError, setAddMemberError] = useState<string | null>(null);
  const [memberUserId, setMemberUserId] = useState<string>("");
  const [memberRole, setMemberRole] = useState<WorkspaceMemberRole>(WorkspaceMemberRole.MEMBER);
  const [availableUsers, setAvailableUsers] = useState<AdminUser[]>([]);
  const [isLoadingUsers, setIsLoadingUsers] = useState(false);

  const [removeTarget, setRemoveTarget] = useState<RemoveMemberTarget | null>(null);
  const [isRemovingMember, setIsRemovingMember] = useState(false);

  const selectedWorkspace = useMemo(
    () => workspaces.find((workspace) => workspace.id === selectedWorkspaceId) ?? null,
    [selectedWorkspaceId, workspaces]
  );

  const loadWorkspaces = useCallback(async (): Promise<void> => {
    setIsLoading(true);

    try {
      const data = await fetchUserWorkspaces();
      setWorkspaces(data);
      setLoadError(null);
      setSelectedWorkspaceId((current) => {
        if (current && data.some((workspace) => workspace.id === current)) {
          return current;
        }

        return data[0]?.id ?? null;
      });
    } catch (error) {
      setLoadError(getErrorMessage(error, "Failed to load workspaces"));
      setSelectedWorkspaceId(null);
    } finally {
      setIsLoading(false);
    }
  }, []);

  const loadMembers = useCallback(async (workspaceId: string): Promise<void> => {
    setIsMembersLoading(true);
    setMembersError(null);

    try {
      const data = await fetchWorkspaceMembers(workspaceId);
      setMembers(data);
    } catch (error) {
      setMembersError(getErrorMessage(error, "Failed to load workspace members"));
      setMembers([]);
    } finally {
      setIsMembersLoading(false);
    }
  }, []);

  useEffect(() => {
    void loadWorkspaces();
  }, [loadWorkspaces]);

  useEffect(() => {
    if (!selectedWorkspaceId) {
      setMembers([]);
      setMembersError(null);
      return;
    }

    void loadMembers(selectedWorkspaceId);
  }, [loadMembers, selectedWorkspaceId]);

  const handleCreateWorkspace = async (event: SyntheticEvent<HTMLFormElement>): Promise<void> => {
    event.preventDefault();

    const workspaceName = newWorkspaceName.trim();
    if (!workspaceName) {
      return;
    }

    setIsCreating(true);
    setCreateError(null);

    try {
      await createWorkspace({ name: workspaceName });
      setNewWorkspaceName("");
      await loadWorkspaces();
    } catch (error) {
      setCreateError(getErrorMessage(error, "Failed to create workspace"));
    } finally {
      setIsCreating(false);
    }
  };

  const eligibleUsers = useMemo(() => {
    const memberIds = new Set(members.map((member) => member.userId));
    return availableUsers.filter((user) => !memberIds.has(user.id));
  }, [availableUsers, members]);

  const loadAvailableUsers = useCallback(async (): Promise<void> => {
    setIsLoadingUsers(true);

    try {
      const response = await fetchAdminUsers(1, 200);
      const activeUsers = response.data.filter((user) => user.deactivatedAt === null);
      setAvailableUsers(activeUsers);

      if (memberUserId && activeUsers.some((user) => user.id === memberUserId)) {
        return;
      }

      const memberIds = new Set(members.map((member) => member.userId));
      const firstEligible = activeUsers.find((user) => !memberIds.has(user.id));
      setMemberUserId(firstEligible?.id ?? "");
    } catch (error) {
      setAddMemberError(getErrorMessage(error, "Failed to load users for member assignment"));
      setAvailableUsers([]);
      setMemberUserId("");
    } finally {
      setIsLoadingUsers(false);
    }
  }, [memberUserId, members]);

  const openAddMemberDialog = async (): Promise<void> => {
    setAddMemberError(null);
    setMemberRole(WorkspaceMemberRole.MEMBER);
    setIsAddMemberOpen(true);
    await loadAvailableUsers();
  };

  const handleAddMember = async (event: SyntheticEvent<HTMLFormElement>): Promise<void> => {
    event.preventDefault();

    if (!selectedWorkspaceId) {
      setAddMemberError("Select a workspace before adding members.");
      return;
    }

    if (!memberUserId) {
      setAddMemberError("Select a user to add.");
      return;
    }

    setIsAddingMember(true);
    setAddMemberError(null);

    try {
      await addWorkspaceMember(selectedWorkspaceId, {
        userId: memberUserId,
        role: memberRole,
      });
      setIsAddMemberOpen(false);
      await loadMembers(selectedWorkspaceId);
    } catch (error) {
      setAddMemberError(getErrorMessage(error, "Failed to add member"));
    } finally {
      setIsAddingMember(false);
    }
  };

  const handleRemoveMember = async (): Promise<void> => {
    if (!selectedWorkspaceId || !removeTarget) {
      return;
    }

    setIsRemovingMember(true);

    try {
      await removeWorkspaceMember(selectedWorkspaceId, removeTarget.userId);
      setRemoveTarget(null);
      await loadMembers(selectedWorkspaceId);
    } catch (error) {
      setMembersError(getErrorMessage(error, "Failed to remove member"));
    } finally {
      setIsRemovingMember(false);
    }
  };

  return (
    <main className="max-w-6xl mx-auto p-6 space-y-6">
      <div className="flex items-start justify-between gap-4">
        <div>
          <h1 className="text-3xl font-bold">Workspaces</h1>
          <p className="text-muted-foreground mt-1">Manage workspaces and workspace members</p>
        </div>
        <Link href="/settings" className="text-sm text-blue-600 hover:text-blue-700">
          ← Back to Settings
        </Link>
      </div>

      <Card>
        <CardHeader>
          <CardTitle>Create New Workspace</CardTitle>
          <CardDescription>Create a workspace for a new team or project.</CardDescription>
        </CardHeader>
        <CardContent>
          <form onSubmit={handleCreateWorkspace} className="flex gap-3">
            <Input
              type="text"
              value={newWorkspaceName}
              onChange={(event) => {
                setNewWorkspaceName(event.target.value);
              }}
              placeholder="Enter workspace name..."
              disabled={isCreating}
            />
            <Button type="submit" disabled={isCreating || !newWorkspaceName.trim()}>
              {isCreating ? "Creating..." : "Create Workspace"}
            </Button>
          </form>
          {createError !== null ? (
            <p className="mt-3 text-sm text-destructive" role="alert">
              {createError}
            </p>
          ) : null}
        </CardContent>
      </Card>

      {loadError !== null ? (
        <Card>
          <CardContent className="py-4">
            <p className="text-sm text-destructive" role="alert">
              {loadError}
            </p>
          </CardContent>
        </Card>
      ) : null}

      <div className="grid grid-cols-1 lg:grid-cols-5 gap-6">
        <Card className="lg:col-span-2">
          <CardHeader>
            <CardTitle>Your Workspaces ({isLoading ? "..." : workspaces.length})</CardTitle>
            <CardDescription>Click a workspace to manage its members.</CardDescription>
          </CardHeader>
          <CardContent className="space-y-3">
            {isLoading ? (
              <p className="text-sm text-muted-foreground">Loading workspaces...</p>
            ) : workspaces.length === 0 ? (
              <p className="text-sm text-muted-foreground">
                No workspaces yet. Create one to begin.
              </p>
            ) : (
              workspaces.map((workspace) => {
                const isSelected = selectedWorkspaceId === workspace.id;

                return (
                  <button
                    key={workspace.id}
                    type="button"
                    onClick={() => {
                      setSelectedWorkspaceId(workspace.id);
                    }}
                    className={`w-full rounded-lg border p-4 text-left transition-colors ${
                      isSelected ? "border-primary bg-muted/40" : "border-border hover:bg-muted/20"
                    }`}
                  >
                    <div className="flex items-start justify-between gap-3">
                      <div className="min-w-0">
                        <p className="font-semibold truncate">{workspace.name}</p>
                        <p className="text-xs text-muted-foreground mt-1">
                          Created {new Date(workspace.createdAt).toLocaleDateString()}
                        </p>
                      </div>
                      <Badge variant="outline">{toRoleLabel(workspace.role)}</Badge>
                    </div>
                  </button>
                );
              })
            )}
          </CardContent>
        </Card>

        <Card className="lg:col-span-3">
          <CardHeader>
            <div className="flex items-start justify-between gap-3">
              <div>
                <CardTitle>
                  {selectedWorkspace ? `${selectedWorkspace.name} Members` : "Workspace Members"}
                </CardTitle>
                <CardDescription>
                  {selectedWorkspace
                    ? "Manage member roles and access for this workspace."
                    : "Select a workspace to view its members."}
                </CardDescription>
              </div>

              <Dialog
                open={isAddMemberOpen}
                onOpenChange={(open) => {
                  if (!open && !isAddingMember) {
                    setIsAddMemberOpen(false);
                    setAddMemberError(null);
                  }
                }}
              >
                <DialogTrigger asChild>
                  <Button
                    onClick={() => {
                      void openAddMemberDialog();
                    }}
                    disabled={!selectedWorkspace}
                  >
                    <UserPlus className="h-4 w-4 mr-2" />
                    Add Member
                  </Button>
                </DialogTrigger>
                <DialogContent>
                  <DialogHeader>
                    <DialogTitle>Add Workspace Member</DialogTitle>
                    <DialogDescription>
                      Add an existing user to {selectedWorkspace?.name ?? "this workspace"}.
                    </DialogDescription>
                  </DialogHeader>

                  <form
                    onSubmit={(event) => {
                      void handleAddMember(event);
                    }}
                    className="space-y-4"
                  >
                    <div className="space-y-2">
                      <Label htmlFor="member-user">User</Label>
                      <Select
                        value={memberUserId}
                        onValueChange={(value) => {
                          setMemberUserId(value);
                        }}
                        disabled={isLoadingUsers || eligibleUsers.length === 0 || isAddingMember}
                      >
                        <SelectTrigger id="member-user">
                          <SelectValue
                            placeholder={
                              isLoadingUsers
                                ? "Loading users..."
                                : eligibleUsers.length === 0
                                  ? "No eligible users"
                                  : "Select a user"
                            }
                          />
                        </SelectTrigger>
                        <SelectContent>
                          {eligibleUsers.map((user) => (
                            <SelectItem key={user.id} value={user.id}>
                              {user.name} ({user.email})
                            </SelectItem>
                          ))}
                        </SelectContent>
                      </Select>
                    </div>

                    <div className="space-y-2">
                      <Label htmlFor="member-role">Role</Label>
                      <Select
                        value={memberRole}
                        onValueChange={(value) => {
                          setMemberRole(value as WorkspaceMemberRole);
                        }}
                        disabled={isAddingMember}
                      >
                        <SelectTrigger id="member-role">
                          <SelectValue placeholder="Select role" />
                        </SelectTrigger>
                        <SelectContent>
                          {Object.values(WorkspaceMemberRole)
                            .filter((role) => role !== WorkspaceMemberRole.OWNER)
                            .map((role) => (
                              <SelectItem key={role} value={role}>
                                {toRoleLabel(role)}
                              </SelectItem>
                            ))}
                        </SelectContent>
                      </Select>
                    </div>

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

                    <DialogFooter>
                      <Button
                        type="button"
                        variant="outline"
                        onClick={() => {
                          if (!isAddingMember) {
                            setIsAddMemberOpen(false);
                            setAddMemberError(null);
                          }
                        }}
                        disabled={isAddingMember}
                      >
                        Cancel
                      </Button>
                      <Button type="submit" disabled={isAddingMember || !memberUserId}>
                        {isAddingMember ? "Adding..." : "Add Member"}
                      </Button>
                    </DialogFooter>
                  </form>
                </DialogContent>
              </Dialog>
            </div>
          </CardHeader>

          <CardContent className="space-y-3">
            {selectedWorkspace === null ? (
              <p className="text-sm text-muted-foreground">Select a workspace to view members.</p>
            ) : membersError !== null ? (
              <p className="text-sm text-destructive" role="alert">
                {membersError}
              </p>
            ) : isMembersLoading ? (
              <p className="text-sm text-muted-foreground">Loading members...</p>
            ) : members.length === 0 ? (
              <p className="text-sm text-muted-foreground">No members found for this workspace.</p>
            ) : (
              members.map((member) => (
                <div
                  key={member.userId}
                  className="rounded-md border p-4 flex flex-col gap-3 md:flex-row md:items-center md:justify-between"
                >
                  <div className="space-y-1 min-w-0">
                    <p className="font-semibold truncate">{member.user.name ?? "Unnamed User"}</p>
                    <p className="text-sm text-muted-foreground truncate">{member.user.email}</p>
                  </div>

                  <div className="flex items-center gap-2 md:justify-end">
                    <Badge variant="outline" className={ROLE_BADGE_CLASS[member.role]}>
                      {toRoleLabel(member.role)}
                    </Badge>

                    <Button
                      type="button"
                      variant="destructive"
                      size="sm"
                      onClick={() => {
                        setRemoveTarget({
                          userId: member.userId,
                          email: member.user.email,
                        });
                      }}
                    >
                      <UserX className="h-4 w-4 mr-2" />
                      Remove
                    </Button>
                  </div>
                </div>
              ))
            )}
          </CardContent>
        </Card>
      </div>

      <AlertDialog
        open={removeTarget !== null}
        onOpenChange={(open) => {
          if (!open && !isRemovingMember) {
            setRemoveTarget(null);
          }
        }}
      >
        <AlertDialogContent>
          <AlertDialogHeader>
            <AlertDialogTitle>Remove Workspace Member</AlertDialogTitle>
            <AlertDialogDescription>
              Remove {removeTarget?.email} from {selectedWorkspace?.name}? They will lose access to
              this workspace.
            </AlertDialogDescription>
          </AlertDialogHeader>
          <AlertDialogFooter>
            <AlertDialogCancel disabled={isRemovingMember}>Cancel</AlertDialogCancel>
            <AlertDialogAction
              disabled={isRemovingMember}
              onClick={() => {
                void handleRemoveMember();
              }}
            >
              {isRemovingMember ? "Removing..." : "Remove"}
            </AlertDialogAction>
          </AlertDialogFooter>
        </AlertDialogContent>
      </AlertDialog>
    </main>
  );
}
