<template>
	<div ref="el" class="hiyeyicy" :class="{ wide: !narrow }">
		<div v-if="!narrow || currentPage?.route.name == null" class="nav">
			<MkSpacer :content-max="700" :margin-min="16">
				<div class="lxpfedzu">
					<div class="banner">
						<img
							:src="$instance.iconUrl || '/favicon.ico'"
							alt=""
							class="icon"
						/>
					</div>

					<MkInfo
						v-if="thereIsUnresolvedAbuseReport"
						warn
						class="info"
						>{{ i18n.ts.thereIsUnresolvedAbuseReportWarning }}
						<MkA to="/admin/abuses" class="_link">{{
							i18n.ts.check
						}}</MkA></MkInfo
					>
					<MkInfo v-if="noMaintainerInformation" warn class="info"
						>{{ i18n.ts.noMaintainerInformationWarning }}
						<MkA to="/admin/settings" class="_link">{{
							i18n.ts.configure
						}}</MkA></MkInfo
					>
					<MkInfo v-if="noBotProtection" warn class="info"
						>{{ i18n.ts.noBotProtectionWarning }}
						<MkA to="/admin/security" class="_link">{{
							i18n.ts.configure
						}}</MkA></MkInfo
					>
					<MkInfo v-if="updateAvailable" warn class="info"
						>{{ i18n.ts.updateAvailable }}
						<a
							href="https://iceshrimp.dev/iceshrimp/iceshrimp/releases"
							target="_bank"
							class="_link"
							>{{ i18n.ts.check }}</a
						></MkInfo
					>

					<MkSuperMenu :def="menuDef" :grid="narrow"></MkSuperMenu>
				</div>
			</MkSpacer>
		</div>
		<div v-if="!(narrow && currentPage?.route.name == null)" class="main">
			<RouterView />
		</div>
	</div>
</template>

<script lang="ts" setup>
import {
	defineAsyncComponent,
	inject,
	nextTick,
	onMounted,
	onUnmounted,
	onActivated,
	provide,
	watch,
	ref,
} from "vue";
import { i18n } from "@/i18n";
import MkSuperMenu from "@/components/MkSuperMenu.vue";
import MkInfo from "@/components/MkInfo.vue";
import { scroll } from "@/scripts/scroll";
import { instance } from "@/instance";
import { version } from "@/config";
import { $i } from "@/account";
import * as os from "@/os";
import { lookupUser } from "@/scripts/lookup-user";
import { lookupFile } from "@/scripts/lookup-file";
import { lookupInstance } from "@/scripts/lookup-instance";
import { defaultStore } from "@/store";
import { useRouter } from "@/router";
import {
	definePageMetadata,
	provideMetadataReceiver,
	setPageMetadata,
} from "@/scripts/page-metadata";
import { isUpdateAvailable } from "@/scripts/is-update-available.js";

const isEmpty = (x: string | null) => x == null || x === "";
const el = ref<HTMLElement | null>(null);
const router = useRouter();

const indexInfo = {
	title: i18n.ts.controlPanel,
	icon: "ph-gear-six ph-bold ph-lg",
	hideHeader: true,
};

provide("shouldOmitHeaderTitle", false);

let INFO = $ref(indexInfo);
let childInfo = $ref(null);
let narrow = $ref(false);
let view = $ref(null);
let pageProps = $ref({});
let noMaintainerInformation =
	isEmpty(instance.maintainerName) || isEmpty(instance.maintainerEmail);
let noBotProtection =
	!instance.disableRegistration &&
	!instance.enableHcaptcha &&
	!instance.enableRecaptcha;
let thereIsUnresolvedAbuseReport = $ref(false);
let updateAvailable = $ref(false);
let currentPage = $computed(() => router.currentRef.value.child);

os.api("admin/abuse-user-reports", {
	state: "unresolved",
	limit: 1,
}).then((reports) => {
	if (reports?.length > 0) thereIsUnresolvedAbuseReport = true;
});

