import { useCallback, useEffect, useMemo, useState } from "react";
import { useNavigate } from "react-router-dom";
import { downloadCsv } from "@/shared/api/download";
import { toPageQuery } from "@/shared/api/query";
import { parseForm } from "@/shared/forms/validation";
import { useAdminQuery } from "@/shared/hooks/useAdminQuery.js";
import { mergePaginatedItems } from "@/shared/hooks/usePaginatedQuery.js";
import { useConfirm } from "@/shared/ui/ConfirmProvider.jsx";
import { useToast } from "@/shared/ui/ToastProvider.jsx";
import { listRoles } from "@/features/roles/api";
import { listTeams } from "@/features/teams/api";
import { listAdminApps } from "@/features/app-registry/api";
import {
    batchUpdateUserStatus,
    createUser,
    exportUsers,
    getFinanceScopeCatalog,
    getUserAppScopes,
    listFinanceScopeAssignments,
    listUserFinanceScopes,
    listUsers,
    replaceUserFinanceScopes,
    replaceUserAppScopes,
    resetUserPassword,
    updateUser,
    updateUserStatus,
} from "@/features/users/api";
import { useUserAbilities } from "@/features/users/permissions.js";
import { userCreateFormSchema, userUpdateFormSchema } from "@/features/users/schema";

const pageSize = 50;
const emptyUsers = { items: [], total: 0, page: 1, pageSize };
const emptyData = { roles: [], teams: [], users: emptyUsers };

const emptyForm = {
    appCodes: [],
    appScopeMode: "none",
    mfaEnabled: false,
    name: "",
    password: "",
    roleIds: [],
    financeScopes: [],
    status: "active",
    team: "",
    teamId: "",
    username: "",
};

