import { rmSync, mkdirSync, existsSync, unlinkSync } from 'fs';
import { resolve } from 'path';
import sharp from 'sharp';

const root = resolve('.');
const dbPath = resolve(root, 'db', 'vendoo.db');
const uploadRoot = resolve(root, 'uploads');
rmSync(dbPath, { force: true });
rmSync(`${dbPath}-wal`, { force: true });
rmSync(`${dbPath}-shm`, { force: true });
rmSync(uploadRoot, { recursive: true, force: true });
mkdirSync(resolve(uploadRoot, 'test'), { recursive: true });
await sharp({ create: { width: 900, height: 1200, channels: 3, background: '#d8c1a7' } }).png().toFile(resolve(uploadRoot, 'test', 'produkt.png'));

const batch = await import('../lib/image-batch-jobs.mjs');
const { db } = await import('../lib/db.mjs');
const profiles = batch.listImageBatchProfiles();
if (profiles.length < 8) throw new Error(`Nur ${profiles.length} integrierte Profile gefunden.`);
const custom = batch.createImageBatchProfile({
  name: 'Test WebP', description: 'Verifikation', filename_pattern: '{name}-test-{index}',
  operations: { resize: { width: 640, height: 640, fit: 'contain', background: '#ffffff' }, format: 'webp', quality: 82 },
});
if (!custom?.id || custom.is_builtin) throw new Error('Eigenes Profil wurde nicht korrekt angelegt.');

const job = batch.createImageBatchJob({ source_paths: ['test/produkt.png'], profile_ids: [custom.id], name: 'Batch-Verifikation' });
batch.startImageBatchJobLoop();
const waitFor = async (id, accepted, timeout = 15000) => {
  const started = Date.now();
  while (Date.now() - started < timeout) {
    const current = batch.getImageBatchJob(id);
    if (accepted.includes(current?.status)) return current;
    await new Promise(resolveWait => setTimeout(resolveWait, 100));
  }
  throw new Error(`Timeout für Auftrag ${id}`);
};
const completed = await waitFor(job.id, ['completed','partial','failed']);
if (completed.status !== 'completed') throw new Error(`Batch-Auftrag endete mit ${completed.status}: ${completed.items?.[0]?.error_message || ''}`);
const output = completed.items[0]?.output_path;
if (!output || !existsSync(resolve(uploadRoot, output))) throw new Error('Batch-Ausgabedatei fehlt.');
const meta = await sharp(resolve(uploadRoot, output)).metadata();
if (meta.width !== 640 || meta.height !== 640 || meta.format !== 'webp') throw new Error(`Falsche Ausgabe: ${meta.width}x${meta.height} ${meta.format}`);
const version = db.prepare("SELECT * FROM image_edit_versions WHERE output_path = ? AND context = 'batch'").get(output);
if (!version) throw new Error('Nicht destruktive Batch-Version fehlt in image_edit_versions.');

await sharp({ create: { width: 700, height: 500, channels: 3, background: '#eeeeee' } }).jpeg().toFile(resolve(uploadRoot, 'test', 'pause.jpg'));
const pausedJob = batch.createImageBatchJob({ source_paths: ['test/pause.jpg'], profile_ids: [profiles[0].id], name: 'Pause-Verifikation' });
batch.pauseImageBatchJob(pausedJob.id);
await new Promise(resolveWait => setTimeout(resolveWait, 300));
if (batch.getImageBatchJob(pausedJob.id).status !== 'paused') throw new Error('Pause wurde nicht persistiert.');
batch.resumeImageBatchJob(pausedJob.id);
const resumed = await waitFor(pausedJob.id, ['completed','partial','failed']);
if (resumed.status !== 'completed') throw new Error('Fortgesetzter Auftrag wurde nicht fertig.');

await sharp({ create: { width: 400, height: 400, channels: 3, background: '#ffffff' } }).png().toFile(resolve(uploadRoot, 'test', 'fail.png'));
const retryJob = batch.createImageBatchJob({ source_paths: ['test/fail.png'], profile_ids: [custom.id], name: 'Retry-Verifikation' });
unlinkSync(resolve(uploadRoot, 'test', 'fail.png'));
const failed = await waitFor(retryJob.id, ['failed','partial']);
if (failed.status !== 'failed') throw new Error('Fehlersimulation wurde nicht als fehlgeschlagen erkannt.');
await sharp({ create: { width: 400, height: 400, channels: 3, background: '#ffffff' } }).png().toFile(resolve(uploadRoot, 'test', 'fail.png'));
batch.retryImageBatchJob(retryJob.id);
const retried = await waitFor(retryJob.id, ['completed','partial','failed']);
if (retried.status !== 'completed') throw new Error('Wiederholung war nicht erfolgreich.');

const outputs = batch.getImageBatchOutputPaths(job.id);
if (outputs.length !== 1) throw new Error('ZIP-Ausgabeliste ist inkorrekt.');
console.log(JSON.stringify({ ok: true, profiles: profiles.length, output, dimensions: `${meta.width}x${meta.height}`, pause_resume: true, retry: true }, null, 2));

db.close();
rmSync(dbPath, { force: true });
rmSync(`${dbPath}-wal`, { force: true });
rmSync(`${dbPath}-shm`, { force: true });
rmSync(uploadRoot, { recursive: true, force: true });
