import { readdir } from "fs/promises";
import { join } from "path";
import { createHash } from "crypto";
import exifr from "exifr";
import { z } from "zod";

const exifSchema = z.object({
  DateTimeOriginal: z.date(),
  Make: z.string(),
  Model: z.string(),
  LensModel: z.string(),
  FNumber: z.number(),
  ExposureTime: z.number(),
  ISO: z.number(),
  FocalLength: z.number(),
  ExifImageWidth: z.number(),
  ExifImageHeight: z.number(),
});

export default defineCachedEventHandler(
  async () => {
    const publicDir = join(process.cwd(), "public/gallery");

    try {
      const files = await readdir(publicDir);
      const imageFiles = files.filter((file) =>
        /\.(jpg|jpeg|png|webp)$/i.test(file),
      );

      const imagesWithExif = await Promise.all(
        imageFiles.map(async (filename) => {
          const filePath = join(publicDir, filename);
          const rawExif = await exifr.parse(filePath, {
            tiff: true,
            exif: true,
            gps: false,
            interop: false,
            ifd1: false,
          });

          const exif = exifSchema.parse(rawExif);

          return {
            filename,
            url: `/gallery/${filename}`,
            width: exif.ExifImageWidth,
            height: exif.ExifImageHeight,
            exif: {
              date: exif.DateTimeOriginal,
              camera: `${exif.Make} ${exif.Model}`,
              lens: exif.LensModel,
              settings: {
                aperture: `f/${exif.FNumber}`,
                shutter: `1/${Math.round(1 / exif.ExposureTime)}s`,
                iso: String(exif.ISO),
                focalLength: `${exif.FocalLength}mm`,
              },
            },
          };
        }),
      );

      return imagesWithExif;
    } catch (err) {
      console.log(err);
      throw createError({
        statusCode: 500,
        message: "Failed to read gallery directory",
      });
    }
  },
  {
    maxAge: 60 * 60 * 24,
    getKey: async () => {
      const publicDir = join(process.cwd(), "public/gallery");
      try {
        const files = await readdir(publicDir);
        const imageFiles = files.filter((file) =>
          /\.(jpg|jpeg|png|webp)$/i.test(file),
        );
        const filesConcat = imageFiles.sort().join("");
        const hash = createHash("sha256").update(filesConcat).digest("hex");
        return `gallery:${hash}`;
      } catch {
        return "gallery:0";
      }
    },
  },
);