export function useUsersPage() {
    const [query, setQuery] = useState("");
    const [roleFilter, setRoleFilter] = useState("");
    const [statusFilter, setStatusFilter] = useState("");
    const [page, setPage] = useState(1);
    const [selectedIds, setSelectedIds] = useState([]);
    const [formOpen, setFormOpen] = useState(false);
    const [editingUser, setEditingUser] = useState(null);
    const [profileUser, setProfileUser] = useState(null);
    const [form, setForm] = useState(emptyForm);
    const [financeScopeCatalog, setFinanceScopeCatalog] = useState({ apps: [], countries: [], error: "", loading: false, regions: [] });
    const [financeScopeAssignments, setFinanceScopeAssignments] = useState([]);
    const [appScopeCatalog, setAppScopeCatalog] = useState([]);
    const [mergedUsers, setMergedUsers] = useState(emptyUsers);
    const abilities = useUserAbilities();
    const confirm = useConfirm();
    const { showToast } = useToast();
    const navigate = useNavigate();

    const requestQuery = useMemo(
        () => toPageQuery({ keyword: query, page, pageSize, role: roleFilter, status: statusFilter }),
        [page, query, roleFilter, statusFilter],
    );

    const queryFn = useCallback(async () => {
        const [userData, roleData, teamData] = await Promise.all([
            listUsers(requestQuery),
            abilities.canViewRoles ? listRoles() : [],
            abilities.canViewTeams ? listTeams() : [],
        ]);
        setSelectedIds([]);
        return { roles: roleData || [], teams: teamData || [], users: userData || emptyUsers };
    }, [abilities.canViewRoles, abilities.canViewTeams, requestQuery]);

    const { data, error, loading: queryLoading, reload } = useAdminQuery(queryFn, {
        errorMessage: "加载用户失败",
        initialData: emptyData,
        keepPreviousData: true,
        queryKey: ["users", requestQuery, abilities.canViewRoles, abilities.canViewTeams],
    });

    useEffect(() => {
        setMergedUsers(emptyUsers);
    }, [query, roleFilter, statusFilter]);

    useEffect(() => {
        const nextUsers = data?.users || emptyUsers;
        const nextItems = Array.isArray(nextUsers.items) ? nextUsers.items : [];
        const nextPage = Number(nextUsers.page || page || 1);
        const nextPageSize = Number(nextUsers.pageSize || pageSize);
        const nextTotal = Number(nextUsers.total || 0);

        setMergedUsers((current) => {
            if (nextPage <= 1) {
                return { ...nextUsers, items: nextItems, page: nextPage, pageSize: nextPageSize, total: nextTotal };
            }

            return {
                ...nextUsers,
                items: mergePaginatedItems(current.items || [], nextItems),
                page: nextPage,
                pageSize: nextPageSize,
                total: nextTotal,
            };
        });
    }, [data?.users, page]);

    const users = mergedUsers;
    const loading = queryLoading && (users.items || []).length === 0;
    const roles = useMemo(() => data?.roles || [], [data?.roles]);
    const teams = useMemo(() => data?.teams || [], [data?.teams]);

    const roleFilters = useMemo(() => [["", "全部角色"], ...roles.map((role) => [role.name, role.name])], [roles]);

    const stats = useMemo(() => {
        const items = users.items || [];
        const active = items.filter((user) => user.status === "active").length;
        const locked = items.filter((user) => user.status === "locked").length;
        const admin = items.filter((user) => String(user.role).includes("管理员")).length;
        return { active, admin, locked };
    }, [users.items]);

    const changeQuery = (value) => {
        setQuery(value);
        setPage(1);
    };

    const changeRoleFilter = (value) => {
        setRoleFilter(value);
        setPage(1);
    };

    const changeStatusFilter = (value) => {
        setStatusFilter(value);
        setPage(1);
    };

    const resetFilters = () => {
        setQuery("");
        setRoleFilter("");
        setStatusFilter("");
        setPage(1);
    };

    const loadFinanceScopeCatalog = useCallback(async () => {
        setFinanceScopeCatalog((current) => ({ ...current, error: "", loading: true }));
        try {
            const catalog = await getFinanceScopeCatalog();
            setFinanceScopeCatalog({
                apps: Array.isArray(catalog?.apps) ? catalog.apps : [],
                countries: Array.isArray(catalog?.countries) ? catalog.countries : [],
                error: "",
                loading: false,
                regions: Array.isArray(catalog?.regions) ? catalog.regions : [],
            });
        } catch (err) {
            setFinanceScopeCatalog({ apps: [], countries: [], error: err.message || "加载财务范围失败", loading: false, regions: [] });
        }
    }, []);

    const loadFinanceScopeAssignments = useCallback(async () => {
        try {
            const data = await listFinanceScopeAssignments();
            setFinanceScopeAssignments(Array.isArray(data?.items) ? data.items : []);
        } catch (err) {
            // 拉不到分配总览时退化为旧行为（不置灰），只提示不阻塞编辑。
            setFinanceScopeAssignments([]);
            showToast(err.message || "加载财务范围分配失败", "error");
        }
    }, [showToast]);

    const loadAppScopeCatalog = useCallback(async () => {
        try {
            const data = await listAdminApps();
            setAppScopeCatalog(Array.isArray(data?.items) ? data.items : []);
        } catch (err) {
            setAppScopeCatalog([]);
            showToast(err.message || "加载 App 范围失败", "error");
        }
    }, [showToast]);

    const openCreate = () => {
        setEditingUser(null);
        setForm(emptyForm);
        setFormOpen(true);
        loadFinanceScopeCatalog();
        loadFinanceScopeAssignments();
        loadAppScopeCatalog();
    };

    const openEdit = (user) => {
        setEditingUser(user);
        setForm({
            appCodes: [],
            appScopeMode: user.appScopeMode || "none",
            mfaEnabled: user.mfaEnabled,
            name: user.name,
            password: "",
            roleIds: user.roleIds || [],
            financeScopes: [],
            status: user.status,
            team: userTeamName(user),
            teamId: resolveUserTeamId(user, teams),
            username: user.account,
        });
        setFormOpen(true);
        loadFinanceScopeCatalog();
        loadFinanceScopeAssignments();
        loadAppScopeCatalog();
        getUserAppScopes(user.id)
            .then((scope) => {
                setForm((current) =>
                    current.username === user.account
                        ? { ...current, appCodes: normalizeAppCodes(scope?.appCodes), appScopeMode: normalizeAppScopeMode(scope?.mode) }
                        : current,
                );
            })
            .catch((err) => showToast(err.message || "加载 App 范围失败", "error"));
        listUserFinanceScopes(user.id)
            .then((data) => {
                const scopes = Array.isArray(data?.items) ? data.items : [];
                setForm((current) =>
                    editingUser?.id === user.id || current.username === user.account
                        ? { ...current, financeScopes: normalizeFinanceScopes(scopes) }
                        : current,
                );
            })
            .catch((err) => showToast(err.message || "加载财务范围失败", "error"));
    };

    const closeForm = () => {
        setFormOpen(false);
    };

    const openProfile = (user) => {
        setProfileUser(user);
    };

    const closeProfile = () => {
        setProfileUser(null);
    };

    const submitUser = async (event) => {
        event.preventDefault();
        try {
            if (editingUser) {
                const payload = parseForm(userUpdateFormSchema, form);
                await updateUser(editingUser.id, payload);
                await replaceUserAppScopes(editingUser.id, normalizeAppScope(form));
                await replaceUserFinanceScopes(editingUser.id, normalizeFinanceScopes(form.financeScopes));
                showToast("用户已更新", "success");
            } else {
                const payload = parseForm(userCreateFormSchema, form);
                const result = await createUser(payload);
                if (result?.user?.id) {
                    await replaceUserAppScopes(result.user.id, normalizeAppScope(form));
                    await replaceUserFinanceScopes(result.user.id, normalizeFinanceScopes(form.financeScopes));
                }
                showToast(`用户已创建，初始密码：${result.initialPassword}`, "success");
            }
            setFormOpen(false);
            reload();
        } catch (err) {
            showToast(err.message || "保存用户失败", "error");
        }
    };

    const toggleLocked = async (user) => {
        const nextStatus = user.status === "locked" ? "active" : "locked";
        const ok = await confirm({
            confirmText: user.status === "locked" ? "解锁" : "锁定",
            message: `${user.name} 的登录状态会立即变更。`,
            title: user.status === "locked" ? "解锁用户" : "锁定用户",
            tone: user.status === "locked" ? "primary" : "danger",
        });
        if (!ok) {
            return;
        }
        await updateUserStatus(user.id, nextStatus);
        showToast("用户状态已更新", "success");
        reload();
    };

    const toggleDisabled = async (user) => {
        const nextStatus = user.status === "disabled" ? "active" : "disabled";
        const ok = await confirm({
            confirmText: user.status === "disabled" ? "启用" : "停用",
            message: `${user.name} 的账号状态会立即变更。`,
            title: user.status === "disabled" ? "启用用户" : "停用用户",
            tone: user.status === "disabled" ? "primary" : "danger",
        });
        if (!ok) {
            return;
        }
        await updateUserStatus(user.id, nextStatus);
        showToast("用户状态已更新", "success");
        reload();
    };

    const resetPassword = async (user) => {
        const ok = await confirm({
            confirmText: "重置",
            message: `${user.name} 的密码会重置为系统生成的初始密码。`,
            title: "重置密码",
            tone: "danger",
        });
        if (!ok) {
            return;
        }
        const result = await resetUserPassword(user.id);
        showToast(`已重置，初始密码：${result.initialPassword}`, "success");
    };

    const batchStatus = async (status) => {
        if (!selectedIds.length) {
            showToast("请先选择用户", "warning");
            return;
        }
        const ok = await confirm({
            confirmText: "确认",
            message: `将更新 ${selectedIds.length} 个用户状态。`,
            title: "批量更新状态",
            tone: status === "active" ? "primary" : "danger",
        });
        if (!ok) {
            return;
        }
        await batchUpdateUserStatus(selectedIds, status);
        showToast("批量状态已更新", "success");
        reload();
    };

    const downloadUsers = () => {
        return downloadCsv(
            () => exportUsers({ keyword: query, role: roleFilter, status: statusFilter }),
            "hyapp-users.csv",
        );
    };

    const setRoleChecked = (roleId, checked) => {
        setForm((current) => ({
            ...current,
            roleIds: checked ? [...current.roleIds, roleId] : current.roleIds.filter((id) => id !== roleId),
        }));
    };

    const setAppScopeMode = (mode) => {
        const normalizedMode = normalizeAppScopeMode(mode);
        setForm((current) => ({
            ...current,
            appCodes: normalizedMode === "selected" ? current.appCodes : [],
            appScopeMode: normalizedMode,
        }));
    };

    const setAppScopeChecked = (appCode, checked) => {
        const normalized = String(appCode || "").trim().toLowerCase();
        if (!normalized) {
            return;
        }
        setForm((current) => {
            // 从“全部 App”取消单项时转换为显式 selected，确保只移除目标 App，不把全部授权一次清空。
            const baseCodes = current.appScopeMode === "all"
                ? appScopeCatalog.map((app) => String(app.appCode || "").trim().toLowerCase()).filter(Boolean)
                : normalizeAppCodes(current.appCodes);
            const nextCodes = checked
                ? normalizeAppCodes([...baseCodes, normalized])
                : baseCodes.filter((code) => code !== normalized);
            return {
                ...current,
                appCodes: nextCodes,
                appScopeMode: nextCodes.length ? "selected" : "none",
            };
        });
    };

    const setFinanceScopeChecked = (appCode, regionId, checked) => {
        const normalizedAppCode = String(appCode || "").trim();
        const normalizedRegionId = Number(regionId || 0);
        if (!normalizedAppCode || normalizedRegionId < 0) {
            return;
        }
        setForm((current) => {
            const scopes = normalizeFinanceScopes(current.financeScopes);
            const exists = scopes.some((scope) => scope.appCode === normalizedAppCode && Number(scope.regionId) === normalizedRegionId);
            if (checked && !exists) {
                return { ...current, financeScopes: [...scopes, { appCode: normalizedAppCode, regionId: normalizedRegionId }] };
            }
            if (!checked && exists) {
                return {
                    ...current,
                    financeScopes: scopes.filter((scope) => !(scope.appCode === normalizedAppCode && Number(scope.regionId) === normalizedRegionId)),
                };
            }
            return current;
        });
    };

    return {
        abilities,
        appScopeCatalog,
        batchStatus,
        changeQuery,
        changeRoleFilter,
        changeStatusFilter,
        closeForm,
        closeProfile,
        downloadUsers,
        editingUser,
        error,
        financeScopeAssignments,
        financeScopeCatalog,
        form,
        formOpen,
        loading,
        navigate,
        openCreate,
        openEdit,
        openProfile,
        page,
        profileUser,
        query,
        reload,
        resetPassword,
        resetFilters,
        roleFilter,
        roleFilters,
        roles,
        selectedIds,
        setForm,
        setAppScopeChecked,
        setAppScopeMode,
        setFinanceScopeChecked,
        setPage,
        setRoleChecked,
        setSelectedIds,
        stats,
        statusFilter,
        submitUser,
        teams,
        toggleDisabled,
        toggleLocked,
        users,
    };
}

