import { useCallback, useMemo, useState } from "react";
import { parseForm } from "@/shared/forms/validation";
import { useAdminQuery } from "@/shared/hooks/useAdminQuery.js";
import { useConfirm } from "@/shared/ui/ConfirmProvider.jsx";
import { useToast } from "@/shared/ui/ToastProvider.jsx";
import {
    createRole,
    deleteRole,
    listPermissions,
    listRoles,
    replaceRolePermissions,
    updateRole,
} from "@/features/roles/api";
import { useRoleAbilities } from "@/features/roles/permissions.js";
import { roleFormSchema } from "@/features/roles/schema";

const emptyRole = { code: "", description: "", name: "", permissionIds: [] };
const emptyData = { permissions: [], roles: [] };
const permissionGroupDefinitions = [
    { key: "overview", prefixes: ["overview"], title: "总览" },
    { key: "users", prefixes: ["user"], title: "后台用户" },
    { key: "teams", prefixes: ["team"], title: "团队配置" },
    { key: "roles", prefixes: ["role"], title: "角色配置" },
    { key: "menus", prefixes: ["menu", "permission"], title: "菜单权限" },
    { key: "app-users", prefixes: ["app-user", "level-config", "region-block"], title: "APP 用户" },
    { key: "rooms", prefixes: ["room", "room-pin", "room-config"], title: "房间管理" },
    { key: "app-config", prefixes: ["app-config", "app-version"], title: "APP 配置" },
    {
        key: "resources",
        prefixes: ["resource", "resource-shop", "resource-group", "resource-grant", "gift", "emoji-pack"],
        title: "资源管理",
    },
    {
        key: "operations",
        prefixes: [
            "coin-ledger",
            "coin-seller-ledger",
            "coin-adjustment",
            "external-admin-user",
            "report",
            "gift-diamond",
        ],
        title: "运营管理",
    },
    { key: "payment", prefixes: ["payment-bill", "payment-product", "payment-third-party"], title: "支付管理" },
    {
        key: "activities",
        prefixes: [
            "activity-template",
            "achievement",
            "agency-opening",
            "cp-config",
            "cumulative-recharge-reward",
            "daily-task",
            "first-recharge-reward",
            "invite-activity-reward",
            "lucky-gift",
            "red-packet",
            "registration-reward",
            "room-rocket",
            "room-turnover-reward",
            "seven-day-checkin",
            "user-leaderboard",
            "vip-config",
            "weekly-star",
        ],
        title: "运营活动",
    },
    { key: "games", prefixes: ["game"], title: "游戏管理" },
    { key: "countries", prefixes: ["country"], title: "国家管理" },
    { key: "regions", prefixes: ["region"], title: "区域管理" },
    {
        key: "host-org",
        prefixes: [
            "agency",
            "bd",
            "coin-seller",
            "host",
            "host-agency-policy",
            "host-salary-settlement",
            "team-salary-policy",
        ],
        title: "团队管理",
    },
    { key: "logs", prefixes: ["log"], title: "日志审计" },
    { key: "common", prefixes: ["upload"], title: "通用能力" },
];
const fallbackPermissionGroup = { key: "other", title: "其他权限" };
const permissionKindOrder = { menu: 1, button: 2, api: 3 };
const permissionActionOrder = {
    view: 1,
    create: 2,
    update: 3,
    status: 4,
    publish: 5,
    grant: 6,
    permission: 7,
    "data-scope": 8,
    sort: 9,
    visible: 10,
    "reset-password": 11,
    password: 12,
    export: 13,
    sync: 14,
    settle: 15,
    retry: 16,
    cancel: 17,
    "stock-credit": 18,
    "exchange-rate": 19,
    delete: 20,
    manage: 21,
};

