import http from 'http';
import { once } from 'events';
import { readFileSync } from 'fs';
import { resolve } from 'path';
import {
  generateWithLocalFlux,
  getLocalFluxRuntimeInfo,
  interruptLocalFlux,
  cancelLocalFluxPrompt,
} from '../lib/ai-local-images.mjs';

let submittedWorkflow = null;
let promptSubmissions = 0;
let interrupted = false;
let deletedQueueIds = [];
const imageBytes = Buffer.from('vendoo-slice-30-mock-image');

const server = http.createServer(async (req, res) => {
  const sendJson = (status, payload) => {
    res.writeHead(status, { 'Content-Type': 'application/json' });
    res.end(JSON.stringify(payload));
  };
  if (req.method === 'GET' && req.url === '/system_stats') {
    return sendJson(200, { system: { os: 'mock-os', comfyui_version: 'mock-1' }, devices: [{ name: 'Mock GPU', vram_total: 16 * 1024 ** 3, vram_free: 12 * 1024 ** 3 }] });
  }
  if (req.method === 'GET' && req.url === '/queue') {
    return sendJson(200, {
      queue_running: [[1, 'mock-running', {}, {}, []]],
      queue_pending: [[2, 'mock-pending', {}, {}, []]],
    });
  }
  if (req.method === 'POST' && req.url === '/queue') {
    let body = '';
    for await (const chunk of req) body += chunk;
    deletedQueueIds = JSON.parse(body || '{}').delete || [];
    return sendJson(200, { ok: true });
  }
  if (req.method === 'GET' && req.url.startsWith('/history?')) {
    return sendJson(200, { 'mock-prompt': { outputs: {} } });
  }
  if (req.method === 'POST' && req.url === '/interrupt') {
    interrupted = true;
    return sendJson(200, { ok: true });
  }
  if (req.method === 'POST' && req.url === '/prompt') {
    promptSubmissions += 1;
    let body = '';
    for await (const chunk of req) body += chunk;
    submittedWorkflow = JSON.parse(body).prompt;
    return sendJson(200, { prompt_id: 'slice30-prompt-id' });
  }
  if (req.method === 'GET' && req.url === '/history/slice30-prompt-id') {
    return sendJson(200, {
      'slice30-prompt-id': {
        outputs: {
          9: { images: [{ filename: 'slice30.png', subfolder: '', type: 'output' }] },
        },
      },
    });
  }
  if (req.method === 'GET' && req.url.startsWith('/view?')) {
    res.writeHead(200, { 'Content-Type': 'image/png' });
    return res.end(imageBytes);
  }
  return sendJson(404, { error: `Unhandled ${req.method} ${req.url}` });
});

server.listen(0, '127.0.0.1');
await once(server, 'listening');
const address = server.address();
const settings = {
  ai_model_photo_local_enabled: '1',
  ai_model_photo_local_url: `http://127.0.0.1:${address.port}`,
  ai_model_photo_local_workflow_path: resolve('local-ai/workflows/vendoo_flux_schnell_api.json'),
  ai_model_photo_use_source_reference: '0',
  ai_model_photo_local_resolution: '768',
};

try {
  const phases = [];
  const result = await generateWithLocalFlux({
    prompt: 'Studio product photo with soft light',
    settings,
    mode: 'prompt',
    sourceDataUrl: '',
    width: 768,
    height: 768,
    seed: 1234,
    steps: 4,
    onPhase: (phase) => phases.push(phase),
  });
  if (result.prompt_id !== 'slice30-prompt-id') throw new Error('Prompt-ID wurde nicht zurückgegeben.');
  if (Buffer.from(result.base64, 'base64').compare(imageBytes) !== 0) throw new Error('Mock-Bild stimmt nicht.');
  const classTypes = Object.values(submittedWorkflow || {}).map(node => node?.class_type).filter(Boolean);
  if (classTypes.includes('LoadImage')) throw new Error('Promptmodus enthält unerlaubten LoadImage-Knoten.');
  if (!phases.includes('submitted') || !phases.includes('rendering') || !phases.includes('completed')) throw new Error(`Phasen unvollständig: ${phases.join(', ')}`);

  let cancelledBeforeSubmit = false;
  try {
    await generateWithLocalFlux({
      prompt: 'This job must not be submitted', settings, mode: 'prompt', isCancelled: () => true,
    });
  } catch (error) {
    cancelledBeforeSubmit = error?.code === 'FLUX_CANCELLED';
  }
  if (!cancelledBeforeSubmit || promptSubmissions !== 1) throw new Error('Abbruch vor der ComfyUI-Übergabe ist nicht sicher.');

  const runtime = await getLocalFluxRuntimeInfo(settings, { historyLimit: 20 });
  if (!runtime.reachable || runtime.queue_summary.running !== 1 || runtime.queue_summary.pending !== 1) throw new Error('Queue/System-Diagnose ist falsch.');
  if (runtime.system_stats?.devices?.[0]?.name !== 'Mock GPU') throw new Error('GPU-Systemdaten fehlen.');

  const pendingCancel = await cancelLocalFluxPrompt('mock-pending', settings);
  if (pendingCancel.mode !== 'dequeued' || !deletedQueueIds.includes('mock-pending')) throw new Error('Gezieltes Entfernen eines wartenden Auftrags ist fehlgeschlagen.');
  const runningCancel = await cancelLocalFluxPrompt('mock-running', settings);
  if (runningCancel.mode !== 'interrupted' || !interrupted) throw new Error('Laufender Auftrag wurde nicht unterbrochen.');
  await interruptLocalFlux(settings);
  if (!interrupted) throw new Error('Interrupt-Endpunkt wurde nicht aufgerufen.');

  const rawWorkflow = JSON.parse(readFileSync(settings.ai_model_photo_local_workflow_path, 'utf8').replace(/^\uFEFF/, ''));
  if (Object.values(rawWorkflow).some(node => node?.class_type === 'LoadImage')) throw new Error('Ausgelieferter freier Promptworkflow enthält LoadImage.');

  console.log(JSON.stringify({
    ok: true,
    prompt_id: result.prompt_id,
    phases,
    queue_summary: runtime.queue_summary,
    gpu: runtime.system_stats.devices[0].name,
    interrupt: interrupted,
    targeted_pending_cancel: deletedQueueIds.includes('mock-pending'),
    targeted_running_cancel: runningCancel.mode === 'interrupted',
    cancelled_before_submit: cancelledBeforeSubmit,
    prompt_submissions: promptSubmissions,
    load_image_in_prompt_workflow: false,
  }, null, 2));
} finally {
  server.close();
}
