import fs from "fs";
import path from "path";
import { logger } from "./logger";

/**
 * 파일 시스템 관리 유틸리티
 * 회사별 폴더 구조 관리
 */
export class FileSystemManager {
  private static readonly BASE_UPLOAD_PATH = path.join(
    process.cwd(),
    "uploads"
  );
  private static readonly SHARED_FOLDER = "shared";

  /**
   * 회사별 업로드 경로 생성
   * @param companyCode 회사 코드
   * @param date 업로드 날짜 (선택적)
   * @returns 생성된 폴더 경로
   */
  static createCompanyUploadPath(companyCode: string, date?: Date): string {
    const uploadDate = date || new Date();
    const year = uploadDate.getFullYear();
    const month = String(uploadDate.getMonth() + 1).padStart(2, "0");
    const day = String(uploadDate.getDate()).padStart(2, "0");

    const folderPath = path.join(
      this.BASE_UPLOAD_PATH,
      `company_${companyCode}`,
      String(year),
      month,
      day
    );

    // 폴더가 없으면 생성 (recursive)
    if (!fs.existsSync(folderPath)) {
      fs.mkdirSync(folderPath, { recursive: true });
      logger.info(`회사별 업로드 폴더 생성: ${folderPath}`);
    }

    return folderPath;
  }

  /**
   * 회사 등록 시 기본 폴더 구조 생성
   * @param companyCode 회사 코드
   */
  static initializeCompanyFolder(companyCode: string): void {
    try {
      const companyBasePath = path.join(
        this.BASE_UPLOAD_PATH,
        `company_${companyCode}`
      );

      if (!fs.existsSync(companyBasePath)) {
        fs.mkdirSync(companyBasePath, { recursive: true });

        // README 파일 생성 (폴더 설명)
        const readmePath = path.join(companyBasePath, "README.txt");
        const readmeContent = `회사 코드: ${companyCode}
생성일: ${new Date().toISOString()}
폴더 구조: YYYY/MM/DD/파일명
관리자: 시스템 자동 생성`;

        fs.writeFileSync(readmePath, readmeContent, "utf8");

        logger.info(`회사 폴더 초기화 완료: ${companyCode}`);
      }
    } catch (error) {
      logger.error(`회사 폴더 초기화 실패: ${companyCode}`, error);
      throw error;
    }
  }

  /**
   * 회사 삭제 시 폴더 및 파일 정리
   * @param companyCode 회사 코드
   * @param createBackup 백업 생성 여부
   */
  static async cleanupCompanyFiles(
    companyCode: string,
    createBackup: boolean = true
  ): Promise<void> {
    try {
      const companyPath = path.join(
        this.BASE_UPLOAD_PATH,
        `company_${companyCode}`
      );

      if (!fs.existsSync(companyPath)) {
        logger.warn(`삭제할 회사 폴더가 없습니다: ${companyCode}`);
        return;
      }

      // 백업 생성
      if (createBackup) {
        const backupPath = path.join(
          this.BASE_UPLOAD_PATH,
          "deleted_companies",
          `${companyCode}_${Date.now()}`
        );

        if (!fs.existsSync(path.dirname(backupPath))) {
          fs.mkdirSync(path.dirname(backupPath), { recursive: true });
        }

        // 폴더 이동 (백업)
        fs.renameSync(companyPath, backupPath);
        logger.info(`회사 파일 백업 완료: ${companyCode} -> ${backupPath}`);
      } else {
        // 완전 삭제
        fs.rmSync(companyPath, { recursive: true, force: true });
        logger.info(`회사 파일 완전 삭제: ${companyCode}`);
      }
    } catch (error) {
      logger.error(`회사 파일 정리 실패: ${companyCode}`, error);
      throw error;
    }
  }

  /**
   * 공통 파일 경로 (시스템 관리용)
   */
  static getSharedPath(): string {
    const sharedPath = path.join(this.BASE_UPLOAD_PATH, this.SHARED_FOLDER);

    if (!fs.existsSync(sharedPath)) {
      fs.mkdirSync(sharedPath, { recursive: true });
    }

    return sharedPath;
  }

