import { defineAsyncComponent } from "vue";
import { i18n } from "@/i18n";
import copyToClipboard from "@/scripts/copy-to-clipboard";
import { host } from "@/config";
import * as os from "@/os";
import { $i, iAmModerator } from "@/account";
import { mainRouter } from "@/router";
import { Router } from "@/nirax";
import * as Misskey from "calckey-js";
import { packed } from "magnetar-common";
import { magTransProperty } from "@/scripts-mag/mag-util";

export function getUserMenu(
    user: packed.PackUserMaybeAll | Misskey.entities.UserDetailed,
    router: Router = mainRouter,
) {
    const meId = $i ? $i.id : null;

    async function pushList() {
        const t = i18n.ts.selectList; // なぜか後で参照すると null になるので最初にメモリに確保しておく
        const lists = await os.api("users/lists/list");
        if (lists.length === 0) {
            os.alert({
                type: "error",
                text: i18n.ts.youHaveNoLists,
            });
            return;
        }
        const { canceled, result: listId } = await os.select({
            title: t,
            items: lists.map((list) => ({
                value: list.id,
                text: list.name,
            })),
        });
        if (canceled) return;
        os.apiWithDialog("users/lists/push", {
            listId: listId,
            userId: user.id,
        });
    }

    async function toggleMute() {
        if (magTransProperty(user, "mute", "isMuted")) {
            os.apiWithDialog("mute/delete", {
                userId: user.id,
            }).then(() => {
                if ("isMuted" in user) user.isMuted = false;
                else if ("mute" in user) user.mute = false;
            });
        } else {
            const { canceled, result: period } = await os.select({
                title: i18n.ts.mutePeriod,
                items: [
                    {
                        value: "indefinitely",
                        text: i18n.ts.indefinitely,
                    },
                    {
                        value: "tenMinutes",
                        text: i18n.ts.tenMinutes,
                    },
                    {
                        value: "oneHour",
                        text: i18n.ts.oneHour,
                    },
                    {
                        value: "oneDay",
                        text: i18n.ts.oneDay,
                    },
                    {
                        value: "oneWeek",
                        text: i18n.ts.oneWeek,
                    },
                ],
                default: "indefinitely",
            });
            if (canceled) return;

            const expiresAt =
                period === "indefinitely"
                    ? null
                    : period === "tenMinutes"
                      ? Date.now() + 1000 * 60 * 10
                      : period === "oneHour"
                        ? Date.now() + 1000 * 60 * 60
                        : period === "oneDay"
                          ? Date.now() + 1000 * 60 * 60 * 24
                          : period === "oneWeek"
                            ? Date.now() + 1000 * 60 * 60 * 24 * 7
                            : null;

            os.apiWithDialog("mute/create", {
                userId: user.id,
                expiresAt,
            }).then(() => {
                if ("isMuted" in user) user.isMuted = true;
                else if ("mute" in user) user.mute = true;
            });
        }
    }

    async function toggleRenoteMute(): Promise<void> {
        os.apiWithDialog(
            magTransProperty(user, "mute_renotes", "isRenoteMuted")
                ? "renote-mute/delete"
                : "renote-mute/create",
            {
                userId: user.id,
            },
        ).then(() => {
            if ("isRenoteMuted" in user)
                user.isRenoteMuted = !user.isRenoteMuted;
            else if ("mute_renotes" in user)
                user.mute_renotes = !user.mute_renotes;
        });
    }

    async function toggleBlock(): Promise<void> {
        if (
            !(await getConfirmed(
                magTransProperty(user, "you_block", "isBlocking")
                    ? i18n.ts.unblockConfirm
                    : i18n.ts.blockConfirm,
            ))
        )
            return;

        await os.apiWithDialog(
            magTransProperty(user, "you_block", "isBlocking")
                ? "blocking/delete"
                : "blocking/create",
            {
                userId: user.id,
            },
        );

        if ("isBlocking" in user) user.isBlocking = !user.isBlocking;
        else if ("you_block" in user) user.you_block = !user.you_block;

        await os.api(
            magTransProperty(user, "you_block", "isBlocking")
                ? "mute/create"
                : "mute/delete",
            {
                userId: user.id,
            },
        );

        if ("isMuted" in user) user.isMuted = user.isBlocking;
        else if ("mute" in user) user.mute = !user.mute;

        if (magTransProperty(user, "isBlocking", "you_block")) {
            await os.api("following/delete", {
                userId: user.id,
            });

            if ("isFollowing" in user) user.isFollowing = false;
            else if ("you_follow" in user) user.you_follow = false;
        }
    }

    async function toggleSilence() {
        if (
            !(await getConfirmed(
                i18n.t(
                    magTransProperty(user, "is_silenced", "isSilenced")
                        ? "unsilenceConfirm"
                        : "silenceConfirm",
                ),
            ))
        )
            return;

        os.apiWithDialog(
            magTransProperty(user, "isSilenced", "is_silenced")
                ? "admin/unsilence-user"
                : "admin/silence-user",
            {
                userId: user.id,
            },
        ).then(() => {
            if ("isSilenced" in user) user.isSilenced = !user.isSilenced;
            else if ("is_silenced" in user)
                user.is_silenced = !user.is_silenced;
        });
    }

    async function toggleSuspend() {
        if (
            !(await getConfirmed(
                i18n.t(
                    magTransProperty(user, "is_suspended", "isSuspended")
                        ? "unsuspendConfirm"
                        : "suspendConfirm",
                ),
            ))
        )
            return;

        os.apiWithDialog(
            magTransProperty(user, "is_suspended", "isSuspended")
                ? "admin/unsuspend-user"
                : "admin/suspend-user",
            {
                userId: user.id,
            },
        ).then(() => {
            if ("isSuspended" in user) user.isSuspended = !user.isSuspended;
            else if ("is_suspended" in user)
                user.is_suspended = !user.is_suspended;
        });
    }

    function reportAbuse() {
        os.popup(
            defineAsyncComponent(
                () => import("@/components/MkAbuseReportWindow.vue"),
            ),
            {
                user: user,
            },
            {},
            "closed",
        );
    }

    async function getConfirmed(text: string): Promise<boolean> {
        const confirm = await os.confirm({
            type: "warning",
            title: "confirm",
            text,
        });

        return !confirm.canceled;
    }

    async function invalidateFollow() {
        if (!(await getConfirmed(i18n.ts.breakFollowConfirm))) return;

        os.apiWithDialog("following/invalidate", {
            userId: user.id,
        }).then(() => {
            if ("isFollowed" in user) user.isFollowed = !user.isFollowed;
            else if ("follows_you" in user)
                user.follows_you = !user.follows_you;
        });
    }

    let menu = [
        {
            type: "label",
            text: user.host
                ? `@${user.username}@${user.host || host}`
                : `@${user.username}`,
        },
        {
            icon: "ph-at ph-bold ph-lg",
            text: i18n.ts.copyUsername,
            action: () => {
                copyToClipboard(`@${user.username}@${user.host || host}`);
            },
        },
        {
            icon: "ph-info ph-bold ph-lg",
            text: i18n.ts.info,
            action: () => {
                router.push(`/user-info/${user.id}`);
            },
        },
        {
            icon: "ph-envelope-simple-open ph-bold ph-lg",
            text: i18n.ts.sendMessage,
            action: () => {
                os.post({ specified: user });
            },
        },
        {
            icon: "ph-list-bullets ph-bold ph-lg",
            text: i18n.ts.addToList,
            action: pushList,
        },
        {
            icon: magTransProperty(user, "mute_renotes", "isRenoteMuted")
                ? "ph-eye ph-bold ph-lg"
                : "ph-eye-slash ph-bold ph-lg",
            text: magTransProperty(user, "mute_renotes", "isRenoteMuted")
                ? i18n.ts.renoteUnmute
                : i18n.ts.renoteMute,
            action: toggleRenoteMute,
        },
    ] as any;

    if ($i && meId !== user.id) {
        menu = menu.concat([
            {
                icon: magTransProperty(user, "mute", "isMuted")
                    ? "ph-eye ph-bold ph-lg"
                    : "ph-eye-slash ph-bold ph-lg",
                text: magTransProperty(user, "mute", "isMuted")
                    ? i18n.ts.unmute
                    : i18n.ts.mute,
                hidden:
                    magTransProperty(user, "you_block", "isBlocking") === true,
                action: toggleMute,
            },
            {
                icon: "ph-prohibit ph-bold ph-lg",
                text: magTransProperty(user, "you_block", "isBlocking")
                    ? i18n.ts.unblock
                    : i18n.ts.block,
                action: toggleBlock,
            },
        ]);

        if (magTransProperty(user, "follows_you", "isFollowed")) {
            menu = menu.concat([
                {
                    icon: "ph-link-break ph-bold ph-lg",
                    text: i18n.ts.breakFollow,
                    action: invalidateFollow,
                },
            ]);
        }

        menu = menu.concat([
            null,
            {
                icon: "ph-warning-circle ph-bold ph-lg",
                text: i18n.ts.reportAbuse,
                action: reportAbuse,
            },
        ]);

        if (iAmModerator) {
            menu = menu.concat([
                null,
                {
                    icon: "ph-microphone-slash ph-bold ph-lg",
                    text: magTransProperty(user, "is_silenced", "isSilenced")
                        ? i18n.ts.unsilence
                        : i18n.ts.silence,
                    action: toggleSilence,
                },
                {
                    icon: "ph-snowflake ph-bold ph-lg",
                    text: magTransProperty(user, "is_suspended", "isSuspended")
                        ? i18n.ts.unsuspend
                        : i18n.ts.suspend,
                    action: toggleSuspend,
                },
            ]);
        }
    }

    if ($i && meId === user.id) {
        menu = menu.concat([
            null,
            {
                icon: "ph-pencil ph-bold ph-lg",
                text: i18n.ts.editProfile,
                action: () => {
                    router.push("/settings/profile");
                },
            },
        ]);
    }

    return menu;
}
