'use client';

import { useState } from 'react';
import { FoxFileUpload } from '@fox/core/components/fox-file-upload';
import { FoxHelperText } from '@fox/core/components/fox-helper-text';
import {
  FILE_MODULE,
  MAX_STREAM_UPLOAD_BYTES,
  allowedExtensions,
  fileModuleAccept,
  formatMaxUploadSize,
  isAllowedFileExtension,
} from '@/lib/domain/file-module';

const UPLOAD_ENDPOINT = `/contents/upload?module=${FILE_MODULE.vodContent.id}`;

const MAX_SIZE_TEXT = formatMaxUploadSize(MAX_STREAM_UPLOAD_BYTES);

const UPLOAD_HELP_TEXT = `${allowedExtensions(FILE_MODULE.vodContent).join(', ')} · ${MAX_SIZE_TEXT} 이하`;

interface ContentVideoFieldProps {
  defaultFileId?: string | null;
  /** 이미 올라가 있는 영상의 원본 파일명. 없으면 대체 문구로 그린다. */
  defaultFileName?: string | null;
}

/**
 * 영상 콘텐츠 — 고르는 즉시 스트리밍 라우트로 올리고 파일 ID만 폼에 싣는다.
 *
 * 영상은 Server Action의 multipart 한도(10MB)를 넘기 때문에 폼 제출에 파일을 실을 수 없다.
 * 업로드가 끝나기 전에 저장하면 영상 없이 저장되므로 그동안은 `videoUploading`을 실어 보내
 * Server Action이 막게 한다.
 */
export function ContentVideoField({
  defaultFileId,
  defaultFileName,
}: ContentVideoFieldProps) {
  const [fileId, setFileId] = useState(defaultFileId ?? '');
  const [isUploading, setIsUploading] = useState(false);
  const [error, setError] = useState('');
  // 고른 영상이 끝내 올라가지 않은 상태. 이대로 저장하면 영상 없이 저장되므로 Server Action이
  // 막게 한다 — 화면에 오류가 떠 있어도 저장 버튼은 눌리기 때문이다.
  const [hasFailedPick, setHasFailedPick] = useState(false);

  async function upload(picked: File[]) {
    const file = picked[0];
    if (!file) {
      return;
    }

    setError('');
    setHasFailedPick(false);

    if (!isAllowedFileExtension(FILE_MODULE.vodContent, file.name)) {
      setHasFailedPick(true);
      setError(
        `${allowedExtensions(FILE_MODULE.vodContent).join(', ')} 파일만 올릴 수 있습니다.`
      );
      return;
    }
    // 넘겨 보내면 앞단이 사유 없는 413으로 끊는다 — 고르는 순간 이유를 말해 준다.
    if (file.size > MAX_STREAM_UPLOAD_BYTES) {
      setHasFailedPick(true);
      setError(`영상은 ${MAX_SIZE_TEXT} 이하만 올릴 수 있습니다.`);
      return;
    }

    const body = new FormData();
    body.set('file', file);

    setIsUploading(true);
    try {
      const response = await fetch(UPLOAD_ENDPOINT, { method: 'POST', body });
      const payload = (await response.json()) as { id?: string; message?: string };
      if (!response.ok || !payload.id) {
        setHasFailedPick(true);
        setError(payload.message ?? '영상을 업로드하지 못했습니다.');
        return;
      }
      setFileId(payload.id);
    } catch {
      setHasFailedPick(true);
      setError('영상을 업로드하지 못했습니다.');
    } finally {
      setIsUploading(false);
    }
  }

  return (
    <>
      <FoxFileUpload
        mode="default"
        accept={fileModuleAccept(FILE_MODULE.vodContent)}
        defaultFiles={
          defaultFileId
            ? [{ id: defaultFileId, name: defaultFileName ?? '등록된 영상' }]
            : undefined
        }
        selectLabel="파일선택"
        placeholder="파일을 선택해 주세요."
        description={UPLOAD_HELP_TEXT}
        disabled={isUploading}
        onSelect={upload}
        onRemove={() => {
          setFileId('');
          setError('');
          setHasFailedPick(false);
        }}
      />
      <input type="hidden" name="videoFileId" value={fileId} />
      {isUploading && <input type="hidden" name="videoUploading" value="1" />}
      {hasFailedPick && <input type="hidden" name="videoUploadFailed" value="1" />}

      {isUploading && (
        <FoxHelperText type="information" message="영상을 올리는 중입니다…" />
      )}
      {error && <FoxHelperText type="danger" message={error} />}
    </>
  );
}
