import { useState, useRef, useEffect, useCallback } from 'react';
import { stitchImages } from '../services/aerialApi';
import { analyzeImage } from '@tabs/prediction/services/predictionApi';
import { setPendingImageAnalysis } from '@common/utils/imageAnalysisSignal';
import { navigateToTab } from '@common/hooks/useSubMenu';

const MAX_IMAGES = 6;

export function OilAreaAnalysis() {
  const [selectedFiles, setSelectedFiles] = useState<File[]>([]);
  const [previewUrls, setPreviewUrls] = useState<string[]>([]);
  const [stitchedBlob, setStitchedBlob] = useState<Blob | null>(null);
  const [stitchedPreviewUrl, setStitchedPreviewUrl] = useState<string | null>(null);
  const [isStitching, setIsStitching] = useState(false);
  const [isAnalyzing, setIsAnalyzing] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const fileInputRef = useRef<HTMLInputElement>(null);

  // Object URL 메모리 누수 방지 — 언마운트 시 전체 revoke
  useEffect(() => {
    return () => {
      previewUrls.forEach(url => URL.revokeObjectURL(url));
      if (stitchedPreviewUrl) URL.revokeObjectURL(stitchedPreviewUrl);
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  const handleFileSelect = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
    setError(null);
    const incoming = Array.from(e.target.files ?? []);
    if (incoming.length === 0) return;

    setSelectedFiles(prev => {
      const merged = [...prev, ...incoming].slice(0, MAX_IMAGES);
      if (prev.length + incoming.length > MAX_IMAGES) {
        setError(`최대 ${MAX_IMAGES}장까지 선택할 수 있습니다.`);
      }
      return merged;
    });

    // setSelectedFiles updater 밖에서 독립 호출 — updater 내부 side effect는
    // React Strict Mode의 이중 호출로 인해 URL이 중복 생성되는 버그를 유발함
    setPreviewUrls(prev => {
      const available = MAX_IMAGES - prev.length;
      const toAdd = incoming.slice(0, available);
      return [...prev, ...toAdd.map(f => URL.createObjectURL(f))];
    });

    // input 초기화 (동일 파일 재선택 허용)
    e.target.value = '';
  }, []);

  const handleRemoveFile = useCallback((idx: number) => {
    setSelectedFiles(prev => prev.filter((_, i) => i !== idx));
    setPreviewUrls(prev => {
      URL.revokeObjectURL(prev[idx]);
      return prev.filter((_, i) => i !== idx);
    });
    // 합성 결과 초기화 (선택 파일이 바뀌었으므로)
    setStitchedBlob(null);
    if (stitchedPreviewUrl) {
      URL.revokeObjectURL(stitchedPreviewUrl);
      setStitchedPreviewUrl(null);
    }
    setError(null);
  }, [stitchedPreviewUrl]);

  const handleStitch = async () => {
    if (selectedFiles.length < 2) {
      setError('이미지를 2장 이상 선택해주세요.');
      return;
    }
    setError(null);
    setIsStitching(true);
    try {
      const blob = await stitchImages(selectedFiles);
      if (stitchedPreviewUrl) URL.revokeObjectURL(stitchedPreviewUrl);
      setStitchedBlob(blob);
      setStitchedPreviewUrl(URL.createObjectURL(blob));
    } catch (err) {
      const msg =
        err instanceof Error
          ? err.message
          : (err as { message?: string }).message ?? '이미지 합성에 실패했습니다.';
      const status = err instanceof Error ? 0 : (err as { status?: number }).status ?? 0;
      setError(status === 504 ? '이미지 합성 서버 응답 시간이 초과되었습니다.' : msg);
    } finally {
      setIsStitching(false);
    }
  };

  const handleAnalyze = async () => {
    if (!stitchedBlob) return;
    setError(null);
    setIsAnalyzing(true);
    try {
      const stitchedFile = new File([stitchedBlob], `stitch_${Date.now()}.jpg`, { type: 'image/jpeg' });
      const result = await analyzeImage(stitchedFile);
      setPendingImageAnalysis({ ...result, autoRun: true });
      navigateToTab('prediction', 'analysis');
    } catch (err) {
      const msg = err instanceof Error ? err.message : '분석에 실패했습니다.';
      setError(msg.includes('GPS') ? '이미지에 GPS 정보가 없습니다. GPS 정보가 포함된 이미지를 사용해주세요.' : msg);
      setIsAnalyzing(false);
    }
  };

  const canStitch = selectedFiles.length >= 2 && !isStitching && !isAnalyzing;
  const canAnalyze = stitchedBlob !== null && !isStitching && !isAnalyzing;

  return (
    <div className="flex gap-5 h-full overflow-hidden">
      {/* ── Left Panel ── */}
      <div className="w-[280px] min-w-[280px] flex flex-col overflow-y-auto scrollbar-thin">
        <div className="text-sm font-bold mb-1 font-korean">🧩 유출유면적분석</div>
        <div className="text-[11px] text-text-3 mb-4 font-korean">
          드론 사진을 합성하여 유출유 확산 면적과 기름 양을 산정합니다.
        </div>

        {/* 이미지 선택 버튼 */}
        <input
          ref={fileInputRef}
          type="file"
          accept="image/*"
          multiple
          className="hidden"
          onChange={handleFileSelect}
        />
        <button
          onClick={() => fileInputRef.current?.click()}
          disabled={selectedFiles.length >= MAX_IMAGES || isStitching || isAnalyzing}
          className="w-full py-2 mb-3 border border-dashed border-border rounded-sm text-xs font-korean text-text-2
                     hover:border-primary-cyan hover:text-primary-cyan transition-colors cursor-pointer
                     disabled:opacity-40 disabled:cursor-not-allowed"
        >
          + 이미지 선택 ({selectedFiles.length}/{MAX_IMAGES})
        </button>

        {/* 선택된 이미지 목록 */}
        {selectedFiles.length > 0 && (
          <>
            <div className="text-[11px] font-bold mb-1.5 font-korean">선택된 이미지</div>
            <div className="flex flex-col gap-1 mb-3">
              {selectedFiles.map((file, i) => (
                <div
                  key={`${file.name}-${i}`}
                  className="flex items-center gap-2 px-2 py-1.5 bg-bg-3 border border-border rounded-sm text-[11px] font-korean"
                >
                  <span className="text-primary-cyan">📷</span>
                  <span className="flex-1 truncate text-text-1">{file.name}</span>
                  <button
                    onClick={() => handleRemoveFile(i)}
                    disabled={isStitching || isAnalyzing}
                    className="text-text-3 hover:text-status-red transition-colors cursor-pointer
                               disabled:opacity-40 disabled:cursor-not-allowed ml-1 shrink-0"
                    title="제거"
                  >
                    ✕
                  </button>
                </div>
              ))}
            </div>
          </>
        )}

        {/* 에러 메시지 */}
        {error && (
          <div className="mb-3 px-2.5 py-2 bg-[rgba(239,68,68,0.08)] border border-[rgba(239,68,68,0.3)] rounded-sm text-[11px] text-status-red font-korean">
            {error}
          </div>
        )}

        {/* 이미지 합성 버튼 */}
        <button
          onClick={handleStitch}
          disabled={!canStitch}
          className="w-full py-2.5 mb-2 rounded-sm text-[12px] font-bold font-korean cursor-pointer transition-colors
                     border border-primary-cyan text-primary-cyan bg-[rgba(6,182,212,0.06)]
                     hover:bg-[rgba(6,182,212,0.15)] disabled:opacity-40 disabled:cursor-not-allowed"
        >
          {isStitching ? '⏳ 합성 중...' : stitchedBlob ? '✅ 다시 합성' : '🔗 이미지 합성'}
        </button>

        {/* 분석 시작 버튼 */}
        <button
          onClick={handleAnalyze}
          disabled={!canAnalyze}
          className="w-full py-3 rounded-sm text-[13px] font-bold font-korean cursor-pointer border-none transition-colors
                     disabled:opacity-40 disabled:cursor-not-allowed text-white"
          style={canAnalyze ? { background: 'linear-gradient(135deg, var(--cyan), var(--blue))' } : { background: 'var(--bg-3)' }}
        >
          {isAnalyzing ? '⏳ 분석 중...' : '🧩 분석 시작'}
        </button>
      </div>

      {/* ── Right Panel ── */}
      <div className="flex-1 flex flex-col overflow-hidden">
        {/* 3×2 이미지 그리드 */}
        <div className="text-[11px] font-bold mb-2 font-korean">선택된 이미지 미리보기</div>
        <div className="grid grid-cols-3 gap-1.5 mb-3">
          {Array.from({ length: MAX_IMAGES }).map((_, i) => (
            <div
              key={i}
              className="bg-bg-3 border border-border rounded-sm overflow-hidden"
              style={{ height: '300px' }}
            >
              {previewUrls[i] ? (
                <img
                  src={previewUrls[i]}
                  alt={selectedFiles[i]?.name ?? ''}
                  className="w-full h-full object-cover"
                />
              ) : (
                <div className="flex items-center justify-center h-full text-text-3 text-lg font-mono opacity-20">
                  {i + 1}
                </div>
              )}
            </div>
          ))}
        </div>

        {/* 합성 결과 */}
        <div className="text-[11px] font-bold mb-2 font-korean">합성 결과</div>
        <div
          className="relative bg-bg-0 border border-border rounded-sm overflow-hidden flex items-center justify-center"
          style={{ minHeight: '160px', flex: '1 1 0' }}
        >
          {stitchedPreviewUrl ? (
            <img
              src={stitchedPreviewUrl}
              alt="합성 결과"
              className="max-w-full max-h-full object-contain"
            />
          ) : (
            <div className="text-[12px] text-text-3 font-korean text-center px-4">
              {isStitching
                ? '⏳ 이미지를 합성하고 있습니다...'
                : '이미지를 선택하고 합성 버튼을 클릭하면\n합성 결과가 여기에 표시됩니다.'}
            </div>
          )}
        </div>
      </div>
    </div>
  );
}
