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

/* ─── Safe fallback prompts per tool ─── */
const SAFE_FALLBACKS: Record<string, string> = {
  'oil-painting': 'Apply artistic oil painting texture to this image with rich colors',
  'cartoon': 'Apply a clean cartoon art style with bold colors to this image',
  'bw': 'Convert this image to black and white with high contrast',
  'golden-hour': 'Add warm golden lighting tones to this image',
  'enhance': 'Improve the quality and sharpness of this image',
  'bg-remove': 'Enhance this photo with a neutral background',
  'cinematic': 'Apply cinematic color grading with warm and cool tones',
  'illustration': 'Apply a digital art illustration style to this image',
};

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

/* Translate Arabic prompt to English using LLM */
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 a translator. Translate the following Arabic text to a concise English image editing prompt. Only output the English translation, nothing else. Keep it under 50 words.',
        },
        {
          role: 'user',
          content: arabicPrompt,
        },
      ],
    });
    const translated = result.choices[0]?.message?.content?.trim();
    if (translated) {
      console.log('[EDIT] Translated prompt:', arabicPrompt, '->', translated);
      return translated;
    }
  } catch (e) {
    console.error('[EDIT] Translation failed:', e);
  }
  return arabicPrompt;
}

/* Use LLM to create a safe version of the prompt */
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 editing prompt to be content-filter-safe while preserving the user\'s editing intent as much as possible. Use simple, neutral language. 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('[EDIT] Safe prompt:', originalPrompt, '->', safe);
      return safe;
    }
  } catch (e) {
    console.error('[EDIT] Safe prompt generation failed:', e);
  }
  return null;
}

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;
}