function normalizeAppScope(form) {
    const mode = normalizeAppScopeMode(form?.appScopeMode);
    return {
        mode,
        appCodes: mode === "selected" ? normalizeAppCodes(form?.appCodes) : [],
    };
}

function normalizeAppScopeMode(mode) {
    return ["all", "selected", "none"].includes(mode) ? mode : "none";
}

function normalizeAppCodes(appCodes = []) {
    return [...new Set((Array.isArray(appCodes) ? appCodes : []).map((code) => String(code || "").trim().toLowerCase()).filter(Boolean))].sort();
}

function normalizeFinanceScopes(scopes = []) {
    const seen = new Set();
    return (Array.isArray(scopes) ? scopes : [])
        .map((scope) => ({
            appCode: String(scope.appCode || scope.app_code || "").trim(),
            regionId: Number(scope.regionId ?? scope.region_id ?? 0),
        }))
        .filter((scope) => {
            if (!scope.appCode || scope.regionId < 0) {
                return false;
            }
            const key = `${scope.appCode}:${scope.regionId}`;
            if (seen.has(key)) {
                return false;
            }
            seen.add(key);
            return true;
        });
}

function userTeamName(user) {
    return String(user?.teamName || user?.team || "").trim();
}

function resolveUserTeamId(user, teams) {
    const rawId = user?.teamId ?? user?.team_id;
    if (rawId !== undefined && rawId !== null && rawId !== "") {
        return Number(rawId);
    }
    const teamName = userTeamName(user);
    const matchedTeam = (teams || []).find((team) => team.name === teamName);
    return matchedTeam?.id ? Number(matchedTeam.id) : "";
}
