import * as path from "path";
import * as fs from "fs";
import * as archiver from "archiver";
import * as mkdirp from "mkdirp";
import * as rimraf from "rimraf";
import { v4 as uuidv4 } from "uuid";
import { ExportOptions, CourseMetadata } from "./types";
import {
  copyDir,
  downloadS3Folder,
  getFilesList,
  getCourseMetadata,
} from "./shared";

export async function exportToScorm(options: ExportOptions): Promise<string> {
  const { courseSlug, bucket, outDir } = options;

  // 1. Create temporary folder
  const tmpName = uuidv4();
  const scormOutDir = path.join(outDir, tmpName);
  rimraf.sync(scormOutDir);
  mkdirp.sync(scormOutDir);

  // 2. Copy SCORM template
  const scormTpl = path.join(__dirname, "../templates/scorm");
  copyDir(scormTpl, scormOutDir);

  // Paths
  const appDir = path.resolve(__dirname, "../../ui/_app");
  const configDir = path.join(scormOutDir, "config");

  // Check if _app exists and has content
  if (fs.existsSync(appDir) && fs.readdirSync(appDir).length > 0) {
    // Copy app.css and app.js to config/
    for (const file of ["app.css", "app.js"]) {
      const src = path.join(appDir, file);
      const dest = path.join(configDir, file);
      if (fs.existsSync(src)) {
        fs.copyFileSync(src, dest);
      }
    }

    // Copy logo-192.png and logo-512.png to SCORM build root
    for (const file of ["logo-192.png", "logo-512.png"]) {
      const src = path.join(appDir, file);
      const dest = path.join(scormOutDir, file);
      if (fs.existsSync(src)) {
        fs.copyFileSync(src, dest);
      }
    }
  }

  // 3. Download exercises and .learn from bucket
  await downloadS3Folder(
    bucket,
    `courses/${courseSlug}/exercises/`,
    path.join(scormOutDir, "exercises")
  );
  await downloadS3Folder(
    bucket,
    `courses/${courseSlug}/.learn/`,
    path.join(scormOutDir, ".learn")
  );

  // 4. Read learn.json for course info
  const learnJson = await getCourseMetadata(bucket, courseSlug);

  // 5. Replace imsmanifest.xml
  const manifestPath = path.join(scormOutDir, "imsmanifest.xml");
  let manifest = fs.readFileSync(manifestPath, "utf-8");
  manifest = manifest.replace(/{{organization_name}}/g, "FourGeeksAcademy");
  manifest = manifest.replace(
    /{{course_title}}/g,
    learnJson.title?.en || learnJson.title || courseSlug
  );

  // Generate exercises list
  const exercisesList = getFilesList(
    path.join(scormOutDir, "exercises"),
    "exercises"
  ).join("\n      ");
  manifest = manifest.replace(/{{exercises_list}}/g, exercisesList);

  // Generate images list (optional, if you have assets)
  let imagesList = "";
  const assetsDir = path.join(scormOutDir, ".learn", "assets");
  if (fs.existsSync(assetsDir)) {
    imagesList = getFilesList(assetsDir, ".learn/assets").join("\n      ");
  }
  manifest = manifest.replace(/{{images_list}}/g, imagesList);

  fs.writeFileSync(manifestPath, manifest, "utf-8");

  // 6. Replace title in config/index.html
  const configIndexPath = path.join(scormOutDir, "config", "index.html");
  let indexHtml = fs.readFileSync(configIndexPath, "utf-8");
  indexHtml = indexHtml.replace(
    /{{title}}/g,
    learnJson.title?.en || learnJson.title || courseSlug
  );
  fs.writeFileSync(configIndexPath, indexHtml, "utf-8");

  // 7. Compress as ZIP
  const zipPath = `${scormOutDir}.zip`;
  await new Promise((resolve: any, reject: any) => {
    const output = fs.createWriteStream(zipPath);
    const archive = archiver("zip", { zlib: { level: 9 } });

    output.on("close", resolve);
    archive.on("error", reject);

    archive.pipe(output);
    archive.directory(scormOutDir, false);
    archive.finalize();
  });

  // Clean up temporary directory
  rimraf.sync(scormOutDir);

  return zipPath;
}
