<?php
/**
 * Edit API Endpoint (SSE Streaming)
 * POST: Accept {imageUrl, prompt, label, toolType}
 *      Process edit with ZaiApi, stream SSE progress events
 *      3-tier retry: original → LLM safe → tool fallback
 */

require_once __DIR__ . '/../includes/ZaiApi.php';
require_once __DIR__ . '/../includes/Database.php';

$baseDir = dirname(__DIR__);

/* ─── Safe fallback prompts per tool ─── */
$SAFE_FALLBACKS = [
    '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',
];

/* ─── Helper functions ─── */
function hasArabic(string $text): bool {
    return (bool)preg_match('/[\x{0600}-\x{06FF}]/u', $text);
}

function translateToEnglish(string $arabicPrompt): string {
    try {
        $zai = new ZaiApi();
        $result = $zai->chatCompletion('glm-4-flash', [
            [
                '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,
            ],
        ]);
        $translated = $result['choices'][0]['message']['content'] ?? '';
        $translated = trim($translated);
        if ($translated) {
            error_log('[EDIT] Translated prompt: ' . $arabicPrompt . ' -> ' . $translated);
            return $translated;
        }
    } catch (Exception $e) {
        error_log('[EDIT] Translation failed: ' . $e->getMessage());
    }
    return $arabicPrompt;
}

function makeSafePrompt(string $originalPrompt): ?string {
    try {
        $zai = new ZaiApi();
        $result = $zai->chatCompletion('glm-4-flash', [
            [
                '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,
            ],
        ]);
        $safe = $result['choices'][0]['message']['content'] ?? '';
        $safe = trim($safe);
        if ($safe) {
            error_log('[EDIT] Safe prompt: ' . $originalPrompt . ' -> ' . $safe);
            return $safe;
        }
    } catch (Exception $e) {
        error_log('[EDIT] Safe prompt generation failed: ' . $e->getMessage());
    }
    return null;
}

function isContentFilterError(string $msg): bool {
    return (
        strpos($msg, 'contentFilter') !== false ||
        strpos($msg, '1301') !== false ||
        mb_strpos($msg, '敏感') !== false ||
        mb_strpos($msg, '不安全') !== false
    );
}

function sseSend(array $eventData): void {
    echo "data: " . json_encode($eventData, JSON_UNESCAPED_UNICODE) . "\n\n";
    ob_flush();
    flush();
}

/* ─── Route handling ─── */
$method = $_SERVER['REQUEST_METHOD'];

if ($method !== 'POST') {
    http_response_code(405);
    header('Content-Type: application/json; charset=utf-8');
    echo json_encode(['error' => 'طريقة الطلب غير مدعومة']);
    exit;
}

// SSE headers — must be set BEFORE any output
header('Content-Type: text/event-stream; charset=utf-8');
header('Cache-Control: no-cache');
header('Connection: keep-alive');
header('X-Accel-Buffering: no');

// Disable output buffering for SSE
if (ob_get_level()) {
    ob_end_clean();
}
ob_implicit_flush(true);

// Parse input
$input = json_decode(file_get_contents('php://input'), true);
$imageUrl = $input['imageUrl'] ?? '';
$prompt   = $input['prompt'] ?? '';
$label    = $input['label'] ?? 'تعديل';
$toolType = $input['toolType'] ?? 'custom';

if (empty($imageUrl) || empty($prompt)) {
    sseSend(['type' => 'error', 'message' => 'البيانات مطلوبة']);
    exit;
}

$projectId = null;
$zai = null;
$retryMethod = '';

