import {useEffect, useState} from "react";
import {createUser, fetchAllUsers, fetchCurrentUser, updateUser,} from "../../api/points/UserPoint";
import type {UserDto} from "../../api/dtos/UserDto";
import ContentBackground from "../basics/ContentBackground";
import ContentBody from "../basics/ContentBody";
import StickyHeader from "../basics/StickyHeader";
import Button from "../basics/Button";
import {ButtonType} from "../basics/BasicButtonDefinitions";
import PageContainer from "../basics/PageContainer";
import {ChangePasswordModal} from "./ChangePasswordModal";
import ButtonGroupLayout from "../basics/ButtonGroupLayout";
import {Plus, X} from "lucide-react";
import ButtonLink from "../basics/ButtonLink";
import {getRecipeListUrl} from "../../routes";
import type {CreateUserResponse} from "../../api/dtos/CreateUserResponse";
import type {UserListResponse} from "../../api/dtos/UserListResponse";
import UserList from "./UserList";
import UserEditForm from "./UserEditForm";
import ErrorPopup from "../basics/ErrorPopup";
import {UserRole} from "../../api/enums/UserRole.ts";

/**
 * UserManagementPage
 * -------------------
 * Displays a two-column layout:
 *  - Left: list of all users
 *  - Right: edit form for selected or new user
 *
 * Allows:
 *  - Admins to manage all users (add/edit)
 *  - Regular users to edit their own profile
 *  - Password changes via modal
 */
export default function UserManagementPage() {
    const [users, setUsers] = useState<UserDto[]>([]);
    const [selectedUser, setSelectedUser] = useState<UserDto | null>(null);
    const [currentUser, setCurrentUser] = useState<UserDto | null>(null);
    const [isPasswordModalOpen, setIsPasswordModalOpen] = useState(false);
    const [isSaving, setIsSaving] = useState(false);
    const [error, setError] = useState<string | null>(null);

    const isAdmin = currentUser?.role === UserRole.ADMIN;

    // Load current user and user list (if admin)
    useEffect(() => {
        loadData();
    }, []);

    /**
     * Load data for user management page
     *
     * An admin can see all users while a normal user can only see his own user data.
     * Initially, the current user is selected.
     */
    const loadData = async () => {
        try {
            const me = await fetchCurrentUser();
            setCurrentUser(me);

            if (me.role === UserRole.ADMIN) {
                const userResponse: UserListResponse = await fetchAllUsers();

                // Sort users alphabetically by last name, then first name
                const sortedUsers = userResponse.valueList.sort((a, b) => {
                    const lastNameCompare = (a.lastName || "").localeCompare(
                        b.lastName || ""
                    );
                    if (lastNameCompare !== 0) {
                        return lastNameCompare;
                    }
                    return (a.firstName || "").localeCompare(b.firstName || "");
                });

                setUsers(sortedUsers);
                setSelectedUser(me);
            } else {
                setUsers([me]);
                setSelectedUser(me);
            }
        } catch (err) {
            setError(
                err instanceof Error
                    ? err.message
                    : "Fehler beim Laden der Benutzerdaten"
            );
        }
    };

    /** Handles selecting a user from the list */
    const handleSelectUser = (user: UserDto) => {
        setSelectedUser({...user});
    };

    /** Handles saving user (create or update) */
    const handleSave = async (user: UserDto, password?: string) => {
        setIsSaving(true);
        setError(null);
        try {
            if (!user.id) {
                // New user
                const response: CreateUserResponse = await createUser({
                    userData: user,
                    password: password || "",
                });
                const userDto = response.userData;
                if (userDto) {
                    const newUsers = [...users, userDto].sort((a, b) => {
                        const lastNameCompare = (a.lastName || "").localeCompare(
                            b.lastName || ""
                        );
                        if (lastNameCompare !== 0) {
                            return lastNameCompare;
                        }
                        return (a.firstName || "").localeCompare(b.firstName || "");
                    });
                    setUsers(newUsers);
                    setSelectedUser(userDto);
                }
            } else {
                // Existing user
                const updated = await updateUser(user);
                setUsers(users.map((u) => (u.id === updated.id ? updated : u)));
                setSelectedUser(updated);
            }
        } catch (err) {
            setError(
                err instanceof Error
                    ? err.message
                    : "Fehler beim Speichern der Benutzerdaten"
            );
        } finally {
            setIsSaving(false);
        }
    };

    /** Opens password modal */
    const openPasswordModal = () => {
        setIsPasswordModalOpen(true);
    };

    /** Add new empty user */
    const handleAddUser = () => {
        setSelectedUser({
            userName: "",
            firstName: "",
            lastName: "",
            email: "",
            role: UserRole.USER,
        });
    };

    return (
        <PageContainer>
            <ContentBackground>
                <StickyHeader className="flex justify-between items-center">
                    <h1>Benutzerverwaltung</h1>
                    <ButtonGroupLayout>
                        {isAdmin && (
                            <Button
                                icon={Plus}
                                onClick={handleAddUser}
                                text="Neuer Benutzer"
                                buttonType={ButtonType.PrimaryButton}
                            />
                        )}
                        {/* Leave user management and return to recipe list. @todo handle unsaved changes?*/}
                        <ButtonLink icon={X} to={getRecipeListUrl()}/>
                    </ButtonGroupLayout>
                </StickyHeader>

                <ContentBody className="p-0">
                    <div className="flex flex-col md:flex-row min-h-[500px]">
                        {/* User List - Left side, no padding */}
                        <div className="md:w-2/5 lg:w-1/3">
                            <UserList
                                users={users}
                                selectedUser={selectedUser}
                                onSelectUser={handleSelectUser}
                            />
                        </div>

                        {/* Edit Form - Right side, takes remaining space */}
                        <div className="md:w-3/5 lg:w-2/3">
                            {selectedUser ? (
                                <UserEditForm
                                    user={selectedUser}
                                    isAdmin={isAdmin}
                                    isSaving={isSaving}
                                    onSave={handleSave}
                                    onCancel={loadData}
                                    onOpenPasswordModal={openPasswordModal}
                                />
                            ) : (
                                <div className="px-6 py-4">
                                    <p className="text-gray-600">Bitte einen Benutzer auswählen.</p>
                                </div>
                            )}
                        </div>
                    </div>
                </ContentBody>

                {/* Password Change Modal */}
                {isPasswordModalOpen && (
                    <ChangePasswordModal
                        userId={selectedUser?.id}
                        onClose={() => setIsPasswordModalOpen(false)}
                    />
                )}

                {/* Error Popup */}
                {error && (
                    <ErrorPopup message={error} onClose={() => setError(null)}/>
                )}
            </ContentBackground>
        </PageContainer>
    );
}