  /**
   * 회사별 디스크 사용량 조회
   * @param companyCode 회사 코드
   */
  static getCompanyDiskUsage(companyCode: string): {
    fileCount: number;
    totalSize: number;
  } {
    try {
      const companyPath = path.join(
        this.BASE_UPLOAD_PATH,
        `company_${companyCode}`
      );

      if (!fs.existsSync(companyPath)) {
        return { fileCount: 0, totalSize: 0 };
      }

      let fileCount = 0;
      let totalSize = 0;

      const scanDirectory = (dirPath: string) => {
        const items = fs.readdirSync(dirPath);

        for (const item of items) {
          const itemPath = path.join(dirPath, item);
          const stats = fs.statSync(itemPath);

          if (stats.isDirectory()) {
            scanDirectory(itemPath);
          } else {
            fileCount++;
            totalSize += stats.size;
          }
        }
      };

      scanDirectory(companyPath);

      return { fileCount, totalSize };
    } catch (error) {
      logger.error(`디스크 사용량 조회 실패: ${companyCode}`, error);
      return { fileCount: 0, totalSize: 0 };
    }
  }

  /**
   * 전체 시스템 디스크 사용량 조회
   */
  static getAllCompaniesDiskUsage(): Array<{
    companyCode: string;
    fileCount: number;
    totalSize: number;
  }> {
    try {
      const baseDir = this.BASE_UPLOAD_PATH;

      if (!fs.existsSync(baseDir)) {
        return [];
      }

      const companies = fs
        .readdirSync(baseDir)
        .filter((item) => item.startsWith("company_"))
        .map((folder) => folder.replace("company_", ""));

      return companies.map((companyCode) => ({
        companyCode,
        ...this.getCompanyDiskUsage(companyCode),
      }));
    } catch (error) {
      logger.error("전체 디스크 사용량 조회 실패", error);
      return [];
    }
  }

  /**
   * 안전한 파일명 생성 (기존 로직 + 회사 정보)
   * @param originalName 원본 파일명
   * @param companyCode 회사 코드
   */
  static generateSafeFileName(
    originalName: string,
    companyCode: string
  ): string {
    const timestamp = Date.now();
    const cleanName = Buffer.from(originalName, "latin1").toString("utf8");
    const ext = path.extname(cleanName);
    const nameWithoutExt = path.basename(cleanName, ext);

    // 회사코드_타임스탬프_파일명 형식
    return `${companyCode}_${timestamp}_${nameWithoutExt}${ext}`;
  }

  /**
   * 회사별 폴더에서 파일 찾기
   * @param companyCode 회사 코드
   * @param serverFilename 서버 파일명
   * @returns 파일 경로 (찾지 못하면 null)
   */
  static findFileInCompanyFolders(
    companyCode: string,
    serverFilename: string
  ): string | null {
    try {
      const companyBasePath = path.join(
        this.BASE_UPLOAD_PATH,
        `company_${companyCode}`
      );

      if (!fs.existsSync(companyBasePath)) {
        return null;
      }

      // 재귀적으로 폴더 탐색
      const findFileRecursively = (dirPath: string): string | null => {
        try {
          const items = fs.readdirSync(dirPath);

          for (const item of items) {
            const itemPath = path.join(dirPath, item);
            const stats = fs.statSync(itemPath);

            if (stats.isDirectory()) {
              // 하위 폴더에서 재귀 검색
              const found = findFileRecursively(itemPath);
              if (found) return found;
            } else if (item === serverFilename) {
              // 파일을 찾았으면 경로 반환
              return itemPath;
            }
          }
        } catch (error) {
          logger.error(`폴더 탐색 오류: ${dirPath}`, error);
        }

        return null;
      };

      return findFileRecursively(companyBasePath);
    } catch (error) {
      logger.error(`파일 찾기 실패: ${companyCode}/${serverFilename}`, error);
      return null;
    }
  }
}
