<script lang="ts">
	// --- 상태 변수 선언 ---
	let videoURL: string = '';
	let videoElement: HTMLVideoElement;
	let originalFileName: string = '';
	let message: string = '동영상 파일을 선택하세요.';
	let startTime: number = 0;
	let endTime: number = 0;
	let stopAtTime: number | null = null; // 미리보기 자동 정지를 위한 변수

	// --- 작업 진행 상태 변수 ---
	let isUploadingOriginal: boolean = false;
	let uploadProgress: number = 0;
	let isDetectingCrop: boolean = false;
	let isCutting: boolean = false;
	let isUploadingSegments: boolean = false;

	// --- Crop 및 구간 정보 ---
	let cropX: number = 0;
	let cropY: number = 0;
	let cropWidth: number = 0;
	let cropHeight: number = 0;

	interface TimeSegment {
		id: number;
		start: number;
		end: number;
		resultURL?: string;
		isUploading?: boolean;
		isUploaded?: boolean;
	}
	let segments: TimeSegment[] = [];
	let nextSegmentId = 0;

	// --- 반응형 변수 ---
	$: allProcessed = segments.length > 0 && segments.every((s) => s.resultURL);
	$: isLoading = isUploadingOriginal || isDetectingCrop || isCutting || isUploadingSegments;
	$: detectedCropParams = `${cropWidth}:${cropHeight}:${cropX}:${cropY}`;
	$: segmentsReadyToUpload = segments.filter((s) => s.resultURL && !s.isUploaded).length > 0;

	// --- 핵심 기능 함수 ---
	const uploadOriginalVideo = async (file: File): Promise<void> => {
		return new Promise((resolve, reject) => {
			isUploadingOriginal = true;
			uploadProgress = 0;
			message = '원본 동영상을 서버로 업로드하는 중...';
			const formData = new FormData();
			formData.append('video', file);
			const xhr = new XMLHttpRequest();
			xhr.upload.onprogress = (event) => {
				if (event.lengthComputable) {
					uploadProgress = (event.loaded / event.total) * 100;
				}
			};
			xhr.onload = () => {
				if (xhr.status >= 200 && xhr.status < 300) {
					isUploadingOriginal = false;
					resolve();
				} else {
					isUploadingOriginal = false;
					message = '원본 파일 업로드 중 오류가 발생했습니다.';
					reject(new Error(xhr.statusText));
				}
			};
			xhr.onerror = () => {
				isUploadingOriginal = false;
				message = '원본 파일 업로드 중 네트워크 오류가 발생했습니다.';
				reject(new Error('네트워크 오류'));
			};
			xhr.open('POST', '/api/upload-original', true);
			xhr.send(formData);
		});
	};

	const handleExecuteCrop = async () => {
		if (!(cropWidth > 0 && cropHeight > 0)) {
			message = 'Crop 영역의 너비와 높이는 0보다 커야 합니다.';
			return;
		}
		isCutting = true;
		message = '서버에서 전체 동영상을 Crop하는 중...';
		try {
			const response = await fetch('/api/process-video', {
				method: 'POST',
				headers: { 'Content-Type': 'application/json' },
				body: JSON.stringify({ action: 'crop-full-video', cropParams: detectedCropParams })
			});
			if (!response.ok) {
				const errorResult = await response.json();
				throw new Error(errorResult.error || 'Crop 작업에 실패했습니다.');
			}
			const result = await response.json();
			if (result.success) {
				videoURL = `/api/video-preview?t=${Date.now()}`;
				message = '✅ Crop 적용이 완료되었습니다. 변경된 미리보기를 확인하세요.';
			} else {
				throw new Error(result.message || '서버에서 Crop 작업을 완료하지 못했습니다.');
			}
		} catch (error) {
			console.error('Crop 적용 중 오류:', error);
			message = `Crop 적용 중 오류가 발생했습니다: ${
				error instanceof Error ? error.message : '알 수 없는 오류'
			}`;
		} finally {
			isCutting = false;
		}
	};

	const handleFileSelect = async (e: Event) => {
		const target = e.target as HTMLInputElement;
		const file = target.files?.[0];

		if (file) {
			videoURL = URL.createObjectURL(file);
			originalFileName = file.name;
			segments = [];
			cropX = 0;
			cropY = 0;
			cropWidth = 0;
			cropHeight = 0;
			try {
				await uploadOriginalVideo(file);
				message = '서버에서 최적의 Crop 영역을 계산하는 중...';
				isDetectingCrop = true;
				const response = await fetch('/api/process-video', {
					method: 'POST',
					headers: { 'Content-Type': 'application/json' },
					body: JSON.stringify({ action: 'detect-crop' })
				});
				if (!response.ok) throw new Error('Crop 영역 계산 요청 실패');
				const result = await response.json();
				if (result.success && result.cropParams) {
					const [width, height, x, y] = result.cropParams.split(':').map(Number);
					cropWidth = width;
					cropHeight = height;
					cropX = x;
					cropY = y;
					message = '자동 Crop 영역 계산 완료!';
				} else {
					message = '자동 Crop 영역을 찾지 못했습니다. 수동으로 잘라내기를 진행합니다.';
				}
			} catch (error) {
				console.error('처리 중 오류:', error);
				message = '오류가 발생했습니다. 콘솔을 확인해주세요.';
			} finally {
				isDetectingCrop = false;
			}
		}
	};

	const cutAllSegments = async () => {
		if (segments.length === 0) {
			message = '먼저 구간을 추가해주세요.';
			return;
		}
		isCutting = true;
		message = '서버에서 동영상 잘라내기 작업 중...';
		try {
			const response = await fetch('/api/process-video', {
				method: 'POST',
				headers: { 'Content-Type': 'application/json' },
				body: JSON.stringify({
					action: 'cut-segments',
					segments: segments,
					cropParams: cropWidth > 0 && cropHeight > 0 ? detectedCropParams : ''
				})
			});
			if (!response.ok) throw new Error('잘라내기 작업 실패');
			const result = await response.json();
			if (result.success && result.outputUrls) {
				let updatedSegments = [...segments];
				for (const output of result.outputUrls) {
					updatedSegments = updatedSegments.map((s) =>
						s.id === output.id ? { ...s, resultURL: output.url } : s
					);
				}
				segments = updatedSegments;
				message = '모든 구간 처리 완료!';
			} else {
				throw new Error(result.error || '알 수 없는 서버 오류');
			}
		} catch (error) {
			console.error('잘라내기 중 오류:', error);
			message = '잘라내기 중 오류가 발생했습니다.';
		} finally {
			isCutting = false;
		}
	};

	const uploadSegment = async (segmentId: number) => {
		const segment = segments.find((s) => s.id === segmentId);
		if (!segment || !segment.resultURL || segment.isUploading) return;
		segments = segments.map((s) => (s.id === segmentId ? { ...s, isUploading: true } : s));
		message = `[${segment.id}번] 구간 업로드 중...`;
		try {
			const response = await fetch(segment.resultURL);
			const videoBlob = await response.blob();
			const formData = new FormData();
			const baseName = originalFileName.split('.').slice(0, -1).join('.') || originalFileName;
			const fileName = `${baseName}_cut-${segment.id}-${segment.start.toFixed(0)}s-${segment.end.toFixed(0)}s.mp4`;
			formData.append('video', videoBlob, fileName);
			formData.append('originalFileName', originalFileName);
			const uploadResponse = await fetch('/api/upload-cut', {
				method: 'POST',
				body: formData
			});
			if (!uploadResponse.ok) {
				throw new Error('서버 업로드 실패');
			}
			segments = segments.map((s) =>
				s.id === segmentId ? { ...s, isUploading: false, isUploaded: true } : s
			);
			message = `[${segment.id}번] 구간 업로드 성공!`;
		} catch (error) {
			console.error(`Segment ${segmentId} 업로드 오류:`, error);
			message = `[${segment.id}번] 구간 업로드 중 오류 발생.`;
			segments = segments.map((s) => (s.id === segmentId ? { ...s, isUploading: false } : s));
		}
	};

	const uploadAllSegments = async () => {
		const segmentsToUpload = segments.filter((s) => s.resultURL && !s.isUploaded && !s.isUploading);
		if (segmentsToUpload.length === 0) {
			message = '업로드할 새로운 동영상이 없습니다.';
			return;
		}
		isUploadingSegments = true;
		message = `총 ${segmentsToUpload.length}개의 동영상 업로드를 시작합니다...`;
		for (const segment of segmentsToUpload) {
			await uploadSegment(segment.id);
		}
		isUploadingSegments = false;
		message = '모든 구간에 대한 업로드 작업이 완료되었습니다.';
	};

	// --- UI 헬퍼 함수들 ---
	const setStartTime = () => {
		if (videoElement) startTime = videoElement.currentTime;
	};
	const setEndTime = () => {
		if (videoElement) endTime = videoElement.currentTime;
	};
	const addSegment = () => {
		if (startTime >= endTime) {
			alert('시작 시간은 종료 시간보다 빨라야 합니다.');
			return;
		}
		segments = [
			...segments,
			{ id: nextSegmentId++, start: startTime, end: endTime, isUploaded: false, isUploading: false }
		];
	};
	const removeSegment = (id: number) => {
		segments = segments.filter((segment) => segment.id !== id);
	};
	const downloadAllSegments = () => {
		if (!allProcessed) return;
		segments.forEach((segment) => {
			if (segment.resultURL) {
				const link = document.createElement('a');
				link.href = segment.resultURL;
				const baseName = originalFileName.split('.').slice(0, -1).join('.') || originalFileName;
				const fileName = `${baseName}_cut-${segment.id}-${segment.start.toFixed(
					0
				)}s-${segment.end.toFixed(0)}s.mp4`;
				link.download = fileName;
				link.click();
			}
		});
	};

	// ### START: 추가된 함수 (구간 미리보기 및 자동 정지) ###
	/** 구간을 클릭하면 해당 구간을 재생합니다. */
	const previewSegment = (segment: TimeSegment) => {
		if (!videoElement) return;

		// 다른 구간 재생 중이면 정지 후 시작
		videoElement.pause();

		// 정지할 시간 설정
		stopAtTime = segment.end;
		// 시작 시간으로 이동
		videoElement.currentTime = segment.start;
		// 재생
		videoElement.play();
	};

	/** 비디오 재생 시간을 감지하여 자동 정지시킵니다. */
	const handleTimeUpdate = () => {
		if (videoElement && stopAtTime !== null && videoElement.currentTime >= stopAtTime) {
			videoElement.pause();
			stopAtTime = null; // 자동 정지 완료 후 초기화
		}
	};
	// ### END: 추가된 함수 ###
