<script lang="ts">
	import { Collapsible } from 'bits-ui';
	import { page } from '$app/state';
	import { api, type TeamRow, type TeamMemberRow } from '$lib/api';
	import { session } from '$lib/session';
	import { resolveOrg } from '$lib/org';
	import { fmtDate } from '$lib/format';
	import PageHeader from '$lib/components/PageHeader.svelte';
	import LoadingState from '$lib/components/LoadingState.svelte';
	import ErrorBanner from '$lib/components/ErrorBanner.svelte';
	import EmptyState from '$lib/components/EmptyState.svelte';
	import { toastError, toastSuccess } from '$lib/toast';

	const org = $derived(resolveOrg($session.me, page.url.search));
	const slug = $derived(org?.slug ?? '');

	let teams = $state<TeamRow[]>([]);
	let loading = $state(true);
	let error = $state<string | null>(null);

	let newSlug = $state('');
	let newName = $state('');
	let newDesc = $state('');
	let adding = $state(false);

	let expandedId = $state<string | null>(null);
	let teamMembers = $state<TeamMemberRow[]>([]);
	let memberInput = $state('');
	let loadingMembers = $state(false);

	async function load() {
		loading = true;
		error = null;
		try {
			const res = await api.teams(slug);
			teams = res.teams;
		} catch (err) {
			error = err instanceof Error ? err.message : String(err);
		} finally {
			loading = false;
		}
	}

	const SLUG_RE = /^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/;

	async function createTeam() {
		if (!newSlug.trim() || !newName.trim()) return;
		const teamSlug = newSlug.trim().toLowerCase();
		if (!SLUG_RE.test(teamSlug)) {
			toastError('标识须为小写字母数字，可用连字符连接');
			return;
		}
		adding = true;
		try {
			await api.createTeam(slug, {
				slug: teamSlug,
				name: newName.trim(),
				...(newDesc.trim() ? { description: newDesc.trim() } : {}),
			});
			newSlug = '';
			newName = '';
			newDesc = '';
			await load();
			toastSuccess('团队已创建');
		} catch (err) {
			toastError(err instanceof Error ? err.message : String(err));
		} finally {
			adding = false;
		}
	}

	async function archiveTeam(t: TeamRow) {
		if (!confirm(`归档团队 ${t.name}? 归档后该团队不再解析为项目授权主体。`)) return;
		try {
			await api.archiveTeam(slug, t.id);
			if (expandedId === t.id) expandedId = null;
			await load();
			toastSuccess('团队已归档');
		} catch (err) {
			toastError(err instanceof Error ? err.message : String(err));
		}
	}

	async function openMembers(t: TeamRow) {
		if (expandedId === t.id) return;
		expandedId = t.id;
		loadingMembers = true;
		memberInput = '';
		try {
			const res = await api.teamMembers(slug, t.id);
			teamMembers = res.members;
		} catch (err) {
			toastError(err instanceof Error ? err.message : String(err));
		} finally {
			loadingMembers = false;
		}
	}

	function onExpandChange(t: TeamRow, open: boolean) {
		if (open) void openMembers(t);
		else if (expandedId === t.id) expandedId = null;
	}

	async function addMember(t: TeamRow) {
		if (!memberInput.trim()) return;
		const v = memberInput.trim();
		try {
			await api.addTeamMember(slug, t.id, v.startsWith('ou') ? { feishuOpenId: v } : { userId: v });
			memberInput = '';
			const res = await api.teamMembers(slug, t.id);
			teamMembers = res.members;
			await load();
			toastSuccess('已加入团队');
		} catch (err) {
			toastError(err instanceof Error ? err.message : String(err));
		}
	}

	async function revokeMember(t: TeamRow, m: TeamMemberRow) {
		if (!confirm(`将 ${m.displayName} 移出团队 ${t.name}?`)) return;
		try {
			await api.revokeTeamMember(slug, t.id, m.userId);
			const res = await api.teamMembers(slug, t.id);
			teamMembers = res.members;
			await load();
			toastSuccess('已移出团队');
		} catch (err) {
			toastError(err instanceof Error ? err.message : String(err));
		}
	}

	$effect(() => {
		if (slug) load();
	});
