<template>
	<MkStickyContainer>
		<template #header>
			<MkPageHeader
				:actions="headerActions"
				:tabs="headerTabs"
				:display-back-button="true"
			/>
		</template>
		<MkSpacer :content-max="900">
			<div class="plans">
				<div class="_panel section">
					<h2>{{ editingPlan ? "プランを編集" : "プランを追加" }}</h2>
					<div class="planForm">
						<MkInput v-model="planName" type="text">
							<template #label>プラン名</template>
						</MkInput>
						<MkInput v-model="planIcon" type="text" placeholder="ph-crown ph-bold ph-lg / ★">
							<template #label>アイコン</template>
						</MkInput>
						<MkInput v-model="planDescription" type="text">
							<template #label>説明</template>
						</MkInput>
						<div class="formActions">
							<MkButton
								primary
								:disabled="planName.trim() === '' || planIcon.trim() === ''"
								@click="savePlan"
							>
								<i class="ph-floppy-disk ph-bold ph-lg"></i>
								保存
							</MkButton>
							<MkButton v-if="editingPlan" @click="clearForm">
								キャンセル
							</MkButton>
						</div>
					</div>
				</div>

				<div class="_panel section">
					<h2>プラン種別</h2>
					<div v-if="plans.length === 0" class="empty">
						プランはまだありません。
					</div>
					<div v-for="plan in plans" :key="plan.id" class="planRow">
						<div class="planBadge">
							<span class="badge">
								<i v-if="isIconClass(plan.icon)" :class="plan.icon"></i>
								<span v-else>{{ plan.icon }}</span>
							</span>
						</div>
						<div class="planInfo">
							<div class="planName">{{ plan.name }}</div>
							<div v-if="plan.description" class="description">
								{{ plan.description }}
							</div>
						</div>
						<MkButton @click="editPlan(plan)">
							<i class="ph-pencil-simple ph-bold ph-lg"></i>
							編集
						</MkButton>
						<MkButton danger @click="deletePlan(plan)">
							<i class="ph-trash ph-bold ph-lg"></i>
							削除
						</MkButton>
					</div>
				</div>

				<div class="_panel section">
					<h2>ユーザーのプラン加入</h2>
					<div class="targetForm">
						<MkInput
							v-model="target"
							type="text"
							:spellcheck="false"
							placeholder="@username / @username@host / userId"
						>
							<template #label>対象アカウント</template>
						</MkInput>
						<MkButton
							primary
							:disabled="target.trim() === ''"
							@click="lookupUser"
						>
							<i class="ph-magnifying-glass ph-bold ph-lg"></i>
							検索
						</MkButton>
					</div>

					<div v-if="targetUser" class="userPlans">
						<MkUserCardMini :user="targetUser" />
						<div class="assignments">
							<div v-for="plan in plans" :key="plan.id" class="assignment">
								<div class="assignmentPlan">
									<span class="badge">
										<i v-if="isIconClass(plan.icon)" :class="plan.icon"></i>
										<span v-else>{{ plan.icon }}</span>
									</span>
									<span>{{ plan.name }}</span>
								</div>
								<MkButton
									v-if="hasPlan(plan.id)"
									danger
									@click="removeUserPlan(plan)"
								>
									外す
								</MkButton>
								<MkButton v-else primary @click="addUserPlan(plan)">
									入れる
								</MkButton>
							</div>
						</div>
					</div>
				</div>
			</div>
		</MkSpacer>
	</MkStickyContainer>
</template>

<script lang="ts" setup>
import { computed, onMounted, ref } from "vue";
import type * as misskey from "iceshrimp-sdk";
import MkButton from "@/components/MkButton.vue";
import MkInput from "@/components/form/input.vue";
import MkUserCardMini from "@/components/MkUserCardMini.vue";
import * as os from "@/os";
import { definePageMetadata } from "@/scripts/page-metadata";

type Plan = misskey.entities.Plan;

const plans = ref<Plan[]>([]);
const editingPlan = ref<Plan | null>(null);
const planName = ref("");
const planIcon = ref("");
const planDescription = ref("");
const target = ref("");
const targetUser = ref<any>(null);
const targetPlans = ref<Plan[]>([]);

onMounted(loadPlans);

async function loadPlans() {
	plans.value = await os.api("admin/plans/list", {});
}

function clearForm() {
	editingPlan.value = null;
	planName.value = "";
	planIcon.value = "";
	planDescription.value = "";
}

