import 'dotenv/config';
import { Worker } from 'bullmq';
import sharp from 'sharp';
import { PrismaClient } from 'prisma/postgres/generated/prisma/client/postgres/client';
import * as path from 'node:path';
import { promises as fsp } from 'node:fs';
import { resolveAttachmentsRoot } from 'src/time-and-attendance/attachments/config/attachment.config';
import { adapterPostgres } from 'prisma.config.postgres';

const prisma = new PrismaClient({ adapter: adapterPostgres });
const q_name = `${process.env.BULL_PREFIX || 'attachments'}:variants`;
const root = resolveAttachmentsRoot();

const variants = [
    { name: 'thumb.jpeg', build: (s: sharp.Sharp) => s.rotate().jpeg({ quality: 80 }).resize({ width: 128 }) },
    { name: '256w.webp', build: (s: sharp.Sharp) => s.rotate().webp({ quality: 80 }).resize({ width: 256 }) },
    { name: '1024w.webp', build: (s: sharp.Sharp) => s.rotate().webp({ quality: 82 }).resize({ width: 1024 }) },
]

new Worker(q_name, async job => {
    const attachment_id: number = job.data.attachmentId ?? job.data.attachment_id;
    if (!attachment_id) return;

    const attachment = await prisma.attachments.findUnique({
        where: { id: attachment_id },
        include: { blob: true },
    });
    if (!attachment) return;

    const source_abs = path.join(root, attachment.blob.storage_path);

    for (const variant of variants) {
        const relative = `${attachment.blob.storage_path}.${variant.name}`;
        const out_Abs = path.join(root, relative);

        //try for idem paths
        try { await fsp.stat(out_Abs); continue; } catch { }

        await fsp.mkdir(path.dirname(out_Abs), { recursive: true });

        //generate variant
        await variant.build(sharp(source_abs)).toFile(out_Abs);

        //meta data of generated variant file
        const meta = await sharp(out_Abs).metadata();
        const bytes = (await fsp.stat(out_Abs)).size;
        await prisma.attachmentVariants.upsert({
            where: { attachment_id_variant: { attachment_id: attachment_id, variant: variant.name } },
            update: { path: relative, bytes, width: meta.width ?? null, height: meta.height ?? null },
            create: { path: relative, bytes, width: meta.width ?? null, height: meta.height ?? null, attachment_id: attachment_id, variant: variant.name },
        } as any);
    }
}, {
    connection: { url: process.env.REDIS_URL }, concurrency: 3
}
);