</script>

<PageHeader title="团队" description="团队是项目授权主体，可被授予只读、编辑或管理权限。" />

{#if loading}
	<LoadingState />
{:else if error}
	<ErrorBanner message={error} onretry={load} />
{:else}
	<div class="saas-card-pad mb-6">
		<h2 class="saas-section-title mb-4">新建团队</h2>
		<div class="grid gap-3 md:grid-cols-[1fr_1fr_1.2fr_auto]">
			<input class="saas-input" placeholder="标识（如 math-g7）" bind:value={newSlug} />
			<input class="saas-input" placeholder="名称" bind:value={newName} />
			<input class="saas-input" placeholder="描述（可选）" bind:value={newDesc} />
			<button class="saas-btn-primary" onclick={createTeam} disabled={adding}>新建</button>
		</div>
	</div>

	{#if teams.length === 0}
		<div class="saas-card">
			<EmptyState title="暂无团队" description="创建团队后，可在项目页授权项目访问。" />
		</div>
	{:else}
		<div class="space-y-3">
			{#each teams as t (t.id)}
				<Collapsible.Root
					class="saas-card p-5"
					open={expandedId === t.id}
					onOpenChange={(open) => onExpandChange(t, open)}
				>
					<div class="flex flex-wrap items-center gap-2.5">
						<span class="text-base font-semibold text-surface-900">{t.name}</span>
						<span class="font-mono text-xs text-surface-600">/{t.slug}</span>
						<span class="saas-badge-neutral">{t.memberCount} 成员</span>
						<div class="ml-auto flex flex-wrap gap-2">
							<Collapsible.Trigger class="saas-btn-secondary py-1.5! text-sm">
								{expandedId === t.id ? '收起' : '管理成员'}
							</Collapsible.Trigger>
							<button type="button" class="saas-btn-danger py-1.5! text-sm" onclick={() => archiveTeam(t)}>
								归档
							</button>
						</div>
					</div>
					{#if t.description}
						<p class="mt-1.5 text-sm text-surface-700">{t.description}</p>
					{/if}
					<p class="mt-1 text-xs text-surface-600">创建于 {fmtDate(t.createdAt)}</p>

					<Collapsible.Content>
						<div class="mt-4 border-t border-surface-200 pt-4">
							{#if loadingMembers && expandedId === t.id}
								<p class="text-sm text-surface-600">加载中…</p>
							{:else if expandedId === t.id}
								<div class="mb-4 flex gap-2">
									<input
										class="saas-input"
										placeholder="飞书 open_id 或用户 id"
										bind:value={memberInput}
										onkeydown={(e) => {
											if (e.key === 'Enter') addMember(t);
										}}
									/>
									<button class="saas-btn-secondary shrink-0" onclick={() => addMember(t)}>加入</button>
								</div>
								{#if teamMembers.length === 0}
									<p class="py-3 text-center text-sm text-surface-600">团队暂无成员</p>
								{:else}
									<table class="data-table">
										<thead>
											<tr>
												<th>成员</th>
												<th>open_id</th>
												<th>加入时间</th>
												<th></th>
											</tr>
										</thead>
										<tbody>
											{#each teamMembers as m}
												<tr>
													<td class="font-medium">{m.displayName}</td>
													<td class="font-mono text-xs">{m.feishuOpenId}</td>
													<td class="text-surface-700">{fmtDate(m.createdAt)}</td>
													<td class="text-right">
														<button class="saas-btn-danger py-1! text-xs" onclick={() => revokeMember(t, m)}>
															移除
														</button>
													</td>
												</tr>
											{/each}
										</tbody>
									</table>
								{/if}
							{/if}
						</div>
					</Collapsible.Content>
				</Collapsible.Root>
			{/each}
		</div>
	{/if}
	<p class="mt-4 text-xs text-surface-600">归档团队会同步撤销其活跃的项目授权。</p>
{/if}
