import { mkdirSync } from 'fs';
import { join } from 'path';
import type { AttachmentKind } from './entities/attachment.entity';

// 업무 첨부파일 업로드 폴더 — 서버 로컬 디스크에 보관(추후 S3/MinIO 로 교체 가능)
// 도커 환경에서는 UPLOAD_DIR 로 볼륨 경로를 주입하고, 미설정 시 작업 디렉터리 하위 uploads 사용
export const UPLOAD_DIR =
  process.env.UPLOAD_DIR || join(process.cwd(), 'uploads');

// 모듈 로드 시 업로드 폴더 존재 보장(multer dest 는 폴더를 자동 생성하지 않음)
mkdirSync(UPLOAD_DIR, { recursive: true });

// 첨부 1건당 최대 크기(25MB)
export const MAX_FILE_SIZE = 25 * 1024 * 1024;

// 허용 MIME 화이트리스트 — 실행 가능/스크립트(예: text/html, image/svg+xml) 차단.
// 다운로드는 attachment + nosniff 로 제공하지만, 업로드 단계에서도 1차로 막는다(심층 방어).
export const ALLOWED_MIME_TYPES: ReadonlySet<string> = new Set<string>([
  // 이미지
  'image/png',
  'image/jpeg',
  'image/gif',
  'image/webp',
  // 문서
  'application/pdf',
  'text/plain',
  'text/csv',
  'application/msword',
  'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
  'application/vnd.ms-excel',
  'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
  'application/vnd.ms-powerpoint',
  'application/vnd.openxmlformats-officedocument.presentationml.presentation',
  // 압축
  'application/zip',
  'application/x-zip-compressed',
  'application/x-7z-compressed',
  'application/x-rar-compressed',
]);

// multer fileFilter — 허용 MIME 만 통과. 거부 시 파일이 저장되지 않아 컨트롤러가 400 처리.
export function fileMimeFilter(
  _req: unknown,
  file: { mimetype: string },
  cb: (error: Error | null, acceptFile: boolean) => void,
): void {
  cb(null, ALLOWED_MIME_TYPES.has(file.mimetype));
}

// multer(diskStorage) 가 채워주는 업로드 파일 메타 — @types/multer 의존 없이 필요한 필드만 정의
export interface UploadedDiskFile {
  originalname: string; // 원본 파일명(비ASCII 는 latin1 인코딩으로 들어옴)
  filename: string; // 업로드 폴더 내 저장명
  size: number; // 바이트
  mimetype: string;
  path: string; // 절대 경로
}

// MIME/확장자로 아이콘 종류 파생
export function deriveKind(mime: string, name: string): AttachmentKind {
  const lower = name.toLowerCase();
  if (mime.startsWith('image/')) return 'img';
  if (mime === 'application/pdf' || lower.endsWith('.pdf')) return 'pdf';
  if (
    mime.includes('zip') ||
    mime.includes('compressed') ||
    lower.endsWith('.zip')
  ) {
    return 'zip';
  }
  return 'doc';
}

// multer 가 비ASCII 파일명을 latin1 로 디코딩하므로 UTF-8 로 복원
export function decodeOriginalName(name: string): string {
  return Buffer.from(name, 'latin1').toString('utf8');
}
