import { NextRequest } from 'next/server';
import ZAI from 'z-ai-web-dev-sdk';
import { writeFile, mkdir } from 'fs/promises';
import path from 'path';
import crypto from 'crypto';

/* ─── In-memory job store ─── */
type JobStatus = 'translating' | 'generating' | 'retrying' | 'done' | 'error';

interface GenJob {
  id: string;
  status: JobStatus;
  progress: number;
  message: string;
  imageUrl?: string;
  error?: string;
  size: string;
  prompt: string;
  createdAt: number;
}

const jobs = new Map<string, GenJob>();

// Cleanup old jobs every 5 minutes
setInterval(() => {
  const now = Date.now();
  for (const [id, job] of jobs) {
    if (now - job.createdAt > 10 * 60 * 1000) jobs.delete(id);
  }
}, 5 * 60 * 1000);

/* ─── Constants ─── */
const SUPPORTED_SIZES = [
  { id: 'square', label: 'مربع (1:1)', value: '1024x1024' },
  { id: 'portrait', label: 'عمودي (3:4)', value: '864x1152' },
  { id: 'landscape', label: 'أفقي (16:9)', value: '1344x768' },
  { id: 'wide', label: 'عريض (2:1)', value: '1440x720' },
];

const PROGRESS_MESSAGES = [
  'جارٍ تحليل الوصف...',
  'يتم تحضير الألوان والأشكال...',
  'الذكاء الاصطناعي يرسم الآن...',
  'جارٍ إضافة التفاصيل...',
  'يتم تحسين الجودة...',
  'أقرب من أي وقت مضى...',
];

/* ─── Helpers ─── */
function hasArabic(text: string): boolean {
  return /[\u0600-\u06FF]/.test(text);
}

async function translateToEnglish(arabicPrompt: string): Promise<string> {
  try {
    const zai = await ZAI.create();
    const result = await zai.chat.completions.create({
      model: 'glm-4-flash',
      messages: [
        {
          role: 'system',
          content:
            'You are an expert image prompt writer. Translate the following Arabic text into a detailed, high-quality English image generation prompt. Add artistic and quality details. Output ONLY the English prompt, nothing else. Keep under 80 words.',
        },
        { role: 'user', content: arabicPrompt },
      ],
    });
    const translated = result.choices[0]?.message?.content?.trim();
    if (translated) {
      console.log('[GEN] Translated:', arabicPrompt.substring(0, 50), '->', translated.substring(0, 80));
      return translated;
    }
  } catch (e) {
    console.error('[GEN] Translation failed:', e);
  }
  return arabicPrompt;
}

async function makeSafePrompt(originalPrompt: string): Promise<string> {
  try {
    const zai = await ZAI.create();
    const result = await zai.chat.completions.create({
      model: 'glm-4-flash',
      messages: [
        {
          role: 'system',
          content:
            'Rewrite the following image generation prompt to be content-filter-safe while preserving the visual intent as much as possible. Use simple, positive, artistic language. Avoid any sensitive, violent, or controversial themes. Output ONLY the rewritten English prompt, nothing else. Keep under 40 words.',
        },
        { role: 'user', content: originalPrompt },
      ],
    });
    const safe = result.choices[0]?.message?.content?.trim();
    if (safe) {
      console.log('[GEN] Safe prompt:', originalPrompt.substring(0, 50), '->', safe);
      return safe;
    }
  } catch (e) {
    console.error('[GEN] Safe prompt generation failed:', e);
  }
  return '';
}

function isContentFilterError(error: unknown): boolean {
  if (error instanceof Error) {
    const m = error.message;
    return m.includes('contentFilter') || m.includes('1301') || m.includes('敏感') || m.includes('不安全');
  }
  return false;
}

function classifyError(error: unknown): string {
  let message = 'حدث خطأ غير متوقع أثناء الرسم';
  if (error instanceof Error) {
    const raw = error.message;
    if (isContentFilterError(error)) {
      message = 'لم نتمكن من رسم هذه الصورة بسبب قيود أمان. جرّب وصفاً مختلفاً.';
    } else if (raw.includes('400')) {
      message = 'وصف غير صالح. جرّب وصفاً أوضح وأبسط.';
    } else if (raw.includes('429')) {
      message = 'طلبات كثيرة. انتظر قليلاً ثم حاول.';
    } else if (raw.includes('500') || raw.includes('502') || raw.includes('503')) {
      message = 'خدمة الرسم غير متاحة حالياً. حاول بعد قليل.';
    } else if (raw.includes('ECONNREFUSED') || raw.includes('fetch failed') || raw.includes('network')) {
      message = 'خطأ في الاتصال بالخادم. حاول بعد قليل.';
    } else {
      message = raw.length > 120 ? raw.substring(0, 120) + '...' : raw;
    }
  }
  return message;
}