if (defaultStore.state.showAdminUpdates) {
	isUpdateAvailable().then(res => {
		updateAvailable = res;
	});
}

const NARROW_THRESHOLD = 600;
const ro = new ResizeObserver((entries, observer) => {
	if (entries.length === 0) return;
	narrow = entries[0].borderBoxSize[0].inlineSize < NARROW_THRESHOLD;
});

const menuDef = $computed(() => [
	{
		title: i18n.ts.quickAction,
		items: [
			{
				type: "button",
				icon: "ph-magnifying-glass ph-bold ph-lg",
				text: i18n.ts.lookup,
				action: lookup,
			},
			...(instance.disableRegistration
				? [
						{
							type: "button",
							icon: "ph-user-plus ph-bold ph-lg",
							text: i18n.ts.invite,
							action: invite,
						},
				  ]
				: []),
		],
	},
	{
		title: i18n.ts.administration,
		items: [
			{
				icon: "ph-gauge ph-bold ph-lg",
				text: i18n.ts.dashboard,
				to: "/admin/overview",
				active: currentPage?.route.name === "overview",
			},
			{
				icon: "ph-users ph-bold ph-lg",
				text: i18n.ts.users,
				to: "/admin/users",
				active: currentPage?.route.name === "users",
			},
			{
				icon: "ph-smiley ph-bold ph-lg",
				text: i18n.ts.customEmojis,
				to: "/admin/emojis",
				active: currentPage?.route.name === "emojis",
			},
			{
				icon: "ph-planet ph-bold ph-lg",
				text: i18n.ts.federation,
				to: "/admin/federation",
				active: currentPage?.route.name === "federation",
			},
			{
				icon: "ph-queue ph-bold ph-lg",
				text: i18n.ts.jobQueue,
				to: "/admin/queue",
				active: currentPage?.route.name === "queue",
			},
			{
				icon: "ph-cloud ph-bold ph-lg",
				text: i18n.ts.files,
				to: "/admin/files",
				active: currentPage?.route.name === "files",
			},
			{
				icon: "ph-megaphone-simple ph-bold ph-lg",
				text: i18n.ts.announcements,
				to: "/admin/announcements",
				active: currentPage?.route.name === "announcements",
			},
			{
				icon: "ph-warning-circle ph-bold ph-lg",
				text: i18n.ts.abuseReports,
				to: "/admin/abuses",
				active: currentPage?.route.name === "abuses",
			},
		],
	},
	...($i?.isAdmin
		? [
				{
					title: i18n.ts.settings,
					items: [
						{
							icon: "ph-gear-six ph-bold ph-lg",
							text: i18n.ts.general,
							to: "/admin/settings",
							active: currentPage?.route.name === "settings",
						},
						{
							icon: "ph-envelope-simple-open ph-bold ph-lg",
							text: i18n.ts.emailServer,
							to: "/admin/email-settings",
							active:
								currentPage?.route.name === "email-settings",
						},
						{
							icon: "ph-cloud ph-bold ph-lg",
							text: i18n.ts.objectStorage,
							to: "/admin/object-storage",
							active:
								currentPage?.route.name === "object-storage",
						},
						{
							icon: "ph-lock ph-bold ph-lg",
							text: i18n.ts.security,
							to: "/admin/security",
							active: currentPage?.route.name === "security",
						},
						{
							icon: "ph-arrows-merge ph-bold ph-lg",
							text: i18n.ts.relays,
							to: "/admin/relays",
							active: currentPage?.route.name === "relays",
						},
						{
							icon: "ph-plug ph-bold ph-lg",
							text: i18n.ts.integration,
							to: "/admin/integrations",
							active: currentPage?.route.name === "integrations",
						},
						{
							icon: "ph-prohibit ph-bold ph-lg",
							text: i18n.ts.instanceBlocking,
							to: "/admin/instance-block",
							active:
								currentPage?.route.name === "instance-block",
						},
						{
							icon: "ph-hash ph-bold ph-lg",
							text: i18n.ts.hiddenTags,
							to: "/admin/hashtags",
							active: currentPage?.route.name === "hashtags",
						},
						{
							icon: "ph-database ph-bold ph-lg",
							text: i18n.ts.database,
							to: "/admin/database",
							active: currentPage?.route.name === "database",
						},
						{
							icon: "ph-flask ph-bold ph-lg",
							text: i18n.ts._experiments.title,
							to: "/admin/experiments",
							active: currentPage?.route.name === "experiments",
						},
					],
				},
		  ]
		: []),
]);