function editPlan(plan: Plan) {
	editingPlan.value = plan;
	planName.value = plan.name;
	planIcon.value = plan.icon;
	planDescription.value = plan.description;
}

async function savePlan() {
	const payload = {
		name: planName.value,
		icon: planIcon.value,
		description: planDescription.value,
	};

	if (editingPlan.value) {
		await os.apiWithDialog("admin/plans/update", {
			planId: editingPlan.value.id,
			...payload,
		});
	} else {
		await os.apiWithDialog("admin/plans/create", payload);
	}

	clearForm();
	await loadPlans();
	if (targetUser.value) await loadTargetPlans();
}

async function deletePlan(plan: Plan) {
	const confirm = await os.confirm({
		type: "warning",
		text: `プラン「${plan.name}」を削除しますか？加入状態も解除されます。`,
	});
	if (confirm.canceled) return;

	await os.apiWithDialog("admin/plans/delete", { planId: plan.id });
	if (editingPlan.value?.id === plan.id) clearForm();
	await loadPlans();
	if (targetUser.value) await loadTargetPlans();
}

function normalizeAcct(input: string) {
	const normalized = input.trim().replace(/^@/, "");
	const parts = normalized.split("@");
	if (parts.length >= 2) {
		return { username: parts[0], host: parts.slice(1).join("@") };
	}
	return { username: normalized, host: null };
}

async function lookupTarget(input: string) {
	try {
		return await os.api("users/show", { userId: input.trim() });
	} catch {
		return await os.api("users/show", normalizeAcct(input));
	}
}

async function lookupUser() {
	targetUser.value = await lookupTarget(target.value);
	await loadTargetPlans();
}

async function loadTargetPlans() {
	if (!targetUser.value) return;
	targetPlans.value = await os.api("admin/user-plans/list", {
		userId: targetUser.value.id,
	});
	targetUser.value = {
		...targetUser.value,
		plans: targetPlans.value,
	};
}

function hasPlan(planId: string) {
	return targetPlans.value.some((plan) => plan.id === planId);
}

async function addUserPlan(plan: Plan) {
	if (!targetUser.value) return;
	await os.apiWithDialog("admin/user-plans/add", {
		userId: targetUser.value.id,
		planId: plan.id,
	});
	await loadTargetPlans();
}

async function removeUserPlan(plan: Plan) {
	if (!targetUser.value) return;
	await os.apiWithDialog("admin/user-plans/remove", {
		userId: targetUser.value.id,
		planId: plan.id,
	});
	await loadTargetPlans();
}

function isIconClass(icon: string) {
	return icon.split(/\s+/).some((part) => part.startsWith("ph-"));
}

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

definePageMetadata({
	title: "プラン",
	icon: "ph-identification-badge ph-bold ph-lg",
});
</script>

<style lang="scss" scoped>
.plans {
	margin: var(--margin);
}

.section {
	padding: 24px;
	margin-bottom: var(--margin);
}

h2 {
	margin: 0 0 16px;
	font-size: 1.1em;
}

.planForm,
.targetForm {
	display: grid;
	grid-template-columns: 1fr 180px;
	gap: 12px;
	align-items: end;
}

.planForm {
	grid-template-columns: 1fr 180px 1fr auto;
}

.formActions {
	display: flex;
	gap: 8px;
}

.empty,
.description {
	opacity: 0.7;
}

.planRow,
.assignment {
	display: grid;
	grid-template-columns: auto 1fr auto auto;
	gap: 12px;
	align-items: center;
	margin-bottom: 12px;
}

.assignment {
	grid-template-columns: 1fr auto;
}

.planInfo {
	min-width: 0;
}

.planName {
	font-weight: 700;
}

.badge {
	display: inline-grid;
	place-items: center;
	width: 2em;
	height: 2em;
	border-radius: 999px;
	background: #334155;
	color: #fff;
	font-weight: 800;
}

.badge > span {
	max-width: 100%;
	overflow: hidden;
	white-space: nowrap;
}

.userPlans {
	display: grid;
	gap: 16px;
	margin-top: 16px;
}

.assignmentPlan {
	display: flex;
	align-items: center;
	gap: 10px;
	min-width: 0;
}

@media (max-width: 700px) {
	.planForm,
	.targetForm,
	.planRow {
		grid-template-columns: 1fr;
	}

	.formActions {
		flex-wrap: wrap;
	}
}
</style>