/* ─── Background generation worker ─── */
async function runGeneration(job: GenJob) {
  try {
    console.log('[GEN] Job', job.id, 'started');

    // ── Step 1: Translate Arabic to English ──
    let englishPrompt = job.prompt.trim();
    if (hasArabic(englishPrompt)) {
      job.status = 'translating';
      job.message = 'جارٍ ترجمة الوصف إلى الإنجليزية...';
      console.log('[GEN] Job', job.id, 'translating...');
      englishPrompt = await translateToEnglish(englishPrompt);
    }

    // ── Step 2: Generate image ──
    job.status = 'generating';
    job.progress = 20;
    job.message = PROGRESS_MESSAGES[0];
    console.log('[GEN] Job', job.id, 'generating...');

    const zai = await ZAI.create();
    let response;
    let usedPrompt = englishPrompt;

    // Simulate progress during generation
    const progressTimer = setInterval(() => {
      if (job.status === 'generating' || job.status === 'retrying') {
        job.progress = Math.min(job.progress + 2, 85);
        job.message = PROGRESS_MESSAGES[Math.floor(Math.random() * PROGRESS_MESSAGES.length)];
      }
    }, 3000);

    try {
      response = await zai.images.generations.create({ prompt: usedPrompt, size: job.size });
    } catch (err1: unknown) {
      console.error('[GEN] Job', job.id, 'attempt 1 error:', err1 instanceof Error ? err1.message : err1);

      if (!isContentFilterError(err1)) {
        clearInterval(progressTimer);
        throw err1;
      }

      // ── Attempt 2: LLM safe rewrite ──
      job.status = 'retrying';
      job.message = 'جارٍ تعديل الوصف ليتوافق مع متطلبات الأمان...';
      console.log('[GEN] Job', job.id, 'content filter hit, generating safe prompt...');

      const safePrompt = await makeSafePrompt(englishPrompt);
      if (safePrompt && safePrompt !== englishPrompt) {
        usedPrompt = safePrompt;
        console.log('[GEN] Job', job.id, 'attempt 2 with safe prompt:', safePrompt);
        try {
          response = await zai.images.generations.create({ prompt: usedPrompt, size: job.size });
        } catch (err2: unknown) {
          console.error('[GEN] Job', job.id, 'attempt 2 error:', err2 instanceof Error ? err2.message : err2);
          if (!isContentFilterError(err2)) {
            clearInterval(progressTimer);
            throw err2;
          }
          response = undefined;
        }
      }

      // ── Attempt 3: Generic fallback ──
      if (!response) {
        usedPrompt = 'A beautiful artistic illustration, vibrant colors, high quality, detailed, professional artwork';
        console.log('[GEN] Job', job.id, 'attempt 3 with generic fallback');
        try {
          response = await zai.images.generations.create({ prompt: usedPrompt, size: job.size });
        } catch (err3: unknown) {
          clearInterval(progressTimer);
          throw err3;
        }
      }
    }

    clearInterval(progressTimer);

    if (!response || !response.data?.[0]?.base64) {
      throw new Error('لم يتم الحصول على صورة من الذكاء الاصطناعي');
    }

    const buffer = Buffer.from(response.data[0].base64, 'base64');
    console.log('[GEN] Job', job.id, 'image received, size:', buffer.length, 'bytes');

    // ── Save image ──
    const genDir = path.join(process.cwd(), 'public', 'generated');
    await mkdir(genDir, { recursive: true });

    const filename = `gen_${crypto.randomBytes(8).toString('hex')}.png`;
    await writeFile(path.join(genDir, filename), buffer);

    job.status = 'done';
    job.progress = 100;
    job.message = 'تم بنجاح!';
    job.imageUrl = `/generated/${filename}`;
    console.log('[GEN] Job', job.id, 'completed:', job.imageUrl);

  } catch (error: unknown) {
    const errorMsg = classifyError(error);
    console.error('[GEN] Job', job.id, 'failed:', errorMsg);
    job.status = 'error';
    job.error = errorMsg;
    job.message = errorMsg;
  }
}

/* ─── POST: Start a new generation job ─── */
export async function POST(request: NextRequest) {
  const { prompt, sizeId } = await request.json();

  if (!prompt || !prompt.trim()) {
    return Response.json({ error: 'يرجى كتابة وصف للصورة' }, { status: 400 });
  }

  const sizeInfo = SUPPORTED_SIZES.find((s) => s.id === sizeId) || SUPPORTED_SIZES[0];

  const job: GenJob = {
    id: crypto.randomBytes(12).toString('hex'),
    status: 'translating',
    progress: 5,
    message: 'جارٍ البدء...',
    size: sizeInfo.value,
    prompt: prompt.trim(),
    createdAt: Date.now(),
  };

  jobs.set(job.id, job);
  console.log('[GEN] Job created:', job.id, 'prompt:', prompt.substring(0, 50));

  // Run generation in background (fire and forget)
  runGeneration(job).catch((e) => {
    console.error('[GEN] Job', job.id, 'unhandled error:', e);
    job.status = 'error';
    job.error = 'حدث خطأ غير متوقع';
  });

  // Return immediately with jobId
  return Response.json({
    jobId: job.id,
    status: job.status,
    message: job.message,
  });
}

/* ─── GET: Poll job status ─── */
export async function GET(request: NextRequest) {
  const { searchParams } = new URL(request.url);
  const jobId = searchParams.get('jobId');

  // Return available sizes if no jobId
  if (!jobId) {
    return Response.json({ sizes: SUPPORTED_SIZES });
  }

  const job = jobs.get(jobId);

  if (!job) {
    return Response.json({ error: 'العملية غير موجودة' }, { status: 404 });
  }

  return Response.json({
    jobId: job.id,
    status: job.status,
    progress: job.progress,
    message: job.message,
    imageUrl: job.imageUrl || null,
    error: job.error || null,
  });
}