watch(narrow, () => {
	if (currentPage?.route.name == null && !narrow) {
		router.push("/admin/overview");
	}
});

onMounted(() => {
	ro.observe(el.value);

	narrow = el.value.offsetWidth < NARROW_THRESHOLD;
	if (currentPage?.route.name == null && !narrow) {
		router.push("/admin/overview");
	}
});

onActivated(() => {
	narrow = el.value.offsetWidth < NARROW_THRESHOLD;

	if (!narrow && currentPage?.route.name == null) {
		router.replace("/admin/overview");
	}
});

onUnmounted(() => {
	ro.disconnect();
});

watch(router.currentRef, (to) => {
	if (to.route.path === "/admin" && to.child?.route.name == null && !narrow) {
		router.replace("/admin/overview");
	}
});

provideMetadataReceiver((info) => {
	if (info == null) {
		childInfo = null;
	} else {
		childInfo = info;
	}
});

const invite = () => {
	os.api("admin/invite")
		.then((x) => {
			os.alert({
				type: "info",
				text: x.code,
			});
		})
		.catch((err) => {
			os.alert({
				type: "error",
				text: err,
			});
		});
};

async function lookupNote() {
	const { canceled, result: q } = await os.inputText({
		title: i18n.ts.noteId,
	});
	if (canceled) return;

	os.api(
		"notes/show",
		q.startsWith("http://") || q.startsWith("https://")
			? { url: q.trim() }
			: { noteId: q.trim() },
	)
		.then((note) => {
			os.pageWindow(`/notes/${note.id}`);
		})
		.catch((err) => {
			if (err.code === "NO_SUCH_NOTE") {
				os.alert({
					type: "error",
					text: i18n.ts.notFound,
				});
			}
		});
}

const lookup = (ev) => {
	os.popupMenu(
		[
			{
				text: i18n.ts.user,
				icon: "ph-user ph-bold ph-lg",
				action: () => {
					lookupUser();
				},
			},
			{
				text: i18n.ts.note,
				icon: "ph-pencil ph-bold ph-lg",
				action: () => {
					lookupNote();
				},
			},
			{
				text: i18n.ts.file,
				icon: "ph-cloud ph-bold ph-lg",
				action: () => {
					lookupFile();
				},
			},
			{
				text: i18n.ts.instance,
				icon: "ph-planet ph-bold ph-lg",
				action: () => {
					lookupInstance();
				},
			},
		],
		ev.currentTarget ?? ev.target,
	);
};

const headerActions = $computed(() => []);

const headerTabs = $computed(() => []);

definePageMetadata(INFO);

defineExpose({
	header: {
		title: i18n.ts.controlPanel,
	},
});
</script>

<style lang="scss" scoped>
.hiyeyicy {
	&.wide {
		display: flex;
		margin: 0 auto;
		height: 100%;

		> .nav {
			width: 32%;
			max-width: 280px;
			box-sizing: border-box;
			border-right: solid 0.5px var(--divider);
			overflow: auto;
			height: 100%;
		}

		> .main {
			flex: 1;
			min-width: 0;
		}
	}

	> .nav {
		.lxpfedzu {
			> .info {
				margin: 16px 0;
			}

			> .banner {
				margin: 16px;

				> .icon {
					display: block;
					margin: auto;
					height: 42px;
					border-radius: 8px;
				}
			}
		}
	}
}
</style>