try {
    error_log('[EDIT] Starting edit process...');
    error_log('[EDIT] imageUrl: ' . $imageUrl);
    error_log('[EDIT] original prompt: ' . mb_substr($prompt, 0, 100));

    // Progress 5%
    sseSend(['type' => 'progress', 'value' => 5]);

    // ── Step 1: Translate Arabic to English if needed ──
    $englishPrompt = $prompt;
    if (hasArabic($prompt)) {
        sseSend(['type' => 'progress', 'value' => 10]);
        error_log('[EDIT] Arabic detected, translating...');
        $englishPrompt = translateToEnglish($prompt);
    }

    // Progress 15%
    sseSend(['type' => 'progress', 'value' => 15]);

    // ── Step 2: Prepare image ──
    $imageForApi = $imageUrl;
    if (strpos($imageUrl, '/') === 0) {
        // Local file — read and convert to base64
        $filepath = $baseDir . '/public' . $imageUrl;
        error_log('[EDIT] Reading file from: ' . $filepath);

        if (!file_exists($filepath)) {
            sseSend(['type' => 'error', 'message' => 'الصورة الأصلية غير موجودة']);
            exit;
        }

        $imageData = file_get_contents($filepath);
        $imageSize = strlen($imageData);

        // Compress large images (>2MB) by resizing and converting to JPEG
        if ($imageSize > 2 * 1024 * 1024) {
            error_log('[EDIT] Large image (' . round($imageSize / 1024) . 'KB), compressing...');
            if (function_exists('imagecreatefromstring')) {
                $srcImg = @imagecreatefromstring($imageData);
                if ($srcImg) {
                    // Get current dimensions
                    $origW = imagesx($srcImg);
                    $origH = imagesy($srcImg);

                    // Scale down to max 1024px on longest side
                    $maxDim = 1024;
                    if ($origW > $maxDim || $origH > $maxDim) {
                        $ratio = min($maxDim / $origW, $maxDim / $origH);
                        $newW = (int)($origW * $ratio);
                        $newH = (int)($origH * $ratio);
                    } else {
                        $newW = $origW;
                        $newH = $origH;
                    }

                    $dstImg = imagecreatetruecolor($newW, $newH);
                    imagecopyresampled($dstImg, $srcImg, 0, 0, 0, 0, $newW, $newH, $origW, $origH);

                    // Capture JPEG output
                    ob_start();
                    imagejpeg($dstImg, null, 85);
                    $imageData = ob_get_clean();
                    $imageSize = strlen($imageData);

                    imagedestroy($srcImg);
                    imagedestroy($dstImg);

                    error_log('[EDIT] Compressed to: ' . round($imageSize / 1024) . 'KB');
                }
            }
        }

        $base64 = base64_encode($imageData);
        $imageForApi = 'data:image/jpeg;base64,' . $base64;
        error_log('[EDIT] Image prepared, size: ' . $imageSize . ' bytes');
    }

    // Progress 20%
    sseSend(['type' => 'progress', 'value' => 20]);

    // ── Step 3: Create project ──
    $projectTitle = $label . ' — ' . date('Y-m-d H:i:s');
    $db = Database::getInstance();
    $projectId = 'proj-' . bin2hex(random_bytes(8));

    $stmt = $db->prepare("INSERT INTO PhotoProject (id, title, status, createdAt, updatedAt)
                          VALUES (:id, :title, :status, datetime('now'), datetime('now'))");
    $stmt->execute([
        ':id'     => $projectId,
        ':title'  => $projectTitle,
        ':status' => 'editing',
    ]);
    error_log('[EDIT] Project created: ' . $projectId);

    // Progress 25%
    sseSend(['type' => 'progress', 'value' => 25]);

    // ── Step 4: Call image edit API with 3-tier retry ──
    error_log('[EDIT] Calling ZAI image edit API...');
    $zai = new ZaiApi();

    sseSend(['type' => 'progress', 'value' => 30]);

    $response = null;
    $usedPrompt = $englishPrompt;
    $retried = false;
    $retryMethod = '';

    // Attempt 1: Original (translated) prompt
    try {
        $response = $zai->imageEdit($usedPrompt, $imageForApi, '1024x1024');
    } catch (Exception $firstError) {
        $firstMsg = $firstError->getMessage();

        if (isContentFilterError($firstMsg)) {
            error_log('[EDIT] Content filter triggered on attempt 1');

            // Attempt 2: LLM-generated safe prompt
            sseSend(['type' => 'progress', 'value' => 40]);
            error_log('[EDIT] Generating safe prompt with LLM...');
            $safePrompt = makeSafePrompt($englishPrompt);

            if ($safePrompt && $safePrompt !== $englishPrompt) {
                $usedPrompt = $safePrompt;
                $retryMethod = 'safe-llm';
                error_log('[EDIT] Attempt 2 with LLM safe prompt: ' . $safePrompt);
                try {
                    $response = $zai->imageEdit($usedPrompt, $imageForApi, '1024x1024');
                } catch (Exception $secondError) {
                    $secondMsg = $secondError->getMessage();
                    if (isContentFilterError($secondMsg)) {
                        error_log('[EDIT] Content filter still triggered on attempt 2');
                        $response = null;
                    } else {
                        throw $secondError;
                    }
                }
            }

            // Attempt 3: Tool-specific fallback
            if (!$response) {
                sseSend(['type' => 'progress', 'value' => 55]);
                $fallback = $SAFE_FALLBACKS[$toolType] ?? 'Enhance this image artistically with improved colors and details';
                $usedPrompt = $fallback;
                $retryMethod = 'fallback';
                $retried = true;
                error_log('[EDIT] Attempt 3 with fallback: ' . $fallback);
                $response = $zai->imageEdit($usedPrompt, $imageForApi, '1024x1024');
            }
        } else {
            throw $firstError;
        }
    }

    error_log('[EDIT] ZAI response received, data count: ' . count($response['data'] ?? []));

    sseSend(['type' => 'progress', 'value' => 80]);

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

    $imageBase64 = $response['data'][0]['base64'];
    $editedData = base64_decode($imageBase64);
    error_log('[EDIT] Edited image received, size: ' . strlen($editedData) . ' bytes');

    // ── Step 5: Save edited image ──
    $editDir = $baseDir . '/public/edited';
    if (!is_dir($editDir)) {
        mkdir($editDir, 0755, true);
    }

    $editFilename = 'edited_' . bin2hex(random_bytes(8)) . '.png';
    file_put_contents($editDir . '/' . $editFilename, $editedData);

    $editedImageUrl = '/edited/' . $editFilename;
    error_log('[EDIT] Image saved to: ' . $editedImageUrl);

    sseSend(['type' => 'progress', 'value' => 90]);

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

    $editId = 'edit-' . bin2hex(random_bytes(8));
    $stmt = $db->prepare("INSERT INTO PhotoEdit (id, \"order\", toolType, toolLabel, prompt, originalPath, editedPath, photoProjectId, createdAt)
                          VALUES (:id, 1, :toolType, :toolLabel, :prompt, :originalPath, :editedPath, :projectId, datetime('now'))");
    $stmt->execute([
        ':id'           => $editId,
        ':toolType'     => $toolType,
        ':toolLabel'    => $displayLabel,
        ':prompt'       => $usedPrompt,
        ':originalPath' => $imageUrl,
        ':editedPath'   => $editedImageUrl,
        ':projectId'    => $projectId,
    ]);

    $db->prepare("UPDATE PhotoProject SET status = 'completed', updatedAt = datetime('now') WHERE id = :id")
       ->execute([':id' => $projectId]);

    sseSend(['type' => 'progress', 'value' => 100]);
    sseSend([
        'type'           => 'done',
        'editedImageUrl' => $editedImageUrl,
        'projectId'      => $projectId,
        'retried'        => $retryMethod !== '',
        'retryMethod'    => $retryMethod,
    ]);
    error_log('[EDIT] Edit completed!' . ($retryMethod ? " (method: $retryMethod)" : ' (original prompt)'));

} catch (Exception $error) {
    $rawMsg = $error->getMessage();
    $message = 'حدث خطأ غير متوقع أثناء التعديل';

    if (isContentFilterError($rawMsg)) {
        $message = 'عذراً، هذه الصورة لا يمكن تعديلها حالياً بسبب قيود أمان. جرّب صورة مختلفة أو استخدم أدوات مثل "تحسين الجودة" أو "لوحة زيتية".';
    } elseif (strpos($rawMsg, '400') !== false) {
        $message = 'طلب غير صالح. جرّب تغيير وصف التعديل.';
    } elseif (strpos($rawMsg, '429') !== false) {
        $message = 'طلبات كثيرة جداً. انتظر قليلاً ثم حاول مجدداً.';
    } elseif (strpos($rawMsg, '500') !== false || strpos($rawMsg, '502') !== false || strpos($rawMsg, '503') !== false) {
        $message = 'خدمة الذكاء الاصطناعي غير متاحة حالياً. حاول بعد قليل.';
    } else {
        $message = mb_strlen($rawMsg) > 150 ? mb_substr($rawMsg, 0, 150) . '...' : $rawMsg;
    }

    error_log('[EDIT] Error: ' . $message);
    sseSend(['type' => 'error', 'message' => $message]);

    // Mark project as failed
    if ($projectId) {
        try {
            $db = Database::getInstance();
            $db->prepare("UPDATE PhotoProject SET status = 'failed', updatedAt = datetime('now') WHERE id = :id")
               ->execute([':id' => $projectId]);
        } catch (Exception $e) {
            // Ignore DB update failure
        }
    }
}