<script lang="ts">
	import { page } from '$app/state';
	import {
		api,
		type ProjectDetail,
		type TeamAccessEntry,
		type TeamRow,
		type SessionSummary,
		type ExplorerData,
		type ProjectUsageReport,
	} from '$lib/api';
	import { session } from '$lib/session';
	import { resolveOrg } from '$lib/org';
	import {
		fmtCost,
		fmtDate,
		fmtNum,
		fmtQuantity,
		fmtTokens,
		permissionRoleLabel,
		usageKindLabel,
	} from '$lib/format';
	import { PERMISSION_ROLES, PERMISSION_ROLE_LABELS } from '$lib/constants';
	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 SelectField from '$lib/components/SelectField.svelte';
	import Icon from '$lib/components/Icon.svelte';
	import { toastError, toastSuccess } from '$lib/toast';

	const org = $derived(resolveOrg($session.me, page.url.search));
	const slug = $derived(org?.slug ?? '');
	const projectId = $derived(page.params.projectId ?? '');
	const roleItems = PERMISSION_ROLES.map((r) => ({ value: r, label: PERMISSION_ROLE_LABELS[r] }));
	const roleChain = `${PERMISSION_ROLE_LABELS.READ} ⊂ ${PERMISSION_ROLE_LABELS.EDIT} ⊂ ${PERMISSION_ROLE_LABELS.MANAGE}`;

	let proj = $state<ProjectDetail | null>(null);
	let access = $state<TeamAccessEntry[]>([]);
	let sessions = $state<SessionSummary[]>([]);
	let projectUsage = $state<ProjectUsageReport | null>(null);
	let teams = $state<TeamRow[]>([]);
	let explorer = $state<ExplorerData | null>(null);
	let loading = $state(true);
	let error = $state<string | null>(null);

	let grantTeam = $state('');
	let grantRole = $state<string>('EDIT');
	let moveFolder = $state('');

	const actorIsOrgAdmin = $derived(proj?.actorIsOrgAdmin ?? false);
	const actorCanManage = $derived(proj?.actorCanManageProject ?? false);

	async function load() {
		loading = true;
		error = null;
		try {
			// Project detail + team-access list are gated to project read/oversight.
			const [p, a] = await Promise.all([api.project(slug, projectId), api.teamAccess(slug, projectId)]);
			proj = p;
			access = a.access;
			// Team list is needed for grant UI whenever the actor has project MANAGE
			// (org admin or member). Sessions/explorer stay org-admin oversight only.
			const needTeams = p.actorIsOrgAdmin === true || p.actorCanManageProject === true;
			const [s, t, e, u] = await Promise.all([
				p.actorIsOrgAdmin ? api.sessions(slug, projectId) : Promise.resolve({ sessions: [] as SessionSummary[] }),
				needTeams ? api.teams(slug) : Promise.resolve({ teams: [] as TeamRow[] }),
				p.actorIsOrgAdmin ? api.explorer(slug) : Promise.resolve(null as ExplorerData | null),
				p.actorIsOrgAdmin
					? api.projectUsage(slug, projectId)
					: Promise.resolve(null as ProjectUsageReport | null),
			]);
			sessions = s.sessions;
			teams = t.teams;
			explorer = e;
			projectUsage = u;
			if (p.actorIsOrgAdmin) {
				moveFolder = p.folderId ?? '';
			}
		} catch (err) {
			error = err instanceof Error ? err.message : String(err);
		} finally {
			loading = false;
		}
	}

	async function rename() {
		if (!proj) return;
		const name = prompt('新名称', proj.name);
		if (!name) return;
		try {
			await api.renameProject(slug, projectId, name);
			await load();
			toastSuccess('已重命名');
		} catch (err) {
			toastError(err instanceof Error ? err.message : String(err));
		}
	}

	async function archiveBinding() {
		if (!confirm('解绑当前飞书群? 用户将无法通过该群触发智能体。')) return;
		try {
			await api.archiveBinding(slug, projectId);
			await load();
			toastSuccess('已解绑飞书群');
		} catch (err) {
			toastError(err instanceof Error ? err.message : String(err));
		}
	}

	async function archiveProject() {
		if (!confirm(`归档项目 ${proj?.name}?`)) return;
		try {
			await api.archiveProject(slug, projectId);
			window.location.href = `/admin/projects`;
		} catch (err) {
			toastError(err instanceof Error ? err.message : String(err));
		}
	}

	async function move() {
		try {
			await api.moveProject(slug, projectId, moveFolder || null);
			await load();
			toastSuccess('已移动');
		} catch (err) {
			toastError(err instanceof Error ? err.message : String(err));
		}
	}

	async function grant() {
		if (!grantTeam) return;
		try {
			await api.grantTeamAccess(slug, projectId, { teamId: grantTeam, role: grantRole });
			grantTeam = '';
			await load();
			toastSuccess('已授权');
		} catch (err) {
			toastError(err instanceof Error ? err.message : String(err));
		}
	}

	async function revoke(t: TeamAccessEntry) {
		if (!confirm(`撤销 ${t.teamName} 对此项目的授权?`)) return;
		try {
			await api.revokeTeamAccess(slug, projectId, t.teamId);
			await load();
			toastSuccess('已撤销授权');
		} catch (err) {
			toastError(err instanceof Error ? err.message : String(err));
		}
	}

	function folderItems() {
		const items = [{ value: '', label: '（根）' }];
		if (!explorer) return items;
		return [...items, ...explorer.folders.map((f) => ({ value: f.id, label: f.name }))];
	}

	function teamItems() {
		return [{ value: '', label: '选择团队…' }, ...teams.map((t) => ({ value: t.id, label: `${t.name}（${t.slug}）` }))];
	}

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

