<script lang="ts">
	// ... (이전과 동일한 <script> 태그 내용) ...
	import { onMount } from 'svelte';

	// --- 1. 상태 변수 선언 ---

	// UI 상태
	let videoURL: string = '';
	let videoElement: HTMLVideoElement;
	let originalFileName: string = '';
	let message: string = '동영상 파일을 선택하세요.';

	// 작업 진행 상태
	let isUploadingOriginal: boolean = false; // 원본 임시 업로드
	let uploadProgress: number = 0;
	let isDetectingCrop: boolean = false; // 자동 Crop 감지
	let isSavingCrop: boolean = false; // "Crop 저장하기" (최종 저장)
	let cropProgress: number = 0;
	let currentProcessId: string | null = null; // 취소용 ID
	let cropEventSource: EventSource | null = null; // Crop 저장용 SSE

	// Crop 정보
	let cropX: number = 0;
	let cropY: number = 0;
	let cropWidth: number = 0;
	let cropHeight: number = 0;

	// Crop 리스트 상태
	// TumerMovie 스키마를 기반으로 한 인터페이스 (가정)
	interface CroppedVideo {
		Index: number; // DB의 Primary Key
		movie_file: string; // 파일명 (예: my_video_crop.mp4)
		movie_path: string; // 파일 경로 (예: /workspace/image/video/crop)
		created_at: string; // 생성일
		movie_type: number; // 1 (Crop본), 2 (원본), 0 (bigdata 편집본)
		original_path: string; // 원본 파일 경로 (예: /workspace/image/video/original)
		// ...TumorMovie의 다른 필드들...
	}
	let croppedVideos: CroppedVideo[] = [];
	let isLoadingList: boolean = false;

	// --- 2. 반응형 변수 ---
	$: isLoading = isUploadingOriginal || isDetectingCrop || isSavingCrop || isLoadingList;
	$: detectedCropParams = `${cropWidth}:${cropHeight}:${cropX}:${cropY}`;

	// --- 3. 핵심 기능 함수 ---

	/**
	 * [패널 3] Crop된 동영상 리스트(MovieType: 1)를 DB에서 불러옵니다.
	 */
	const loadCroppedVideos = async () => {
		isLoadingList = true;
		try {
			// 이 API는 MovieType=1인 동영상 목록을 반환해야 합니다.
			const response = await fetch('/api/get-cropped-videos');
			if (!response.ok) throw new Error('데이터를 불러오는 데 실패했습니다.');
			const data = (await response.json()) as CroppedVideo[];
			// 최신순으로 정렬 (id 또는 created_at 기준)
			croppedVideos = data.sort((a, b) => b.id - a.id);
		} catch (error) {
			console.error('Error loading cropped videos:', error);
			message = 'Crop 리스트를 불러오는 중 오류가 발생했습니다.';
		} finally {
			isLoadingList = false;
		}
	};

	/**
	 * [패널 1] 파일을 선택하면 서버에 임시 업로드하고 자동 Crop을 감지합니다.
	 */
	const handleFileSelect = async (e: Event) => {
		const target = e.target as HTMLInputElement;
		const file = target.files?.[0];

		if (file) {
			// 이전 상태 초기화
			resetForm();
			videoURL = URL.createObjectURL(file);
			originalFileName = file.name;

			try {
				// 1. 원본을 서버 임시 폴더에 업로드
				await uploadOriginalVideo(file);

				// 2. 임시 업로드된 파일을 기반으로 Crop 영역 감지
				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 영역 계산 완료! "Crop 저장하기"를 눌러주세요.';
				} else {
					message = '자동 Crop 영역을 찾지 못했습니다. 수동으로 영역을 지정하세요.';
				}
			} catch (error) {
				console.error('처리 중 오류:', error);
				message = '오류가 발생했습니다. 콘솔을 확인해주세요.';
			} finally {
				isDetectingCrop = false;
			}
		}
	};

	/**
	 * (Helper) handleFileSelect에 사용되며, 임시 업로드를 수행합니다.
	 */
	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 = () => {
				isUploadingOriginal = false;
				if (xhr.status >= 200 && xhr.status < 300) {
					resolve();
				} else {
					message = '원본 파일 업로드 중 오류가 발생했습니다.';
					reject(new Error(xhr.statusText));
				}
			};
			xhr.onerror = () => {
				isUploadingOriginal = false;
				message = '원본 파일 업로드 중 네트워크 오류가 발생했습니다.';
				reject(new Error('네트워크 오류'));
			};
			// 이 API는 파일을 '임시' 위치에 저장해야 합니다.
			xhr.open('POST', '/api/upload-original', true);
			xhr.send(formData);
		});
	};

	/**
	 * [패널 1] "Crop 저장하기" 버튼 클릭 시 실행됩니다.
	 * 원본(Type:2) 저장 및 Crop본(Type:1) 저장을 서버에 요청합니다.
	 */
	const handleSaveCrop = () => {
		if (!(cropWidth > 0 && cropHeight > 0) || isSavingCrop) {
			message = 'Crop 영역의 너비와 높이는 0보다 커야 합니다.';
			return;
		}

		isSavingCrop = true;
		cropProgress = 0;
		message = '서버에서 원본 저장 및 Crop 동영상 생성 중...';

		// 새 API 엔드포인트: 원본 저장(Type 2)과 Crop본 저장(Type 1)을 모두 처리
		// 임시 업로드된 파일을 기반으로 작동해야 함
		cropEventSource = new EventSource(
			`/api/save-crop-video?crop=${encodeURIComponent(
				detectedCropParams
			)}&fileName=${encodeURIComponent(originalFileName)}`
		);

		cropEventSource.onmessage = (event) => {
			const data = JSON.parse(event.data);
			if (data.processId) {
				currentProcessId = data.processId;
			}

			if (data.error) {
				console.error('Crop Save Error:', data.error);
				message = `오류 발생: ${data.error}`;
				isSavingCrop = false;
				currentProcessId = null;
				cropEventSource?.close();
				cropEventSource = null;
				return;
			}

			if (data.progress) {
				cropProgress = data.progress;
				message = `동영상 Crop 및 저장 중... ${cropProgress.toFixed(0)}%`;
			}

			if (data.status === 'completed') {
				setTimeout(() => {
					message = '✅ 원본 및 Crop 동영상 저장이 완료되었습니다.';
					isSavingCrop = false;
					currentProcessId = null;
					cropEventSource?.close();
					cropEventSource = null;

					// 폼 초기화
					resetForm();
					// [패널 3] 리스트 새로고침
					loadCroppedVideos();
				}, 500);
			}
		};

		cropEventSource.onerror = (error) => {
			console.error('EventSource failed:', error);
			if (!message.includes('취소')) {
				message = '오류: 서버와 연결이 끊어졌습니다.';
			}
			isSavingCrop = false;
			currentProcessId = null;
			cropEventSource?.close();
			cropEventSource = null;
		};
	};

	/**
	 * [패널 1] Crop 저장 작업을 취소합니다.
	 */
	const handleCancelCrop = async () => {
		if (!currentProcessId || !isSavingCrop) return;

		message = 'Crop 작업을 취소하는 중...';
		try {
			// 이 API는 'save-crop-video'에서 받은 processId를 취소해야 합니다.
			const response = await fetch('/api/cancel-process', {
				method: 'POST',
				headers: { 'Content-Type': 'application/json' },
				body: JSON.stringify({ processId: currentProcessId })
			});
			const result = await response.json();
			if (result.success) {
				message = '작업이 성공적으로 취소되었습니다.';
			} else {
				message = `취소 실패: ${result.error || '알 수 없는 오류'}`;
			}
		} catch (error) {
			console.error('Failed to send cancellation request:', error);
			message = '취소 요청 중 네트워크 오류가 발생했습니다.';
		} finally {
			isSavingCrop = false;
			currentProcessId = null;
			cropEventSource?.close();
			cropEventSource = null;
		}
	};

	/**
	 * [패널 3] Crop 리스트에서 동영상을 삭제합니다. (Type: 1 동영상)
	 */
	const handleDeleteVideo = async (Index: number) => {
		if (isLoading) return;
		if (!confirm(`[Index: ${Index}] 동영상을 DB 및 파일 시스템에서 삭제하시겠습니까?`)) {
			return;
		}

		message = `[Index: ${Index}] 동영상 삭제 중...`;
		isLoadingList = true;
		try {
			// 이 API는 DB 레코드(id)와 실제 파일(movie_path)을 모두 삭제해야 함
			const response = await fetch('/api/delete-video', {
				method: 'POST',
				headers: { 'Content-Type': 'application/json' },
				body: JSON.stringify({ Index: Index, movieType: 1 }) // movieType 1 (Crop본) 삭제
			});

			const result = await response.json();
			if (result.success) {
				message = `[Index: ${Index}] 동영상이 성공적으로 삭제되었습니다.`;
				// 리스트에서 즉시 제거
				croppedVideos = croppedVideos.filter((v) => v.Index !== Index);
			} else {
				throw new Error(result.error || '알 수 없는 오류');
			}
		} catch (error) {
			console.error('Error deleting video:', error);
			message = `동영상 삭제 중 오류 발생: ${error.message}`;
		} finally {
			isLoadingList = false;
		}
	};

	// --- 4. 유틸리티 함수 ---

	/**
	 * 작업 완료 후 폼을 초기화합니다.
	 */
	const resetForm = () => {
		videoURL = '';
		originalFileName = '';
		message = '동영상 파일을 선택하세요.';
		cropX = 0;
		cropY = 0;
		cropWidth = 0;
		cropHeight = 0;
		uploadProgress = 0;
		isUploadingOriginal = false;
		isDetectingCrop = false;
		isSavingCrop = false;

		// 파일 입력 필드 값 초기화
		const fileInput = document.querySelector('input[type="file"]') as HTMLInputElement;
		if (fileInput) fileInput.value = '';
	};

	/**
	 * 페이지 로드 시 Crop 리스트를 불러옵니다.
	 */
	onMount(() => {
		loadCroppedVideos();
	});