export async function POST(request: NextRequest) {
  const { imageUrl, prompt, label, toolType } = await request.json();

  if (!imageUrl || !prompt) {
    return new Response(JSON.stringify({ error: 'البيانات مطلوبة' }), {
      status: 400,
      headers: { 'Content-Type': 'application/json' },
    });
  }

  const encoder = new TextEncoder();

  const sendEvent = (data: object) => {
    return `data: ${JSON.stringify(data)}\n\n`;
  };

  const stream = new ReadableStream({
    async start(controller) {
      let project: { id: string } | null = null;
      try {
        console.log('[EDIT] Starting edit process...');
        console.log('[EDIT] imageUrl:', imageUrl);
        console.log('[EDIT] original prompt:', prompt.substring(0, 100));

        // Progress 5%
        controller.enqueue(encoder.encode(sendEvent({ type: 'progress', value: 5 })));

        // ── Step 1: Translate Arabic to English if needed ──
        let englishPrompt = prompt;
        if (hasArabic(prompt)) {
          controller.enqueue(encoder.encode(sendEvent({
            type: 'progress',
            value: 10,
          })));
          console.log('[EDIT] Arabic detected, translating...');
          englishPrompt = await translateToEnglish(prompt);
        }

        // Progress 15%
        controller.enqueue(encoder.encode(sendEvent({ type: 'progress', value: 15 })));

        // ── Step 2: Prepare image ──
        let imageForApi = imageUrl;
        if (imageUrl.startsWith('/')) {
          const filepath = path.join(process.cwd(), 'public', imageUrl);
          console.log('[EDIT] Reading file from:', filepath);
          let buffer = await readFile(filepath);

          // Compress large images
          if (buffer.length > 2 * 1024 * 1024) {
            console.log('[EDIT] Large image (' + Math.round(buffer.length / 1024) + 'KB), compressing...');
            try {
              const sharp = (await import('sharp')).default;
              buffer = await sharp(buffer)
                .resize(1024, 1024, { fit: 'inside', withoutEnlargement: true })
                .jpeg({ quality: 85 })
                .toBuffer();
              console.log('[EDIT] Compressed to:', Math.round(buffer.length / 1024), 'KB');
            } catch {
              console.log('[EDIT] sharp not available, using original');
            }
          }

          const base64 = buffer.toString('base64');
          imageForApi = `data:image/jpeg;base64,${base64}`;
          console.log('[EDIT] Image prepared, size:', buffer.length, 'bytes');
        }

        // Progress 20%
        controller.enqueue(encoder.encode(sendEvent({ type: 'progress', value: 20 })));

        // ── Step 3: Create project ──
        const projectTitle = `${label} — ${new Date().toLocaleString('ar-EG')}`;

        project = await db.photoProject.create({
          data: {
            title: projectTitle,
            status: 'editing',
          },
        });
        console.log('[EDIT] Project created:', project.id);

        // Progress 25%
        controller.enqueue(encoder.encode(sendEvent({ type: 'progress', value: 25 })));

        // ── Step 4: Call image edit API with retry logic ──
        console.log('[EDIT] Calling ZAI image edit API...');
        const zai = await ZAI.create();

        controller.enqueue(encoder.encode(sendEvent({ type: 'progress', value: 30 })));

        let response;
        let usedPrompt = englishPrompt;
        let retried = false;
        let retryMethod = '';

        // Attempt 1: Original (translated) prompt
        try {
          response = await zai.images.generations.edit({
            prompt: usedPrompt,
            images: [{ url: imageForApi }],
            size: '1024x1024',
          });
        } catch (firstError: unknown) {
          if (isContentFilterError(firstError)) {
            console.log('[EDIT] Content filter triggered on attempt 1');

            // Attempt 2: LLM-generated safe prompt
            controller.enqueue(encoder.encode(sendEvent({
              type: 'progress',
              value: 40,
            })));
            console.log('[EDIT] Generating safe prompt with LLM...');
            const safePrompt = await makeSafePrompt(englishPrompt);

            if (safePrompt && safePrompt !== englishPrompt) {
              usedPrompt = safePrompt;
              retryMethod = 'safe-llm';
              console.log('[EDIT] Attempt 2 with LLM safe prompt:', safePrompt);
              try {
                response = await zai.images.generations.edit({
                  prompt: usedPrompt,
                  images: [{ url: imageForApi }],
                  size: '1024x1024',
                });
              } catch (secondError: unknown) {
                if (isContentFilterError(secondError)) {
                  console.log('[EDIT] Content filter still triggered on attempt 2');
                  // Fall through to attempt 3
                } else {
                  throw secondError;
                }
              }
            }

            // Attempt 3: Tool-specific fallback
            if (!response) {
              controller.enqueue(encoder.encode(sendEvent({
                type: 'progress',
                value: 55,
              })));
              const fallback = SAFE_FALLBACKS[toolType] || 'Enhance this image artistically with improved colors and details';
              usedPrompt = fallback;
              retryMethod = 'fallback';
              retried = true;
              console.log('[EDIT] Attempt 3 with fallback:', fallback);
              response = await zai.images.generations.edit({
                prompt: usedPrompt,
                images: [{ url: imageForApi }],
                size: '1024x1024',
              });
            }
          } else {
            throw firstError;
          }
        }

        console.log('[EDIT] ZAI response received, data length:', response.data?.length);

        controller.enqueue(encoder.encode(sendEvent({ type: 'progress', value: 80 })));

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

        const imageBase64 = response.data[0].base64;
        const buffer = Buffer.from(imageBase64, 'base64');
        console.log('[EDIT] Edited image received, size:', buffer.length, 'bytes');

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

        const editFilename = `edited_${crypto.randomBytes(8).toString('hex')}.png`;
        const editFilepath = path.join(editDir, editFilename);
        await writeFile(editFilepath, buffer);

        const editedImageUrl = `/edited/${editFilename}`;
        console.log('[EDIT] Image saved to:', editedImageUrl);

        controller.enqueue(encoder.encode(sendEvent({ type: 'progress', value: 90 })));

        // ── Step 6: Save to database ──
        let displayLabel = label || 'تعديل';
        if (retryMethod === 'safe-llm') {
          displayLabel = `${label} (تم التعديل تلقائياً)`;
        } else if (retryMethod === 'fallback') {
          displayLabel = `${label} (تعديل بديل)`;
        }

        if (project) {
          await db.photoEdit.create({
            data: {
              order: 1,
              toolType: toolType || 'custom',
              toolLabel: displayLabel,
              prompt: usedPrompt,
              originalPath: imageUrl,
              editedPath: editedImageUrl,
              photoProjectId: project.id,
            },
          });

          await db.photoProject.update({
            where: { id: project.id },
            data: { status: 'completed' },
          });
        }

        controller.enqueue(encoder.encode(sendEvent({ type: 'progress', value: 100 })));
        controller.enqueue(encoder.encode(sendEvent({
          type: 'done',
          editedImageUrl,
          projectId: project?.id,
          retried: retryMethod !== '',
          retryMethod,
        })));
        console.log('[EDIT] Edit completed!', retryMethod ? `(method: ${retryMethod})` : '(original prompt)');
      } catch (error: unknown) {
        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 {
            message = raw.length > 150 ? raw.substring(0, 150) + '...' : raw;
          }
        }
        console.error('[EDIT] Error:', message);
        controller.enqueue(encoder.encode(sendEvent({ type: 'error', message })));

        if (project) {
          try {
            await db.photoProject.update({
              where: { id: project.id },
              data: { status: 'failed' },
            });
          } catch {}
        }
      } finally {
        controller.close();
      }
    },
  });

  return new Response(stream, {
    headers: {
      'Content-Type': 'text/event-stream',
      'Cache-Control': 'no-cache',
      Connection: 'keep-alive',
    },
  });
}