import { appId, BASE_URL } from "../../env";
import { LoginRes } from "./login.d";
import { wxLogin, wxRequest } from "../../utils/wx-api";

const app = getApp<IAppOption>();
const defaultAvatarUrl =
    "https://mmbiz.qpic.cn/mmbiz/icTdbqWNOwNRna42FI242Lcia07jQodd2FJGIYQfG0LAJGFxM4FbnQP6yfMxBgJ0F3YRqJCJ1aPAK2dQagdusBZg/0";

type LoginDisplayConfig = {
    showLoginImage: boolean;
};

type PartialLoginDisplayConfig = Partial<LoginDisplayConfig>;

const loginConfigKeys = [
    "login",
    "loginConfig",
    "loginPage",
    "auth",
    "authConfig",
    "authPage",
];
const WXROOM_REDIRECT_PATH_KEY = "wxroomRedirectPath";

function isPlainObject(value: unknown): value is Record<string, any> {
    return Object.prototype.toString.call(value) === "[object Object]";
}

function hasOwnValue(source: Record<string, any>, keys: string[]) {
    return keys.some((key) => source[key] !== undefined && source[key] !== null);
}

function normalizeString(value: unknown) {
    return typeof value === "string" ? value.trim() : "";
}

function normalizeBoolean(value: unknown) {
    if (typeof value === "boolean") return value;
    if (typeof value === "number") return value > 0;
    if (typeof value !== "string") return undefined;

    const normalized = value.trim().toLowerCase();
    if (["1", "true", "yes", "show", "visible", "enabled"].includes(normalized)) {
        return true;
    }
    if (["0", "false", "no", "hide", "hidden", "disabled"].includes(normalized)) {
        return false;
    }
    return undefined;
}

function normalizeSwitchValue(value: unknown) {
    const normalized = normalizeBoolean(value);
    if (normalized !== undefined) return normalized;
    if (typeof value === "string") return value.trim().length > 0;
    if (Array.isArray(value)) return value.length > 0;
    if (isPlainObject(value)) {
        const innerToggle = getBooleanValue(value, ["show", "visible", "enabled", "value"]);
        if (innerToggle !== undefined) return innerToggle;
        return !!getStringValue(value, [
            "url",
            "src",
            "image",
            "imageUrl",
            "background",
            "backgroundImage",
        ]);
    }
    return undefined;
}

function getObjectValue(source: Record<string, any>, keys: string[]) {
    for (const key of keys) {
        const value = source[key];
        if (value !== undefined && value !== null && value !== "") {
            return value;
        }
    }
    return undefined;
}

function getStringValue(source: Record<string, any>, keys: string[]):string {
    const value = getObjectValue(source, keys);
    if (value === undefined) return "";

    if (isPlainObject(value)) {
        return getStringValue(value, [
            "url",
            "src",
            "image",
            "imageUrl",
            "background",
            "backgroundImage",
        ]);
    }

    return normalizeString(value);
}

function getBooleanValue(source: Record<string, any>, keys: string[]) {
    const value = getObjectValue(source, keys);
    return normalizeBoolean(value);
}

function pushConfigCandidate(list: Record<string, any>[], value: unknown) {
    if (isPlainObject(value)) {
        list.push(value);
    }
}

function collectLoginConfigCandidates(template: unknown) {
    const candidates: Record<string, any>[] = [];
    if (!isPlainObject(template)) return candidates;

    if (
        hasOwnValue(template, [
            "showLoginImage",
            "showLoginBackground",
            "showBackgroundImage",
            "showImage",
            "imageSwitch",
            "backgroundSwitch",
            "loginImage",
            "heroImage",
            "loginBg",
            "loginBackground",
            "backgroundImage",
            "backgroundUrl",
            "background",
            "image",
        ])
    ) {
        candidates.push(template);
    }

    loginConfigKeys.forEach((key) => {
        pushConfigCandidate(candidates, template[key]);
        pushConfigCandidate(candidates, template.pageConfig?.[key]);
        pushConfigCandidate(candidates, template.pages?.[key]);
        pushConfigCandidate(candidates, template.property?.[key]);
    });

    if (Array.isArray(template.pages?.login)) {
        template.pages.login.forEach((item: any) => {
            pushConfigCandidate(candidates, item);
            pushConfigCandidate(candidates, item?.props);
        });
    }

    Object.entries(template).forEach(([key, value]) => {
        if (!/login|auth/i.test(key)) return;

        if (Array.isArray(value)) {
            value.forEach((item) => {
                if (!isPlainObject(item)) return;
                pushConfigCandidate(candidates, item);
                pushConfigCandidate(candidates, item.props);
            });
            return;
        }

        pushConfigCandidate(candidates, value);
    });

    return candidates;
}

