import { useEffect, useMemo, useState } from "react";
import { parseForm, FormValidationError } from "@/shared/forms/validation";
import { useAdminQuery } from "@/shared/hooks/useAdminQuery.js";
import { useToast } from "@/shared/ui/ToastProvider.jsx";
import { listRegionBlocks, replaceRegionBlocks } from "@/features/region-blocks/api";
import { useRegionBlockAbilities } from "@/features/region-blocks/permissions.js";
import {
    regionBlockIPSchema,
    regionBlockKeywordSchema,
    regionBlockReplaceSchema,
    regionBlockUserIDSchema,
} from "@/features/region-blocks/schema";

const emptyData = { items: [], total: 0, whitelistItems: [], whitelistTotal: 0, whitelistUserItems: [], whitelistUserTotal: 0 };
const countryCodePattern = /^[A-Za-z]{2,3}$/;

export function useRegionBlockPage() {
    const abilities = useRegionBlockAbilities();
    const { showToast } = useToast();
    const [keywordInput, setKeywordInput] = useState("");
    const [ipInput, setIPInput] = useState("");
    const [userIDInput, setUserIDInput] = useState("");
    const [draftKeywords, setDraftKeywords] = useState([]);
    const [draftWhitelistIPs, setDraftWhitelistIPs] = useState([]);
    const [draftWhitelistUserIDs, setDraftWhitelistUserIDs] = useState([]);
    const [dirty, setDirty] = useState(false);
    const [whitelistDialogOpen, setWhitelistDialogOpen] = useState(false);
    const [saving, setSaving] = useState(false);
    const {
        data = emptyData,
        error,
        loading,
        reload,
    } = useAdminQuery(listRegionBlocks, {
        errorMessage: "加载地区屏蔽配置失败",
        initialData: emptyData,
        queryKey: ["region-blocks"],
    });
    const serverKeywords = useMemo(() => (data.items || []).map((item) => item.keyword).filter(Boolean), [data.items]);
    const serverWhitelistIPs = useMemo(
        () => (data.whitelistItems || []).map((item) => item.ipAddress).filter(Boolean),
        [data.whitelistItems],
    );
    const serverWhitelistUserIDs = useMemo(
        () => (data.whitelistUserItems || []).map((item) => item.userId).filter(Boolean),
        [data.whitelistUserItems],
    );
    const serverKeywordKey = serverKeywords.join("\n");
    const serverWhitelistKey = serverWhitelistIPs.join("\n");
    const serverWhitelistUserKey = serverWhitelistUserIDs.join("\n");
    const serverBlockByKeyword = useMemo(() => {
        const blocks = new Map();
        (data.items || []).forEach((item) => blocks.set(normalizeKey(item.keyword), item));
        return blocks;
    }, [data.items]);
    const serverWhitelistByIP = useMemo(() => {
        const items = new Map();
        (data.whitelistItems || []).forEach((item) => items.set(normalizeKey(item.ipAddress), item));
        return items;
    }, [data.whitelistItems]);
    const serverWhitelistByUserID = useMemo(() => {
        const items = new Map();
        (data.whitelistUserItems || []).forEach((item) => items.set(normalizeKey(item.userId), item));
        return items;
    }, [data.whitelistUserItems]);

    useEffect(() => {
        if (!dirty) {
            setDraftKeywords(serverKeywords);
            setDraftWhitelistIPs(serverWhitelistIPs);
            setDraftWhitelistUserIDs(serverWhitelistUserIDs);
        }
    }, [dirty, serverKeywordKey, serverKeywords, serverWhitelistIPs, serverWhitelistKey, serverWhitelistUserIDs, serverWhitelistUserKey]);

    const draftItems = useMemo(
        () =>
            draftKeywords.map((keyword, index) => {
                const saved = serverBlockByKeyword.get(normalizeKey(keyword));
                return (
                    saved || {
                        blockId: `draft-${index}-${keyword}`,
                        countryCode: countryCodePattern.test(keyword) ? keyword.toUpperCase() : "",
                        createdAtMs: 0,
                        enabled: true,
                        keyword,
                        updatedAtMs: 0,
                    }
                );
            }),
        [draftKeywords, serverBlockByKeyword],
    );
    const draftWhitelistItems = useMemo(
        () =>
            draftWhitelistIPs.map((ip, index) => {
                const saved = serverWhitelistByIP.get(normalizeKey(ip));
                return (
                    saved || {
                        whitelistId: `draft-${index}-${ip}`,
                        ipAddress: ip,
                        createdAtMs: 0,
                        enabled: true,
                        updatedAtMs: 0,
                    }
                );
            }),
        [draftWhitelistIPs, serverWhitelistByIP],
    );
    const draftWhitelistUserItems = useMemo(
        () =>
            draftWhitelistUserIDs.map((userID, index) => {
                const saved = serverWhitelistByUserID.get(normalizeKey(userID));
                return (
                    saved || {
                        whitelistId: `draft-user-${index}-${userID}`,
                        userId: userID,
                        displayUserId: "",
                        createdAtMs: 0,
                        enabled: true,
                        updatedAtMs: 0,
                    }
                );
            }),
        [draftWhitelistUserIDs, serverWhitelistByUserID],
    );

    const addKeyword = () => {
        if (!abilities.canUpdate) {
            return;
        }
        try {
            const keyword = parseForm(regionBlockKeywordSchema, keywordInput);
            if (draftKeywords.some((item) => normalizeKey(item) === normalizeKey(keyword))) {
                showToast("屏蔽词已存在", "warning");
                return;
            }
            setDraftKeywords([...draftKeywords, normalizeKeyword(keyword)]);
            setKeywordInput("");
            setDirty(true);
        } catch (err) {
            showValidationError(err, showToast, "屏蔽词参数不正确");
        }
    };

    const submitInput = (event) => {
        event.preventDefault();
        addKeyword();
    };

    const addIP = () => {
        if (!abilities.canUpdate) {
            return;
        }
        try {
            const ip = parseForm(regionBlockIPSchema, ipInput);
            if (draftWhitelistIPs.some((item) => normalizeKey(item) === normalizeKey(ip))) {
                showToast("白名单 IP 已存在", "warning");
                return;
            }
            setDraftWhitelistIPs([...draftWhitelistIPs, ip]);
            setIPInput("");
            setDirty(true);
        } catch (err) {
            showValidationError(err, showToast, "IP 参数不正确");
        }
    };

    const submitIPInput = (event) => {
        event.preventDefault();
        addIP();
    };

    const addUserID = () => {
        if (!abilities.canUpdate) {
            return;
        }
        try {
            const userID = parseForm(regionBlockUserIDSchema, userIDInput);
            if (draftWhitelistUserIDs.some((item) => normalizeKey(item) === normalizeKey(userID))) {
                showToast("白名单用户已存在", "warning");
                return;
            }
            setDraftWhitelistUserIDs([...draftWhitelistUserIDs, userID]);
            setUserIDInput("");
            setDirty(true);
        } catch (err) {
            showValidationError(err, showToast, "用户 ID/短 ID/靓号参数不正确");
        }
    };

    const submitUserIDInput = (event) => {
        event.preventDefault();
        addUserID();
    };

    const removeKeyword = (keyword) => {
        if (!abilities.canUpdate) {
            return;
        }
        setDraftKeywords(draftKeywords.filter((item) => normalizeKey(item) !== normalizeKey(keyword)));
        setDirty(true);
    };

    const removeIP = (ip) => {
        if (!abilities.canUpdate) {
            return;
        }
        setDraftWhitelistIPs(draftWhitelistIPs.filter((item) => normalizeKey(item) !== normalizeKey(ip)));
        setDirty(true);
    };

    const removeUserID = (userID) => {
        if (!abilities.canUpdate) {
            return;
        }
        setDraftWhitelistUserIDs(draftWhitelistUserIDs.filter((item) => normalizeKey(item) !== normalizeKey(userID)));
        setDirty(true);
    };

    const resetDraft = () => {
        setDraftKeywords(serverKeywords);
        setDraftWhitelistIPs(serverWhitelistIPs);
        setDraftWhitelistUserIDs(serverWhitelistUserIDs);
        setKeywordInput("");
        setIPInput("");
        setUserIDInput("");
        setDirty(false);
    };

    const save = async () => {
        if (!abilities.canUpdate || saving) {
            return;
        }
        setSaving(true);
        try {
            const payload = parseForm(regionBlockReplaceSchema, {
                keywords: draftKeywords,
                whitelist_ips: draftWhitelistIPs,
                whitelist_user_ids: draftWhitelistUserIDs,
            });
            const saved = await replaceRegionBlocks(payload);
            setDraftKeywords((saved.items || []).map((item) => item.keyword).filter(Boolean));
            setDraftWhitelistIPs((saved.whitelistItems || []).map((item) => item.ipAddress).filter(Boolean));
            setDraftWhitelistUserIDs((saved.whitelistUserItems || []).map((item) => item.userId).filter(Boolean));
            setDirty(false);
            showToast("地区屏蔽配置已保存", "success");
            await reload();
        } catch (err) {
            showValidationError(err, showToast, "保存地区屏蔽配置失败");
        } finally {
            setSaving(false);
        }
    };

    return {
        abilities,
        addIP,
        addKeyword,
        addUserID,
        dirty,
        draftItems,
        draftWhitelistItems,
        draftWhitelistUserItems,
        error,
        ipInput,
        keywordInput,
        loading,
        openWhitelistDialog: () => setWhitelistDialogOpen(true),
        reload,
        removeIP,
        removeKeyword,
        removeUserID,
        resetDraft,
        save,
        saving,
        setIPInput,
        setKeywordInput,
        setUserIDInput,
        submitIPInput,
        submitInput,
        submitUserIDInput,
        userIDInput,
        whitelistDialogOpen,
        closeWhitelistDialog: () => setWhitelistDialogOpen(false),
    };
}

function normalizeKeyword(value) {
    const keyword = value.trim();
    return countryCodePattern.test(keyword) ? keyword.toUpperCase() : keyword;
}

function normalizeKey(value) {
    return String(value || "").trim().toLowerCase();
}

function showValidationError(err, showToast, fallback) {
    if (err instanceof FormValidationError) {
        showToast(err.message, "error");
        return;
    }
    showToast(err?.message || fallback, "error");
}