export function useRolesPage() {
    const [query, setQuery] = useState("");
    const [drawerOpen, setDrawerOpen] = useState(false);
    const [editingRole, setEditingRole] = useState(null);
    const [form, setForm] = useState(emptyRole);
    const abilities = useRoleAbilities();
    const confirm = useConfirm();
    const { showToast } = useToast();

    const queryFn = useCallback(async () => {
        const roleData = await listRoles();
        const permissionData = abilities.canLoadPermissions ? await listPermissions() : [];
        return { permissions: permissionData || [], roles: roleData || [] };
    }, [abilities.canLoadPermissions]);

    const { data, error, loading, reload } = useAdminQuery(queryFn, {
        errorMessage: "加载角色失败",
        initialData: emptyData,
        keepPreviousData: true,
        queryKey: ["roles", abilities.canLoadPermissions],
    });

    const permissionGroups = useMemo(() => {
        return groupPermissionsByMenu(data.permissions || []);
    }, [data.permissions]);

    const roles = useMemo(() => {
        const keyword = query.trim().toLowerCase();
        const items = data.roles || [];
        if (!keyword) {
            return items;
        }
        return items.filter((role) => {
            return [role.name, role.code, role.description].some((value) =>
                String(value || "")
                    .toLowerCase()
                    .includes(keyword),
            );
        });
    }, [data.roles, query]);

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

    const resetFilters = () => {
        setQuery("");
    };

    const openCreate = () => {
        setEditingRole(null);
        setForm(emptyRole);
        setDrawerOpen(true);
    };

    const openEdit = (role) => {
        setEditingRole(role);
        setForm({
            code: role.code,
            description: role.description || "",
            name: role.name,
            permissionIds: role.permissions?.map((permission) => permission.id) || [],
        });
        setDrawerOpen(true);
    };

    const closeDrawer = () => {
        setDrawerOpen(false);
    };

    const submit = async (event) => {
        event.preventDefault();
        try {
            const payload = parseForm(roleFormSchema, form);
            if (editingRole) {
                if (abilities.canUpdate) {
                    await updateRole(editingRole.id, {
                        code: payload.code,
                        description: payload.description,
                        name: payload.name,
                    });
                }
                if (abilities.canGrant) {
                    await replaceRolePermissions(editingRole.id, payload.permissionIds);
                }
                showToast("角色已更新", "success");
            } else {
                await createRole({
                    code: payload.code,
                    description: payload.description,
                    name: payload.name,
                    permissionIds: abilities.canGrant ? payload.permissionIds : [],
                });
                showToast("角色已创建", "success");
            }
            setDrawerOpen(false);
            reload();
        } catch (err) {
            showToast(err.message || "保存角色失败", "error");
        }
    };

    const remove = async (role) => {
        const ok = await confirm({
            confirmText: "删除",
            message: `${role.name} 删除前需要先解绑用户。`,
            title: "删除角色",
            tone: "danger",
        });
        if (!ok) {
            return;
        }
        try {
            await deleteRole(role.id);
            showToast("角色已删除", "success");
            reload();
        } catch (err) {
            showToast(err.message || "删除角色失败", "error");
        }
    };

    const togglePermission = (permissionId, checked) => {
        if (!abilities.canGrant) {
            return;
        }
        setForm((current) => ({
            ...current,
            permissionIds: checked
                ? Array.from(new Set([...current.permissionIds, permissionId]))
                : current.permissionIds.filter((id) => id !== permissionId),
        }));
    };

    const togglePermissionGroup = (permissionIds, checked) => {
        if (!abilities.canGrant) {
            return;
        }
        setForm((current) => {
            const targetIds = new Set(permissionIds);

            return {
                ...current,
                permissionIds: checked
                    ? Array.from(new Set([...current.permissionIds, ...permissionIds]))
                    : current.permissionIds.filter((id) => !targetIds.has(id)),
            };
        });
    };

    return {
        abilities,
        changeQuery,
        closeDrawer,
        drawerOpen,
        editingRole,
        error,
        form,
        loading,
        openCreate,
        openEdit,
        permissionGroups,
        permissions: data.permissions || [],
        query,
        reload,
        remove,
        resetFilters,
        roles,
        setForm,
        submit,
        togglePermission,
        togglePermissionGroup,
    };
}

function groupPermissionsByMenu(permissions) {
    const groups = new Map(
        permissionGroupDefinitions.map((definition) => [definition.key, { ...definition, items: [] }]),
    );
    const prefixToGroup = new Map(
        permissionGroupDefinitions.flatMap((definition) =>
            definition.prefixes.map((prefix) => [prefix, definition.key]),
        ),
    );
    const fallbackGroup = { ...fallbackPermissionGroup, items: [] };

    permissions.forEach((permission) => {
        const prefix = getPermissionPrefix(permission.code);
        const groupKey = prefixToGroup.get(prefix);
        const group = groupKey ? groups.get(groupKey) : fallbackGroup;
        group.items.push(permission);
    });

    return [...groups.values(), fallbackGroup]
        .filter((group) => group.items.length > 0)
        .map((group) => ({
            ...group,
            items: [...group.items].sort(comparePermissions),
        }));
}

function getPermissionPrefix(code = "") {
    return code.split(":")[0] || "other";
}

function comparePermissions(left, right) {
    const kindDiff = (permissionKindOrder[left.kind] || 9) - (permissionKindOrder[right.kind] || 9);
    if (kindDiff !== 0) {
        return kindDiff;
    }
    const prefixDiff = getPermissionPrefix(left.code).localeCompare(getPermissionPrefix(right.code));
    if (prefixDiff !== 0) {
        return prefixDiff;
    }
    const actionDiff = getPermissionActionOrder(left.code) - getPermissionActionOrder(right.code);
    if (actionDiff !== 0) {
        return actionDiff;
    }
    return left.code.localeCompare(right.code);
}

function getPermissionActionOrder(code = "") {
    const action = code.split(":")[1] || "";
    return permissionActionOrder[action] || 99;
}
