import { useCallback, useEffect, useMemo, useState } from "react";
import { getCPConfig, listCPApplications, listCPRelationships, updateCPConfig } from "@/features/cp-config/api";
import { useCPConfigAbilities } from "@/features/cp-config/permissions.js";
import { listResourceGroups } from "@/features/resources/api";
import { useToast } from "@/shared/ui/ToastProvider.jsx";

export const cpRelationTypes = ["cp", "brother", "sister"];
export const cpRelationLabels = {
    cp: "CP",
    brother: "兄弟",
    sister: "姐妹",
};

const defaultExpireHours = 24;
const defaultThresholds = [0, 10000, 30000, 60000, 100000];
const listPageSize = 50;
const emptyListPage = () => ({ items: [], page: 1, pageSize: listPageSize, serverTimeMs: 0, total: 0 });

export function useCPConfigPage() {
    const abilities = useCPConfigAbilities();
    const { showToast } = useToast();
    const [activeTab, setActiveTabValue] = useState("relationships");
    const [relationships, setRelationships] = useState(emptyListPage);
    const [applications, setApplications] = useState(emptyListPage);
    const [relationshipsLoading, setRelationshipsLoading] = useState(false);
    const [applicationsLoading, setApplicationsLoading] = useState(false);
    const [relationshipsError, setRelationshipsError] = useState("");
    const [applicationsError, setApplicationsError] = useState("");
    const [applicationsLoaded, setApplicationsLoaded] = useState(false);
    const [config, setConfig] = useState({ relations: defaultRelations() });
    const [form, setForm] = useState({
        relations: defaultRelations().map(relationToForm),
    });
    const [drawerOpen, setDrawerOpen] = useState(false);
    const [loading, setLoading] = useState(false);
    const [resourceGroups, setResourceGroups] = useState([]);
    const [saving, setSaving] = useState(false);

    const activeRelationCount = useMemo(
        () => (config.relations || []).filter((relation) => relation.status === "active").length,
        [config.relations],
    );

    const reloadConfig = useCallback(async () => {
        setLoading(true);
        try {
            const [configResult, groupResult] = await Promise.allSettled([
                getCPConfig(),
                listResourceGroups({ page: 1, page_size: 200, status: "active" }),
            ]);
            if (configResult.status === "fulfilled") {
                const remoteConfig = configResult.value;
                const relations = completeRelations(remoteConfig.relations || []);
                setConfig({ ...remoteConfig, relations });
                setForm({ relations: relations.map(relationToForm) });
            } else {
                showToast(configResult.reason?.message || "加载 CP 配置失败", "error");
            }
            if (groupResult.status === "fulfilled") {
                setResourceGroups(groupResult.value?.items || []);
            } else {
                showToast(groupResult.reason?.message || "加载资源组失败", "error");
            }
        } catch (err) {
            showToast(err.message || "加载 CP 配置失败", "error");
        } finally {
            setLoading(false);
        }
    }, [showToast]);

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

    const loadRelationships = useCallback(
        async (page = 1) => {
            const normalizedPage = Number(page || 1);
            if (normalizedPage <= 1) {
                setRelationshipsLoading(true);
                setRelationshipsError("");
            }
            try {
                const result = await listCPRelationships({ page: normalizedPage, page_size: listPageSize });
                setRelationships((current) =>
                    normalizedPage > 1
                        ? { ...result, items: [...(current.items || []), ...(result.items || [])] }
                        : result,
                );
            } catch (err) {
                const message = err.message || "加载用户关系列表失败";
                if (normalizedPage <= 1) {
                    setRelationshipsError(message);
                } else {
                    showToast(message, "error");
                }
            } finally {
                if (normalizedPage <= 1) {
                    setRelationshipsLoading(false);
                }
            }
        },
        [showToast],
    );

    const loadApplications = useCallback(
        async (page = 1) => {
            const normalizedPage = Number(page || 1);
            if (normalizedPage <= 1) {
                setApplicationsLoading(true);
                setApplicationsError("");
            }
            try {
                const result = await listCPApplications({ page: normalizedPage, page_size: listPageSize });
                setApplications((current) =>
                    normalizedPage > 1
                        ? { ...result, items: [...(current.items || []), ...(result.items || [])] }
                        : result,
                );
                setApplicationsLoaded(true);
            } catch (err) {
                const message = err.message || "加载 CP 申请列表失败";
                if (normalizedPage <= 1) {
                    setApplicationsError(message);
                } else {
                    showToast(message, "error");
                }
            } finally {
                if (normalizedPage <= 1) {
                    setApplicationsLoading(false);
                }
            }
        },
        [showToast],
    );

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

    const setActiveTab = useCallback(
        (tab) => {
            setActiveTabValue(tab);
            if (tab === "applications" && !applicationsLoaded) {
                void loadApplications(1);
            }
        },
        [applicationsLoaded, loadApplications],
    );

    const reloadActiveTab = useCallback(() => {
        if (activeTab === "applications") {
            void loadApplications(1);
            return;
        }
        void loadRelationships(1);
    }, [activeTab, loadApplications, loadRelationships]);

    const reload = useCallback(async () => {
        await Promise.allSettled([
            reloadConfig(),
            activeTab === "applications" ? loadApplications(1) : loadRelationships(1),
        ]);
    }, [activeTab, loadApplications, loadRelationships, reloadConfig]);

    const openDrawer = () => {
        setForm({
            relations: completeRelations(config.relations || []).map(relationToForm),
        });
        setDrawerOpen(true);
    };

    const closeDrawer = () => {
        if (saving) {
            return;
        }
        setForm({
            relations: completeRelations(config.relations || []).map(relationToForm),
        });
        setDrawerOpen(false);
    };

    const updateRelation = (relationType, patch) => {
        setForm((current) => ({
            ...current,
            relations: (current.relations || []).map((relation) =>
                relation.relationType === relationType ? { ...relation, ...patch } : relation,
            ),
        }));
    };

    const updateLevel = (relationType, levelNumber, patch) => {
        setForm((current) => ({
            ...current,
            relations: (current.relations || []).map((relation) =>
                relation.relationType === relationType
                    ? {
                          ...relation,
                          levels: (relation.levels || []).map((level) =>
                              Number(level.level) === Number(levelNumber) ? { ...level, ...patch } : level,
                          ),
                      }
                    : relation,
            ),
        }));
    };

    const submit = async (event) => {
        event.preventDefault();
        if (!abilities.canUpdate) {
            return;
        }
        let payload;
        try {
            payload = payloadFromForm(form);
        } catch (err) {
            showToast(err.message || "CP 配置参数不正确", "error");
            return;
        }
        setSaving(true);
        try {
            const saved = await updateCPConfig(payload);
            const relations = completeRelations(saved.relations || []);
            setConfig({ ...saved, relations });
            setForm({ relations: relations.map(relationToForm) });
            setDrawerOpen(false);
            showToast("CP 配置已保存", "success");
        } catch (err) {
            showToast(err.message || "保存 CP 配置失败", "error");
        } finally {
            setSaving(false);
        }
    };

    return {
        abilities,
        activeTab,
        activeRelationCount,
        applications,
        applicationsError,
        applicationsLoading,
        closeDrawer,
        config,
        drawerOpen,
        form,
        loading,
        loadApplications,
        loadRelationships,
        openDrawer,
        reload,
        reloadActiveTab,
        relationships,
        relationshipsError,
        relationshipsLoading,
        resourceGroups,
        saving,
        setActiveTab,
        submit,
        updateLevel,
        updateRelation,
    };
}

