import { execFile } from 'child_process';
import { existsSync, mkdtempSync, readFileSync, rmSync } from 'fs';
import * as os from 'os';
import * as path from 'path';
import { promisify } from 'util';

const execFileAsync = promisify(execFile);

const FLUX_MAC_SCRIPT_PATH = process.env.FLUX_MAC_SCRIPT_PATH || '/home/administrator/scripts/flux-mac-generate.py';
const FLUX_MAC_SERVER = process.env.FLUX_MAC_SERVER || process.env.COMFY_MAC_URL || 'http://10.10.0.2:8188';
const FLUX_MAC_MODEL_PRESET = process.env.FLUX_MAC_MODEL_PRESET || '4b';
const FLUX_MAC_REALISM_PRESET = process.env.FLUX_MAC_REALISM_PRESET || 'photo';
const FLUX_MAC_DEFAULT_WIDTH = parseInt(process.env.FLUX_MAC_DEFAULT_WIDTH || '1024', 10);
const FLUX_MAC_DEFAULT_HEIGHT = parseInt(process.env.FLUX_MAC_DEFAULT_HEIGHT || '576', 10);
const FLUX_MAC_TIMEOUT_SECONDS = parseInt(process.env.FLUX_MAC_TIMEOUT_SECONDS || '900', 10);
const FLUX_MAC_ENABLED = process.env.FLUX_MAC_ENABLED !== 'false';

export interface GenerateFluxMacImageOptions {
  negativePrompt?: string;
  filenamePrefix?: string;
  width?: number;
  height?: number;
  timeoutSeconds?: number;
}

export interface FluxMacImageResult {
  buffer: Buffer;
  localPath: string;
  server: string;
  modelPreset: string;
  realismPreset: string;
  seed: number | null;
  prompt: string;
  negativePrompt: string;
}

interface FluxMacGenerateResponse {
  downloaded?: Array<{ local_path?: string }>;
  server?: string;
  seed?: number;
  prompt?: string;
  negative?: string;
  model_preset?: string;
  realism_preset?: string;
  status?: string;
}

export function isFluxMacEnabled(): boolean {
  return FLUX_MAC_ENABLED && existsSync(FLUX_MAC_SCRIPT_PATH);
}

export async function generateFluxMacImage(
  prompt: string,
  options: GenerateFluxMacImageOptions = {},
): Promise<FluxMacImageResult | null> {
  if (!isFluxMacEnabled()) {
    return null;
  }

  const trimmedPrompt = prompt.trim();
  if (!trimmedPrompt) {
    return null;
  }

  const width = options.width ?? FLUX_MAC_DEFAULT_WIDTH;
  const height = options.height ?? FLUX_MAC_DEFAULT_HEIGHT;
  const timeoutSeconds = options.timeoutSeconds ?? FLUX_MAC_TIMEOUT_SECONDS;
  const negativePrompt = (options.negativePrompt || '').trim();
  const tempDir = mkdtempSync(path.join(os.tmpdir(), 'rainmaker-flux-mac-'));

  const args = [
    FLUX_MAC_SCRIPT_PATH,
    'generate',
    '--prompt',
    trimmedPrompt,
    '--model-preset',
    FLUX_MAC_MODEL_PRESET,
    '--realism-preset',
    FLUX_MAC_REALISM_PRESET,
    '--width',
    String(width),
    '--height',
    String(height),
    '--server',
    FLUX_MAC_SERVER,
    '--timeout',
    String(timeoutSeconds),
    '--local-output-dir',
    tempDir,
  ];

  if (negativePrompt) {
    args.push('--negative', negativePrompt);
  }

  if (options.filenamePrefix) {
    args.push('--filename-prefix', options.filenamePrefix);
  }

  try {
    const { stdout } = await execFileAsync('python3', args, {
      cwd: '/home/administrator',
      maxBuffer: 8 * 1024 * 1024,
      timeout: Math.max(timeoutSeconds + 30, 60) * 1000,
    });

    const payload = JSON.parse(stdout) as FluxMacGenerateResponse;
    if (payload.status !== 'completed') {
      return null;
    }

    const localPath = payload.downloaded?.[0]?.local_path;
    if (!localPath || !existsSync(localPath)) {
      return null;
    }

    return {
      buffer: readFileSync(localPath),
      localPath,
      server: payload.server || FLUX_MAC_SERVER,
      modelPreset: payload.model_preset || FLUX_MAC_MODEL_PRESET,
      realismPreset: payload.realism_preset || FLUX_MAC_REALISM_PRESET,
      seed: typeof payload.seed === 'number' ? payload.seed : null,
      prompt: payload.prompt || trimmedPrompt,
      negativePrompt: payload.negative || negativePrompt,
    };
  } finally {
    rmSync(tempDir, { recursive: true, force: true });
  }
}