</script>

<main class="mx-auto max-w-screen-2xl p-4 sm:p-6 lg:p-8">
	<div class="text-center mb-8">
		<h1 class="text-3xl font-bold tracking-tight text-gray-900 sm:text-4xl">
			🎬 내시경 BigData 동영상 편집기 (Server-Side)
		</h1>
	</div>

	<p class="p-4 mb-6 bg-blue-50 text-blue-700 border border-blue-200 rounded-lg text-center">
		{message}
	</p>

	<div class="flex flex-col lg:flex-row gap-6 items-start">
		{#if videoURL}
			<div class="w-full lg:w-1/2">
				<section class="bg-white shadow-sm ring-1 ring-gray-900/5 rounded-xl p-6">
					<h2 class="text-xl font-semibold text-gray-800 mb-4">동영상 미리보기</h2>
					{#key videoURL}
						<video
							bind:this={videoElement}
							class="w-full rounded-lg"
							controls
							autoplay
							on:timeupdate={handleTimeUpdate}
						>
							<source src={videoURL} type="video/mp4" />
							브라우저가 비디오 태그를 지원하지 않습니다.
						</video>
					{/key}
					</section>
			</div>
		{/if}

		<div class="w-full lg:w-1/4 flex flex-col gap-6">
			<section class="bg-white shadow-sm ring-1 ring-gray-900/5 rounded-xl p-6">
				<h2 class="text-xl font-semibold text-gray-800 mb-4">1. 동영상 파일 선택</h2>
				<label
					class="w-full text-center cursor-pointer rounded-md border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 shadow-sm hover:bg-gray-50"
				>
					동영상 파일 불러오기
					<input
						type="file"
						accept="video/*"
						on:change={handleFileSelect}
						class="sr-only"
						disabled={isLoading}
					/>
				</label>

				<div class="mt-4 space-y-2 text-sm">
					{#if isUploadingOriginal}
						<div>
							<p class="font-medium text-gray-900 mb-1">서버로 업로드 중...</p>
							<progress class="w-full" max="100" value={uploadProgress}></progress>
							<p class="text-right font-mono text-gray-700">{uploadProgress.toFixed(0)}%</p>
						</div>
					{/if}
					{#if isDetectingCrop}
						<p class="text-gray-500 animate-pulse">자동 Crop 영역 계산 중...</p>
					{:else if cropWidth > 0 && !isUploadingOriginal}
						<div>
							<p class="font-medium text-gray-900 mb-2">자동 Crop 영역 (수정 가능):</p>
							<div class="grid grid-cols-2 gap-x-4 gap-y-2">
								<div>
									<label for="cropX" class="block text-xs font-medium text-gray-500">X 시작점</label>
									<input
										type="number"
										id="cropX"
										bind:value={cropX}
										class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm p-1.5"
									/>
								</div>
								<div>
									<label for="cropY" class="block text-xs font-medium text-gray-500">Y 시작점</label>
									<input
										type="number"
										id="cropY"
										bind:value={cropY}
										class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm p-1.5"
									/>
								</div>
								<div>
									<label for="cropWidth" class="block text-xs font-medium text-gray-500">너비</label>
									<input
										type="number"
										id="cropWidth"
										bind:value={cropWidth}
										class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm p-1.5"
									/>
								</div>
								<div>
									<label for="cropHeight" class="block text-xs font-medium text-gray-500"
										>높이</label
									>
									<input
										type="number"
										id="cropHeight"
										bind:value={cropHeight}
										class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm p-1.5"
									/>
								</div>
							</div>
						</div>

						<button
							on:click={handleExecuteCrop}
							disabled={isLoading || !(cropWidth > 0 && cropHeight > 0)}
							class="mt-4 w-full text-center cursor-pointer rounded-md border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 shadow-sm hover:bg-gray-50 disabled:opacity-50 disabled:cursor-not-allowed"
						>
							Crop 적용하기
						</button>
					{/if}
				</div>
			</section>

			{#if videoURL}
				<section class="bg-white shadow-sm ring-1 ring-gray-900/5 rounded-xl p-6">
					<h3 class="text-lg font-semibold text-gray-800 mb-4">2. 구간 추가</h3>
					<div class="flex gap-2 mb-4">
						<button
							on:click={setStartTime}
							class="w-full rounded-md border border-gray-300 bg-white px-3 py-2 text-sm font-medium text-gray-700 shadow-sm hover:bg-gray-50"
							>시작 시간 설정</button
						>
						<button
							on:click={setEndTime}
							class="w-full rounded-md border border-gray-300 bg-white px-3 py-2 text-sm font-medium text-gray-700 shadow-sm hover:bg-gray-50"
							>종료 시간 설정</button
						>
					</div>
					<div class="space-y-1 text-sm mb-4">
						<p><strong class="font-medium text-gray-900">시작:</strong> {startTime.toFixed(2)}초</p>
						<p><strong class="font-medium text-gray-900">종료:</strong> {endTime.toFixed(2)}초</p>
					</div>
					<button
						on:click={addSegment}
						class="w-full rounded-md border border-transparent bg-green-600 px-4 py-2 text-base font-medium text-white shadow-sm hover:bg-green-700"
					>
						➕ 구간 추가하기
					</button>
				</section>
			{/if}
		</div>

		{#if videoURL}
			<div class="w-full lg:w-1/4">
				<section
					class="bg-white shadow-sm ring-1 ring-gray-900/5 rounded-xl p-6 flex flex-col h-full"
				>
					<h2 class="text-xl font-semibold text-gray-800 mb-4">
						3. 자르기 목록 ({segments.length}개)
					</h2>
					<div class="space-y-4 mb-6 flex-1 overflow-y-auto pr-2">
						{#each segments as segment (segment.id)}
							<div
								class="p-3 border rounded-lg flex items-center justify-between"
								class:bg-green-50={segment.isUploaded}
								class:bg-blue-50={segment.isUploading}
							>
								<div class="flex-1 overflow-hidden">
									<p
										class="font-medium text-gray-800 truncate cursor-pointer hover:text-indigo-600"
										on:click={() => previewSegment(segment)}
										title="클릭하여 구간 미리보기"
									>
										{segment.start.toFixed(2)}초 ~ {segment.end.toFixed(2)}초
									</p>
									{#if segment.resultURL}
										<div class="text-sm mt-1 flex items-center gap-4">
											<a
												href={segment.resultURL}
												download={`${originalFileName.split('.').slice(0, -1).join('.')}_cut-${
													segment.id
												}.mp4`}
												class="text-indigo-600 hover:underline">다운로드</a
											>

											{#if segment.isUploading}
												<span class="text-gray-500 animate-pulse">업로드 중...</span>
											{:else if segment.isUploaded}
												<span class="font-medium text-green-600">✓ 업로드 완료</span>
											{:else}
												<button
													on:click={() => uploadSegment(segment.id)}
													class="text-blue-600 hover:underline"
													disabled={isLoading}>업로드</button
												>
											{/if}
										</div>
									{/if}
								</div>
								<button
									on:click={() => removeSegment(segment.id)}
									class="text-red-500 hover:text-red-700 font-bold px-2 ml-2 self-start">X</button
								>
							</div>
						{:else}
							<p class="text-gray-500 text-center py-4">추가된 구간이 없습니다.</p>
						{/each}
					</div>
					<div class="mt-auto grid grid-cols-1 md:grid-cols-3 gap-2">
						<button
							on:click={cutAllSegments}
							disabled={isLoading || segments.length === 0}
							class="w-full rounded-md border border-transparent bg-indigo-600 px-4 py-2 text-sm font-medium text-white shadow-sm hover:bg-indigo-700 disabled:opacity-50"
						>
							✂️ 전체 잘라내기
						</button>
						<button
							on:click={uploadAllSegments}
							disabled={isLoading || !segmentsReadyToUpload}
							class="w-full rounded-md border border-transparent bg-blue-600 px-4 py-2 text-sm font-medium text-white shadow-sm hover:bg-blue-700 disabled:opacity-50"
						>
							📤 전체 업로드
						</button>
						<button
							on:click={downloadAllSegments}
							disabled={isLoading || !allProcessed}
							class="w-full rounded-md border border-transparent bg-green-600 px-4 py-2 text-sm font-medium text-white shadow-sm hover:bg-green-700 disabled:opacity-50"
						>
							📦 전체 다운로드
						</button>
					</div>
				</section>
			</div>
		{/if}
	</div>
</main>