<script lang="ts">
	interface Props {
		open?: boolean;
		title?: string;
		width?: string | number;
		centered?: boolean;
		confirmLoading?: boolean;
		footer?: import('svelte').Snippet | null | undefined;
		okText?: string;
		cancelText?: string;
		maskClosable?: boolean;
		destroyOnHidden?: boolean;
		children?: import('svelte').Snippet;
		titleSlot?: import('svelte').Snippet;
		footerSlot?: import('svelte').Snippet ;
		onOk?: () => Promise<void> | void;
		onCancel?: () => void;
	}

	let {
		open = $bindable(false),
		title = '',
		width = 520,
		footer = undefined,
		centered = true,
		confirmLoading = false,
		okText = '确定',
		cancelText = '取消',
		maskClosable = true,
		destroyOnHidden = false,
		children,
		titleSlot,
		footerSlot,
		onOk,
		onCancel
	}: Props = $props();

	let dialog: HTMLDialogElement;
	let internalLoading = $state(false);

	// 1. 唯一的 DOM 操作入口：$effect
	// 所有的开关逻辑都通过改变 open 变量来触发这里
	$effect(() => {
		if (!dialog) return;

		if (open && !dialog.open) {
			dialog.showModal();
		}
		else if (!open && dialog.open) {
			dialog.close();
		}
	});

	// 2. 处理原生关闭（仅用于处理 ESC 键等浏览器原生行为）
	function handleNativeClose() {
		// 只有当状态认为它是“开”，但 DOM 变成了“关”时，才需要同步
		if (open) {
			open = false;
			onCancel?.();
		}
	}

	// 3. 按钮点击：只修改状态
	function handleCancel() {
		if (internalLoading) return;
		// 先触发回调，再关闭
		onCancel?.();
		open = false;
	}

	async function handleOk() {
		if (internalLoading) return;

		if (onOk) {
			const result = onOk();
			if (result instanceof Promise) {
				internalLoading = true;
				try {
					await result;
					open = false; // 成功后，修改状态来关闭
				} catch (e) {
					console.error('Modal ok error', e);
				} finally {
					internalLoading = false;
				}
			} else {
				open = false; // 修改状态来关闭
			}
		} else {
			open = false; // 修改状态来关闭
		}
	}

	function handleBackdropClick(e: MouseEvent) {
		if (maskClosable && e.target === dialog) {
			// 同样，只修改状态
			onCancel?.();
			open = false;
		}
	}

	let widthStyle = $derived(typeof width === 'number' ? `max-width: ${width}px` : `max-width: ${width}`);
</script>


<dialog
	bind:this={dialog}
	class="modal"
	class:modal-bottom={!centered}
	class:modal-middle={centered}
	onclose={handleNativeClose}
	onclick={handleBackdropClick}
>
	<div class="modal-box" style={widthStyle}>
		<!-- 移除 stopPropagation，改用新的 handleCancel -->
		<button
			class="btn btn-sm btn-circle btn-ghost absolute right-2 top-2"
			onclick={handleCancel}
		>✕</button>

		{#if title || titleSlot}
			<h3 class="font-bold text-lg mb-4">
				{#if titleSlot}
					{@render titleSlot()}
				{:else}
					{title}
				{/if}
			</h3>
		{/if}

		<div class="py-4">
			{#if destroyOnHidden && !open}
				<!-- Destroyed -->
			{:else if children}
				{@render children()}
			{/if}
		</div>

		<div class="modal-action">
			{#if footer === undefined}
				{#if footerSlot}
					{@render footerSlot()}
				{:else}

					<button class="btn" disabled={internalLoading || confirmLoading}
									onclick={handleCancel}
					>
						{cancelText}
					</button>
					<button
						class="btn btn-primary"
						class:loading={internalLoading || confirmLoading}
						disabled={internalLoading || confirmLoading}
						onclick={handleOk}
					>
						{#if internalLoading || confirmLoading}
							<span class="loading loading-spinner"></span>
						{/if}
						{okText}
					</button>
				{/if}
			{:else if footer === null}
				<!-- No footer -->
			{/if}

		</div>
	</div>
	<form method="dialog" class="modal-backdrop">
		<button>close</button>
	</form>
</dialog>