{#if loading}
	<LoadingState />
{:else if error}
	<ErrorBanner message={error} onretry={load} />
{:else if proj}
	<div class="mb-2">
		<a
			href={`/admin/projects`}
			class="inline-flex items-center gap-1 text-sm text-surface-700 hover:text-primary-600"
		>
			<Icon name="arrow-left" class="h-4 w-4" />
			返回项目列表
		</a>
	</div>

	{@const detail = proj}
	<PageHeader title={detail.name} description={`项目是权限边界；通过团队授予 ${roleChain}。`}>
		{#snippet actions()}
			{#if actorIsOrgAdmin}
				<button class="saas-btn-secondary py-1.5! text-sm" onclick={rename}>重命名</button>
				{#if detail.binding}
					<button class="saas-btn-secondary py-1.5! text-sm" onclick={archiveBinding}>解绑飞书群</button>
				{/if}
				<button class="saas-btn-danger py-1.5! text-sm" onclick={archiveProject}>归档</button>
			{/if}
		{/snippet}
	</PageHeader>

	<div class="saas-card-pad mb-6">
		<dl class="grid gap-x-8 gap-y-3 text-sm sm:grid-cols-2">
			<div>
				<dt class="text-xs font-medium uppercase tracking-wide text-surface-600">工作区路径</dt>
				<dd class="mt-0.5 break-all font-mono text-xs text-surface-700">{proj.workspaceDir}</dd>
			</div>
			<div>
				<dt class="text-xs font-medium uppercase tracking-wide text-surface-600">创建者</dt>
				<dd class="mt-0.5 text-surface-800">
					{proj.createdBy ? `${proj.createdBy.displayName} (${proj.createdBy.feishuOpenId})` : '—'}
				</dd>
			</div>
			<div>
				<dt class="text-xs font-medium uppercase tracking-wide text-surface-600">文件夹</dt>
				<dd class="mt-0.5 text-surface-800">{proj.folder ? proj.folder.name : '（根）'}</dd>
			</div>
			<div>
				<dt class="text-xs font-medium uppercase tracking-wide text-surface-600">飞书群</dt>
				<dd class="mt-0.5 text-surface-800">
					{#if proj.binding}
						<span class="saas-badge-success mr-1">已绑定</span>
						<span class="font-mono text-xs">群 {proj.binding.chatId}</span>
						<span class="text-surface-600"> · {fmtDate(proj.binding.createdAt)}</span>
					{:else}
						<span class="saas-badge-neutral">未绑定</span>
					{/if}
				</dd>
			</div>
			<div>
				<dt class="text-xs font-medium uppercase tracking-wide text-surface-600">创建时间</dt>
				<dd class="mt-0.5 text-surface-800">{fmtDate(proj.createdAt)}</dd>
			</div>
		</dl>

		{#if explorer}
			<div class="mt-5 flex flex-wrap items-end gap-2 border-t border-surface-100 pt-4">
				<div class="min-w-48 flex-1">
					<p class="saas-label">移动到文件夹</p>
					<SelectField items={folderItems()} bind:value={moveFolder} />
				</div>
				<button class="saas-btn-secondary" onclick={move}>移动</button>
			</div>
		{/if}
	</div>

	<div class="saas-card-pad mb-6">
		<h3 class="saas-section-title mb-1">团队授权</h3>
		<p class="saas-muted mb-4">通过团队授权项目访问。一项目可授多团队，一团队可访问多项目。</p>

		{#if actorCanManage}
			<div class="mb-4 grid gap-2 sm:grid-cols-[1fr_10rem_auto]">
				<SelectField items={teamItems()} bind:value={grantTeam} />
				<SelectField items={roleItems} bind:value={grantRole} />
				<button class="saas-btn-primary" onclick={grant}>授权</button>
			</div>
		{:else}
			<p class="mb-4 text-xs text-surface-600">需要项目 MANAGE 授权才能增删团队访问。</p>
		{/if}

		{#if access.length === 0}
			<EmptyState title="暂无团队授权" description="选择团队并授予角色以开放项目访问。" />
		{:else}
			<table class="data-table">
				<thead>
					<tr>
						<th>团队</th>
						<th>标识</th>
						<th>角色</th>
						<th></th>
					</tr>
				</thead>
				<tbody>
					{#each access as g}
						<tr>
							<td class="font-medium">{g.teamName}</td>
							<td class="font-mono text-xs">/{g.teamSlug}</td>
							<td><span class="saas-badge-primary">{permissionRoleLabel(g.role)}</span></td>
							<td class="text-right">
								{#if actorCanManage}
									<button class="saas-btn-danger py-1! text-xs" onclick={() => revoke(g)}>撤销</button>
								{:else}
									<span class="text-xs text-surface-500">—</span>
								{/if}
							</td>
						</tr>
					{/each}
				</tbody>
			</table>
		{/if}
	</div>

	{#if actorIsOrgAdmin}
		{#if projectUsage}
			<div class="saas-card overflow-hidden mb-6">
				<div class="border-b border-surface-200 px-5 py-3 flex items-center justify-between gap-3">
					<div>
						<h3 class="text-sm font-semibold">项目用量分账</h3>
						<p class="saas-muted mt-0.5 text-xs">
							{fmtNum(projectUsage.runCount)} 次运行 · 成本 {fmtCost(projectUsage.costUsd)} · tokens
							{fmtTokens(projectUsage.inputTokens, projectUsage.outputTokens)}
						</p>
					</div>
					<a class="text-sm text-primary-700 hover:underline" href={`/admin/usage`}>组织报告</a>
				</div>
				{#if projectUsage.breakdown.length === 0}
					<div class="px-5 py-4 text-sm text-surface-600">尚无 UsageFact。</div>
				{:else}
					<div class="overflow-x-auto">
						<table class="data-table">
							<thead>
								<tr>
									<th>类型</th>
									<th>供应方</th>
									<th>模型 / 能力</th>
									<th>次数</th>
									<th>计量</th>
									<th>成本</th>
								</tr>
							</thead>
							<tbody>
								{#each projectUsage.breakdown as row}
									<tr>
										<td>
											<span
												class={row.kind === 'external_capability' ? 'saas-badge-primary' : 'saas-badge-success'}
											>
												{usageKindLabel(row.kind)}
											</span>
										</td>
										<td class="font-mono text-xs">{row.provider}</td>
										<td class="font-mono text-xs">{row.capabilityId ?? row.model ?? '—'}</td>
										<td class="tabular-nums">{fmtNum(row.factCount)}</td>
										<td class="tabular-nums text-xs">
											{#if row.unit}
												{fmtQuantity(row.quantity, row.unit)}
											{:else}
												{fmtTokens(row.inputTokens, row.outputTokens)}
											{/if}
										</td>
										<td class="tabular-nums">{fmtCost(row.costUsd)}</td>
									</tr>
								{/each}
							</tbody>
						</table>
					</div>
				{/if}
			</div>
		{/if}

		<div class="saas-card overflow-hidden">
			<div class="border-b border-surface-200 px-5 py-3">
				<h3 class="text-sm font-semibold">智能体会话</h3>
				<p class="saas-muted mt-0.5 text-xs">点进会话可查看每次 run 的 UsageFact 分账（模型 / 外部能力）。</p>
			</div>
			{#if sessions.length === 0}
				<EmptyState title="暂无会话" description="飞书侧触发智能体后会显示在此。" />
			{:else}
				<table class="data-table">
					<thead>
						<tr>
							<th>供应方 / 角色</th>
							<th>模型</th>
							<th>运行次数</th>
							<th>更新</th>
							<th></th>
						</tr>
					</thead>
					<tbody>
						{#each sessions as s}
							<tr>
								<td class="font-mono text-xs">{s.provider} / {s.roleId}</td>
								<td class="font-mono text-xs">{s.model}</td>
								<td class="tabular-nums">{s.runCount}</td>
								<td class="text-surface-700">{fmtDate(s.updatedAt)}</td>
								<td class="text-right">
									<a
										class="text-sm text-primary-700 hover:underline"
										href={`/admin/sessions/${s.id}`}
									>
										详情
									</a>
								</td>
							</tr>
						{/each}
					</tbody>
				</table>
			{/if}
		</div>
	{/if}
{:else}
	<div class="saas-empty">
		<p class="text-sm text-surface-600">项目数据不可用</p>
	</div>
{/if}