</script>

<main class="mx-auto max-w-screen-2xl p-4 sm:p-6 lg:p-8 flex flex-col h-screen">
	<div class="text-center mb-8 flex-shrink-0">
		<h1 class="text-3xl font-bold tracking-tight text-gray-900 sm:text-4xl">
			🎬 1단계: 동영상 업로드 및 Crop
		</h1>
	</div>

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

	<div class="flex-1 flex gap-6 overflow-hidden">
		<section class="w-1/3 bg-white shadow-sm ring-1 ring-gray-900/5 rounded-xl p-6 flex flex-col overflow-hidden">
			<h2 class="text-xl font-semibold text-gray-800 mb-4 flex-shrink-0">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 flex-shrink-0"
			>
				동영상 파일 불러오기
				<input
					type="file"
					accept="video/*"
					on:change={handleFileSelect}
					class="sr-only"
					disabled={isLoading}
				/>
			</label>

			<div class="flex-1 overflow-y-auto mt-4 space-y-2 text-sm pr-2">
				{#if isUploadingOriginal}
					<div>
						<p class="font-medium text-gray-900 mb-1">서버로 업로드 중...</p>
						<progress class="w-full" max="100" value={uploadProgress} />
						<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 || videoURL}
					<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"
									disabled={isSavingCrop}
								/>
							</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"
									disabled={isSavingCrop}
								/>
							</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"
									disabled={isSavingCrop}
								/>
							</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"
									disabled={isSavingCrop}
								/>
							</div>
						</div>
					</div>

					<button
						on:click={isSavingCrop ? handleCancelCrop : handleSaveCrop}
						disabled={(isLoading && !isSavingCrop) ||
							(!isSavingCrop && !(cropWidth > 0 && cropHeight > 0))}
						class="mt-4 w-full text-center cursor-pointer rounded-md border px-4 py-2 text-sm font-medium shadow-sm disabled:opacity-50 disabled:cursor-not-allowed"
						class:bg-white={!isSavingCrop}
						class:text-gray-700={!isSavingCrop}
						class:hover:bg-gray-50={!isSavingCrop}
						class:border-gray-300={!isSavingCrop}
						class:bg-red-600={isSavingCrop}
						class:text-white={isSavingCrop}
						class:hover:bg-red-700={isSavingCrop}
						class:border-transparent={isSavingCrop}
					>
						{#if isSavingCrop}
							🔴 취소하기
						{:else}
							✅ Crop 저장하기
						{/if}
					</button>
					{#if isSavingCrop}
						<div class="mt-2">
							<progress class="w-full" max="100" value={cropProgress} />
							<p class="text-right font-mono text-gray-700">{cropProgress.toFixed(0)}%</p>
						</div>
					{/if}
				{/if}
			</div>
		</section>

		<section class="w-1/3 bg-white shadow-sm ring-1 ring-gray-900/5 rounded-xl p-6 flex flex-col">
			<h2 class="text-xl font-semibold text-gray-800 mb-4 flex-shrink-0">2. 동영상 미리보기</h2>
			{#if videoURL}
				{#key videoURL}
					<video
						bind:this={videoElement}
						class="w-full rounded-lg"
						controls
						autoplay
						src={videoURL}
					>
						브라우저가 비디오 태그를 지원하지 않습니다.
					</video>
				{/key}
			{:else}
				<div
					class="flex-1 h-full w-full flex items-center justify-center bg-gray-100 rounded-lg border border-dashed"
				>
					<p class="text-gray-500">동영상을 선택하세요.</p>
				</div>
			{/if}
		</section>

		<section class="w-1/3 bg-white shadow-sm ring-1 ring-gray-900/5 rounded-xl p-6 flex flex-col overflow-hidden">
			<h2 class="text-xl font-semibold text-gray-800 mb-4 flex-shrink-0">
				3. Crop 동영상 리스트 ({croppedVideos.length}개)
			</h2>
			<div class="flex-1 overflow-y-auto space-y-3 mb-6 pr-2">
				{#if isLoadingList && croppedVideos.length === 0}
					<p class="text-gray-500 text-center py-4 animate-pulse">리스트 로딩 중...</p>
				{:else if croppedVideos.length === 0}
					<p class="text-gray-500 text-center py-4">저장된 Crop 동영상이 없습니다.</p>
				{:else}
					{#each croppedVideos as video (video.Index)}
						<div class="p-3 border rounded-lg flex items-center justify-between gap-2">
							<div class="flex-1 overflow-hidden">
								<p class="font-medium text-sm text-gray-800 truncate" title={video.movie_file}>
									{video.movie_file}
								</p>
								<p class="text-xs text-gray-500">
									{new Date(video.created_at).toLocaleString('ko-KR')}
								</p>
							</div>
							<div class="flex-shrink-0 flex gap-2">
								<a
									href={`/video-editor?id=${video.Index}`}
									class="px-3 py-1 text-sm font-medium text-white bg-blue-600 rounded-md hover:bg-blue-700"
									title="이 동영상으로 구간 편집하기"
								>
									선택
								</a>
								<button
									on:click={() => handleDeleteVideo(video.Index)}
									class="px-2 py-1 text-sm font-medium text-red-600 hover:text-red-800"
									title="삭제"
									disabled={isLoading}
								>
									삭제
								</button>
							</div>
						</div>
					{/each}
				{/if}
			</div>
			<div class="flex-shrink-0">
				<button
					on:click={loadCroppedVideos}
					disabled={isLoading}
					class="w-full 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"
				>
					🔄 새로고침
				</button>
			</div>
		</section>
	</div>
</main>