function readLoginImageSwitch(source: Record<string, any>) {
    const imageValue = getObjectValue(source, [
        "showLoginImage",
        "showLoginBackground",
        "showBackgroundImage",
        "showImage",
        "imageSwitch",
        "backgroundSwitch",
        "loginImage",
        "heroImage",
        "loginBackground",
        "loginBg",
        "backgroundImage",
        "backgroundUrl",
        "background",
        "image",
        "imageUrl",
    ]);

    return normalizeSwitchValue(imageValue);
}

function resolveLoginDisplayConfigFromSource(source: unknown): PartialLoginDisplayConfig {
    if (!isPlainObject(source)) return {};

    const showLoginImage = readLoginImageSwitch(source);

    return {
        ...(showLoginImage !== undefined ? { showLoginImage } : {}),
    };
}

function mergeLoginDisplayConfig(
    current: PartialLoginDisplayConfig,
    next: PartialLoginDisplayConfig
) {
    return {
        ...current,
        ...(next.showLoginImage !== undefined ? { showLoginImage: next.showLoginImage } : {}),
    };
}

Page({
    data: {
        back: "",
        agree: false,
        nickFocus: true,
        showPopup: false,
        safeBottom: app.globalData.safeBottom,
        showLoginImage: false,
        userInfo: {
            avatarUrl: defaultAvatarUrl,
            nickName: "微信用户",
        },
    },

    applyLoginDisplayConfig(options: Record<string, any> = {}) {
        const template = app.globalData.template as Record<string, any> | null;
        const config = collectLoginConfigCandidates(template).reduce(
            (result, item) =>
                mergeLoginDisplayConfig(result, resolveLoginDisplayConfigFromSource(item)),
            {} as PartialLoginDisplayConfig
        );
        const optionConfig = resolveLoginDisplayConfigFromSource(options);
        const merged = mergeLoginDisplayConfig(config, optionConfig);

        this.setData({
            showLoginImage: merged.showLoginImage ?? false,
        });
    },

    async onChooseAvatar(e: any) {
        const { avatarUrl } = e.detail;
        wx.uploadFile({
            url: `${BASE_URL}/api/operation/sys-media/upload-oss`,
            filePath: avatarUrl,
            name: "media",
            success: (res: any) => {
                const { data } = JSON.parse(res.data);
                this.setData({
                    userInfo: {
                        ...this.data.userInfo,
                        avatarUrl: data,
                    },
                });
            },
            fail: () => {
                wx.showToast({
                    title: "上传头像失败",
                    icon: "none",
                });
            },
        });
    },

    buildQueryString(params: Record<string, any>): string {
        return Object.entries(params)
            .map(
                ([key, value]) =>
                    `${encodeURIComponent(key)}=${encodeURIComponent(value)}`
            )
            .join("&");
    },

    redirectUrl() {
        const self = this;
        let fullPath = "";
        const tabPages = [
            "/pages/tab-bar/medicine-box/index",
            "/pages/tab-bar/shopping-cart/shopping-cart",
            "/pages/tab-bar/course/course",
            "/pages/tab-bar/user/user",
            "/pages/tab-bar/points-mall/points-mall",
            "/pages/tab-bar/category/category",
        ];

        if (self.data.back) {
            if (self.data.back === "wxroom") {
                fullPath =
                    wx.getStorageSync(WXROOM_REDIRECT_PATH_KEY) ||
                    "/package-live/wxroom/index";
                wx.removeStorageSync(WXROOM_REDIRECT_PATH_KEY);
            } else {
            const store = app.globalData.store;
            const state = wx.getStorageSync("state") ?? undefined;
            const code = wx.getStorageSync("code") ?? undefined;
            const groupId = wx.getStorageSync("groupId") ?? undefined;

            if (state && !code) {
                if (self.data.back === "video") {
                    const storeParams =
                        typeof store === "string" ? store : this.buildQueryString(store);
                    fullPath = `/pages/live/video/video?${storeParams}`;
                } else if (self.data.back === "red") {
                    fullPath = `/pages/common/red/red`;
                } else if (self.data.back === "user") {
                    fullPath = `/pages/tab-bar/user/user`;
                } else {
                    fullPath = `/pages/live/registration/registration?state=${state}`;
                }
            } else if (!state && code) {
                if (self.data.back === "video") {
                    const storeParams =
                        typeof store === "string" ? store : this.buildQueryString(store);
                    fullPath = `/pages/live/video/video?${storeParams}`;
                } else if (self.data.back === "red") {
                    fullPath = `/pages/common/red/red`;
                } else if (self.data.back === "user") {
                    fullPath = `/pages/tab-bar/user/user`;
                } else {
                    fullPath = `/pages/live/registration/registration?code=${code}`;
                }
            } else {
                if (self.data.back === "room") {
                    fullPath = `/pages/live/room/room?groupId=${groupId}`;
                } else if (self.data.back === "red") {
                    fullPath = `/pages/common/red/red`;
                } else if (self.data.back === "user") {
                    fullPath = `/pages/tab-bar/user/user`;
                }
            }
            }
        } else {
            const pages = getCurrentPages();
            const currentPage = pages[pages.length - 2];

            if (!currentPage) {
                // 如果没有上一页，跳转到第一个可用 tab，而不是硬编码的 index
                const tabbarItems = app.globalData.tabbarItems;
                if (tabbarItems && tabbarItems.length > 0) {
                  wx.switchTab({ url: tabbarItems[0].pagePath });
                } else {
                  wx.switchTab({ url: "/pages/tab-bar/medicine-box/index" });
                }
                return;
            }

            const route = `/${currentPage.route}`;
            const options = currentPage.options || {};
            const query = this.buildQueryString(options);
            fullPath = query ? `${route}?${query}` : route;

            if (tabPages.includes(route)) {
                wx.switchTab({ url: route });
                return;
            }

            wx.redirectTo({ url: route });
            return;
        }

        if (tabPages.includes(fullPath)) {
            wx.switchTab({ url: fullPath });
        } else {
            wx.redirectTo({ url: fullPath });
        }
    },

    async handleLogin() {
        if (!this.data.agree) {
            wx.showModal({
                title: "请先勾选用户协议和隐私政策",
                icon: "none",
                success: (options) => {
                    if (options.confirm) {
                        this.setData({ agree: true });
                    }
                },
            });
            if (!this.data.agree) return;
        }

        try {
            wx.showLoading({ title: "登录中" });
            const loginRes = await wxLogin();
            if (!loginRes.code) throw new Error(loginRes.errMsg);

            const { avatarUrl, nickName } = this.data.userInfo;
            const state = wx.getStorageSync("state");
            let loginResult: LoginRes;

            if (state) {
                const reqData: Record<string, any> = {
                    state: wx.getStorageSync("state") ?? undefined,
                    ...(nickName && nickName !== "微信用户" ? { nickName } : {}),
                    ...(avatarUrl && avatarUrl !== defaultAvatarUrl ? { avatarUrl } : {}),
                };

                loginResult = await wxRequest<LoginRes>({
                    url: `${BASE_URL}/api/auth/app-login?appId=${appId}&code=${loginRes.code}`,
                    method: "POST",
                    data: reqData,
                });
            } else {
                const reqData: Record<string, any> = {
                    state: wx.getStorageSync("code") ?? undefined,
                    ...(nickName && nickName !== "微信用户" ? { nickName } : {}),
                    ...(avatarUrl && avatarUrl !== defaultAvatarUrl ? { avatarUrl } : {}),
                };

                loginResult = await wxRequest<LoginRes>({
                    url: `${BASE_URL}/api/auth/app-auth?appId=${appId}&code=${loginRes.code}`,
                    method: "POST",
                    data: reqData,
                });
            }

            if (
                loginResult?.statusCode !== 200 ||
                (loginResult.data.code && loginResult.data.code !== 200)
            ) {
                throw new Error(loginResult?.data?.msg || "登录失败");
            }

            const {
                mpUserId,
                id,
                openId,
                unionId,
                nickName: resNickName,
                avatarUrl: resAvatarUrl,
            } = loginResult.data;

            const storageData = {
                openId,
                userId: mpUserId,
                mbuId: id,
                unionId,
                userName: resNickName,
                avatarUrl: resAvatarUrl,
            };

            Object.entries(storageData).forEach(([key, value]) => {
                wx.setStorageSync(key, value);
            });

            app.globalData.isLogin = true;
            this.triggerEvent("loginSuccess", {
                userName: resNickName,
                avatarUrl: resAvatarUrl,
            });
            wx.showToast({
                title: "登录成功",
                duration: 2000,
            });
            this.redirectUrl();

        } catch (err: any) {
            console.log("登录失败:", err);
            app.globalData.isLogin = false;
            wx.showToast({
                title: `登录失败：${err.message || err.errMsg}`,
                icon: "none",
            });
        } finally {
            setTimeout(() => wx.hideToast(), 3000);
        }
    },

    handleToggleAgree() {
        this.setData({ agree: !this.data.agree });
    },

    openPrivacyContract() {
        // @ts-ignore
        wx.openPrivacyContract();
    },

    onLoad(options: any) {
        if (options.back) {
            this.setData({ back: options.back });
        }
        this.applyLoginDisplayConfig(options);
    },

    onShow() {
        setTimeout(() => {
            this.setData({ nickFocus: true });
        }, 200);
    },
});
