// src/routes/api/upload/+server.ts

import { error, json } from '@sveltejs/kit';
import * as fs from 'fs/promises';
import * as path from 'path';
import { promisify } from 'util';
import { exec } from 'child_process';
import pool from '../../../lib/server/database';

const execAsync = promisify(exec);

export const POST: import('@sveltejs/kit').RequestHandler = async ({ request }) => {
  // --- 1. 파일 업로드 및 저장 (기존 로직) ---
  const formData = await request.formData();
  const file = formData.get('video') as File | null;
  const originalFileName = formData.get('fileName') as string | null;

  if (!file || !originalFileName) {
    throw error(400, '필수 데이터가 누락되었습니다.');
  }

  const today = new Date();
  const year = today.getFullYear();
  const month = String(today.getMonth() + 1).padStart(2, '0');
  const day = String(today.getDate()).padStart(2, '0');
  const dateFolder = `${year}${month}${day}`;

  const movieBaseDir = '/workspace/image/movie'; 
  const movieUploadDir = path.join(movieBaseDir, dateFolder);
  await fs.mkdir(movieUploadDir, { recursive: true });

  const movieFilePath = path.join(movieUploadDir, originalFileName);
  const buffer = Buffer.from(await file.arrayBuffer());
  await fs.writeFile(movieFilePath, buffer);
  console.log(`동영상 저장 완료: ${movieFilePath}`);

  // 트랜잭션 시작
  const client = await pool.connect();
  try {
    await client.query('BEGIN');

    // --- 2. FFprobe로 TotalFrameCount 계산 및 TumerMovie에 INSERT ---
    const ffprobeCommand = `ffprobe -v error -select_streams v:0 -count_frames -show_entries stream=nb_read_frames -of default=nokey=1:noprint_wrappers=1 "${movieFilePath}"`;
    const { stdout } = await execAsync(ffprobeCommand);
    const totalFrameCount = parseInt(stdout.trim(), 10);

    if (isNaN(totalFrameCount)) {
      throw new Error('프레임 수를 계산할 수 없습니다.');
    }

    const locationNetwork = '192.168.1.50'; // 예시 IP
    const objectType = 0;
    
    // ✅ TumerMovie에 INSERT 후, 생성된 Index 값을 반환받음
    const movieInsertQuery = `
        INSERT INTO public."TumerMovie" ("LocationNetwork", "LocationFile", "TotalFrameCount", "ObjectType")
        VALUES ($1, $2, $3, $4)
        RETURNING "Index"
    `;
    const movieInsertRes = await client.query(movieInsertQuery, [locationNetwork, originalFileName, totalFrameCount, objectType]);
    const tumerMovieIndex = movieInsertRes.rows[0].Index;
    console.log(`TumerMovie 저장 완료, Index: ${tumerMovieIndex}`);

    // --- 3. FFmpeg로 모든 프레임 추출 ---
    const videoFileNameWithoutExt = originalFileName.split('.').slice(0, -1).join('.');
    const imageRefBaseDir = path.join('/workspace/image/image_ref', videoFileNameWithoutExt);
    const tempFrameDir = path.join(imageRefBaseDir, 'temp_frames'); // 임시 추출 폴더
    await fs.mkdir(tempFrameDir, { recursive: true });

    const ffmpegCommand = `ffmpeg -i "${movieFilePath}" "${tempFrameDir}/%d.png"`;
    await execAsync(ffmpegCommand);
    console.log(`${totalFrameCount}개 프레임 추출 완료`);

    // --- 4. 프레임 재구성 및 TumerDatasetRef 데이터 준비 ---
    const extractedFrames = await fs.readdir(tempFrameDir);
    const datasetRefValues: (string | number)[] = [];
    const queryParams: string[] = [];
    let paramIndex = 1;

    for (const frameFile of extractedFrames) {
        const frameNumber = parseInt(path.basename(frameFile, '.png'), 10);
        const shardDirNumber = Math.floor((frameNumber - 1) / 1000);
        const finalDir = path.join(imageRefBaseDir, String(shardDirNumber));
        await fs.mkdir(finalDir, { recursive: true });

        const oldPath = path.join(tempFrameDir, frameFile);
        const newPath = path.join(finalDir, `${frameNumber}.png`);
        await fs.rename(oldPath, newPath);

        // DB에 저장될 경로 (예: image_ref/my_video/0/1.png)
        //const dbLocationFile = path.join('image_ref', videoFileNameWithoutExt, String(shardDirNumber), `${frameNumber}.png`);
        const dbLocationFile = path.join('image', 'image_ref', videoFileNameWithoutExt, String(shardDirNumber), `${frameNumber}.png`);

        queryParams.push(`($${paramIndex++}, $${paramIndex++}, $${paramIndex++})`);
        datasetRefValues.push(tumerMovieIndex, frameNumber, dbLocationFile);
    }
    await fs.rm(tempFrameDir, { recursive: true, force: true }); // 임시 폴더 삭제
    console.log('프레임 파일 재구성 완료');


    // --- 5. TumerDatasetRef에 대량 INSERT ---
    if (datasetRefValues.length > 0) {
        const datasetRefQuery = `
            INSERT INTO public."TumerDatasetRef" ("IndexMovie", "DataNumber", "LocationFile")
            VALUES ${queryParams.join(', ')}
        `;
        await client.query(datasetRefQuery, datasetRefValues);
        console.log(`${extractedFrames.length}개 프레임 정보 DB 저장 완료`);
    }

    // 모든 작업 성공 시 트랜잭션 커밋
    await client.query('COMMIT');
    
    return json({ 
        success: true, 
        message: '업로드, 프레임 추출 및 DB 저장이 모두 완료되었습니다.',
        tumerMovieIndex,
        totalFrameCount
    });

  } catch (err) {
    // 오류 발생 시 트랜잭션 롤백
    await client.query('ROLLBACK');
    console.error('전체 작업 중 오류 발생:', err);
    throw error(500, '서버 처리 중 오류가 발생했습니다.');
  } finally {
    // 클라이언트 연결 해제
    client.release();
  }
}