export function defaultRelations() {
    return cpRelationTypes.map((relationType) => ({
        relationType,
        displayName: cpRelationLabels[relationType],
        maxCountPerUser: relationType === "cp" ? 1 : 5,
        applicationExpireHours: defaultExpireHours,
        breakupCostCoins: 0,
        status: "active",
        levels: defaultLevels(),
        updatedAtMs: 0,
    }));
}

function defaultLevels() {
    return defaultThresholds.map((threshold, index) => ({
        level: index + 1,
        intimacyThreshold: threshold,
        rewardResourceGroupId: 0,
        levelIconUrl: "",
        status: "active",
        updatedAtMs: 0,
    }));
}

function completeRelations(relations) {
    const byType = new Map((relations || []).map((relation) => [relation.relationType, relation]));
    return defaultRelations().map((fallback) => {
        const relation = { ...fallback, ...(byType.get(fallback.relationType) || {}) };
        if (relation.relationType === "cp") {
            relation.maxCountPerUser = 1;
        }
        relation.displayName = relation.displayName || cpRelationLabels[relation.relationType];
        relation.levels = completeLevels(relation.levels || []);
        return relation;
    });
}

function completeLevels(levels) {
    const byLevel = new Map((levels || []).map((level) => [Number(level.level), level]));
    return defaultLevels().map((fallback) => ({
        ...fallback,
        ...(byLevel.get(fallback.level) || {}),
        level: fallback.level,
    }));
}

function relationToForm(relation) {
    return {
        relationType: relation.relationType,
        displayName: relation.displayName || cpRelationLabels[relation.relationType],
        maxCountPerUser: relation.relationType === "cp" ? "1" : String(relation.maxCountPerUser || 5),
        applicationExpireHours: String(relation.applicationExpireHours || defaultExpireHours),
        breakupCostCoins: String(relation.breakupCostCoins || 0),
        status: relation.status || "active",
        levels: completeLevels(relation.levels || []).map(levelToForm),
    };
}

function levelToForm(level) {
    return {
        level: Number(level.level || 0),
        intimacyThreshold: String(level.intimacyThreshold || 0),
        rewardResourceGroupId: level.rewardResourceGroupId ? String(level.rewardResourceGroupId) : "",
        levelIconUrl: level.levelIconUrl || "",
        status: level.status || "active",
    };
}

function payloadFromForm(form) {
    const relations = completeFormRelations(form.relations || []).map((relation) => {
        const relationType = relation.relationType;
        const maxCountPerUser = relationType === "cp" ? 1 : Number(relation.maxCountPerUser || 0);
        const applicationExpireHours = Number(relation.applicationExpireHours || 0);
        const breakupCostCoins = Number(relation.breakupCostCoins || 0);
        const status = relation.status === "disabled" ? "disabled" : "active";
        if (!Number.isInteger(maxCountPerUser) || maxCountPerUser <= 0) {
            throw new Error(`${cpRelationLabels[relationType]}数量必须大于 0`);
        }
        if (!Number.isInteger(applicationExpireHours) || applicationExpireHours <= 0) {
            throw new Error(`${cpRelationLabels[relationType]}申请过期小时必须大于 0`);
        }
        if (!Number.isInteger(breakupCostCoins) || breakupCostCoins < 0) {
            throw new Error(`${cpRelationLabels[relationType]}解除费用不能小于 0`);
        }
        return {
            relationType,
            maxCountPerUser,
            applicationExpireHours,
            breakupCostCoins,
            status,
            levels: completeFormLevels(relation.levels || [], relationType),
        };
    });
    return { relations };
}

function completeFormRelations(relations) {
    const byType = new Map((relations || []).map((relation) => [relation.relationType, relation]));
    return defaultRelations().map((fallback) => ({
        ...relationToForm(fallback),
        ...(byType.get(fallback.relationType) || {}),
    }));
}

function completeFormLevels(levels, relationType) {
    const byLevel = new Map((levels || []).map((level) => [Number(level.level), level]));
    let previous = -1;
    return defaultLevels().map((fallback) => {
        const level = { ...levelToForm(fallback), ...(byLevel.get(fallback.level) || {}) };
        const threshold = Number(level.intimacyThreshold || 0);
        const rewardResourceGroupId = Number(level.rewardResourceGroupId || 0);
        if (!Number.isInteger(threshold) || threshold < 0) {
            throw new Error(`${cpRelationLabels[relationType]}${fallback.level}级亲密值不能小于 0`);
        }
        if (threshold <= previous) {
            throw new Error(`${cpRelationLabels[relationType]}等级亲密值必须递增`);
        }
        if (!Number.isInteger(rewardResourceGroupId) || rewardResourceGroupId < 0) {
            throw new Error(`${cpRelationLabels[relationType]}${fallback.level}级奖励资源组不正确`);
        }
        previous = threshold;
        return {
            level: fallback.level,
            intimacyThreshold: threshold,
            rewardResourceGroupId,
            levelIconUrl: String(level.levelIconUrl || "").trim(),
            status: level.status === "disabled" ? "disabled" : "active",
        };
    });
}
