<?php

namespace App\Modules\Ai\Http\Controllers;

use App\Core\Contracts\Ai\AiImageGenerationPort;
use App\Core\Http\Controllers\BaseApiController;
use App\Models\ImageGeneration;
use App\Models\Setting;
use App\Modules\Ai\Exceptions\OpenAiImageGenerationException;
use App\Modules\Ai\Services\ImagePromptEnhancerService;
use App\Modules\Ai\Services\ImageStyleCatalog;
use App\Services\Subscriptions\StudioQuotaService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Throwable;

/**
 * Madar AI Studio — توليد الصور مع Prompt Enhancement.
 */
class AiImageController extends BaseApiController
{
    public function __construct(
        private readonly StudioQuotaService $studioQuota,
        private readonly AiImageGenerationPort $imageGeneration,
        private readonly ImagePromptEnhancerService $promptEnhancer,
    ) {}

    public function options(): JsonResponse
    {
        $settings = Setting::current();

        return $this->successResponse('OK', [
            'styles' => ImageStyleCatalog::allStyles(),
            'qualities' => [
                ['id' => 'low', 'label' => 'سريع'],
                ['id' => 'medium', 'label' => 'متوسط'],
                ['id' => 'high', 'label' => 'احترافي'],
            ],
            'aspects' => [
                ['id' => '1:1', 'label' => '1:1'],
                ['id' => '16:9', 'label' => '16:9'],
                ['id' => '9:16', 'label' => '9:16'],
                ['id' => '4:3', 'label' => '4:3'],
                ['id' => '3:4', 'label' => '3:4'],
            ],
            'defaults' => [
                'enhance_prompt' => (bool) $settings->image_prompt_enhancer_enabled,
                'quality' => $settings->image_default_quality,
                'model' => $settings->image_model,
            ],
        ]);
    }

    public function enhancePreview(Request $request): JsonResponse
    {
        $data = $request->validate([
            'prompt' => ['required', 'string', 'max:2000'],
            'style' => ['nullable', 'string', 'max:64'],
            'aspect_ratio' => ['nullable', 'string', 'max:16'],
            'quality' => ['nullable', 'string', 'in:low,medium,high,auto'],
        ]);

        $settings = Setting::current();
        $quality = $data['quality'] ?? $settings->image_default_quality ?? 'high';

        $result = $this->promptEnhancer->enhance(
            $data['prompt'],
            $data['style'] ?? null,
            $data['aspect_ratio'] ?? null,
            $quality,
            $request->user()->id,
        );

        return $this->successResponse('OK', [
            'enhanced_prompt' => $result['enhanced_prompt'],
            'used_ai' => $result['used_ai'],
        ]);
    }

    public function index(Request $request): JsonResponse
    {
        $user = $request->user();
        $page = max(1, (int) $request->query('page', 1));
        $per = min(50, max(5, (int) $request->query('per_page', 20)));

        $q = ImageGeneration::query()->where('user_id', $user->id)->orderByDesc('id');
        $total = (clone $q)->count();
        $rows = $q->forPage($page, $per)->get();

        $items = $rows->map(fn (ImageGeneration $g) => $this->jobPayload($g))->all();

        $lastPage = max(1, (int) ceil($total / $per));

        return $this->successResponse('OK', [
            'items' => $items,
            'meta' => [
                'current_page' => $page,
                'per_page' => $per,
                'total' => $total,
                'last_page' => $lastPage,
                'has_more' => $page < $lastPage,
            ],
        ]);
    }

    public function store(Request $request): JsonResponse
    {
        $user = $request->user();

        try {
            $this->studioQuota->assertCanUse(
                $user,
                'image_generation',
                'توليد الصور متاح للمشتركين في Pro و Ultra.'
            );
        } catch (\Illuminate\Validation\ValidationException $e) {
            $msg = collect($e->errors())->flatten()->first() ?: 'غير مسموح';

            return $this->errorResponse($msg, ['code' => 'image_generation_locked'], 403);
        }

        $data = $request->validate([
            'prompt' => ['required', 'string', 'max:2000'],
            'style' => ['nullable', 'string', 'max:64'],
            'aspect_ratio' => ['nullable', 'string', 'max:16'],
            'quality' => ['nullable', 'string', 'in:low,medium,high,auto'],
            'enhance_prompt' => ['nullable', 'boolean'],
        ]);

        $settings = Setting::current();
        $originalPrompt = trim($data['prompt']);
        $style = ImageStyleCatalog::resolveStyleKey($data['style'] ?? null);
        $aspectRatio = $data['aspect_ratio'] ?? '1:1';
        $quality = $data['quality'] ?? $settings->image_default_quality ?? 'high';
        $model = $this->resolveImageModel($settings);
        $shouldEnhance = $request->boolean('enhance_prompt', (bool) $settings->image_prompt_enhancer_enabled);

        $job = ImageGeneration::query()->create([
            'user_id' => $user->id,
            'original_prompt' => $originalPrompt,
            'prompt' => $originalPrompt,
            'style' => $style,
            'aspect_ratio' => $aspectRatio,
            'model' => $model,
            'quality' => $quality,
            'status' => ImageGeneration::STATUS_QUEUED,
            'provider' => null,
            'meta' => ['enhance_prompt' => $shouldEnhance],
        ]);

        try {
            $enhanced = $shouldEnhance
                ? $this->promptEnhancer->enhance($originalPrompt, $style, $aspectRatio, $quality, $user->id)
                : [
                    'enhanced_prompt' => ImageStyleCatalog::buildFallbackPrompt($originalPrompt, $style, $aspectRatio, $quality),
                    'used_ai' => false,
                ];

            $job->update(['enhanced_prompt' => $enhanced['enhanced_prompt']]);

            Log::info('ai.image_generation_start', [
                'job_id' => $job->id,
                'user_id' => $user->id,
                'model' => $model,
                'quality' => $quality,
                'style' => $style,
                'used_ai_enhancer' => $enhanced['used_ai'],
            ]);

            $result = $this->imageGeneration->generate(
                $enhanced['enhanced_prompt'],
                $aspectRatio,
                $quality,
                $model,
            );

            $job->update([
                'image_url' => $result['image_url'],
                'status' => ImageGeneration::STATUS_COMPLETED,
                'provider' => $result['provider'],
                'model' => $result['model'] ?? $model,
                'meta' => array_filter([
                    'enhance_prompt' => $shouldEnhance,
                    'used_ai_enhancer' => $enhanced['used_ai'],
                    'external_id' => $result['external_id'] ?? null,
                ]),
            ]);
            $job->refresh();

            return $this->successResponse('تم إنشاء الصورة', [
                'job' => $this->jobPayload($job, includeEnhanced: $request->boolean('show_enhanced', false)),
            ], 201);
        } catch (OpenAiImageGenerationException $e) {
            $this->logGenerationFailure($job->id, $user->id, $e);

            $job->update([
                'status' => ImageGeneration::STATUS_FAILED,
                'meta' => array_merge($job->meta ?? [], [
                    'error' => $e->userMessage(),
                    'api_error' => $e->apiMessage(),
                    'error_code' => $e->errorCode(),
                ]),
            ]);

            return $this->errorResponse(
                $e->userMessage(),
                [
                    'code' => $e->errorCode(),
                    'detail' => $e->apiMessage(),
                    'job_id' => $job->id,
                ],
                $e->httpStatus() >= 400 && $e->httpStatus() < 600 ? $e->httpStatus() : 502
            );
        } catch (Throwable $e) {
            $this->logGenerationFailure($job->id, $user->id, $e);

            $job->update([
                'status' => ImageGeneration::STATUS_FAILED,
                'meta' => array_merge($job->meta ?? [], ['error' => $e->getMessage()]),
            ]);

            return $this->errorResponse(
                $e->getMessage() !== '' ? $e->getMessage() : 'تعذر توليد الصورة',
                ['code' => 'image_generation_failed', 'job_id' => $job->id],
                502
            );
        }
    }

    public function file(Request $request, int $id): BinaryFileResponse|JsonResponse
    {
        $gen = ImageGeneration::query()
            ->where('user_id', $request->user()->id)
            ->findOrFail($id);

        $stored = $gen->image_url;
        if (! is_string($stored) || $stored === '') {
            return $this->errorResponse('لا توجد صورة بعد', null, 404);
        }

        $relative = preg_replace('#^/storage/#', '', $stored);
        if ($relative === $stored && str_starts_with($stored, 'http')) {
            return $this->errorResponse('استخدم رابط التخزين المحلي', null, 404);
        }

        if (! Storage::disk('public')->exists($relative)) {
            return $this->errorResponse('ملف الصورة غير موجود على الخادم', null, 404);
        }

        return response()->file(
            Storage::disk('public')->path($relative),
            [
                'Content-Type' => 'image/png',
                'Cache-Control' => 'private, max-age=86400',
            ]
        );
    }

    /**
     * @return array<string, mixed>
     */
    private function jobPayload(ImageGeneration $g, bool $includeEnhanced = false): array
    {
        $payload = [
            'id' => $g->id,
            'prompt' => $g->original_prompt ?? $g->prompt,
            'original_prompt' => $g->original_prompt ?? $g->prompt,
            'style' => $g->style,
            'aspect_ratio' => $g->aspect_ratio,
            'model' => $g->model,
            'quality' => $g->quality,
            'status' => $g->status,
            'result_url' => $g->image_url,
            'image_url' => $g->image_url,
            'preview_url' => $g->image_url ? url('/api/ai/images/'.$g->id.'/file') : null,
            'created_at' => $g->created_at?->toIso8601String(),
        ];

        if ($includeEnhanced) {
            $payload['enhanced_prompt'] = $g->enhanced_prompt;
        }

        return $payload;
    }

    private function resolveImageModel(Setting $settings): string
    {
        $model = trim((string) $settings->image_model);
        if ($model !== '' && in_array($model, ['gpt-image-1', 'gpt-image-1-mini'], true)) {
            return $model;
        }

        $env = trim((string) config('openai.image_model', 'gpt-image-1'));

        return in_array($env, ['gpt-image-1', 'gpt-image-1-mini'], true) ? $env : 'gpt-image-1';
    }

    private function logGenerationFailure(int $jobId, int $userId, Throwable $e): void
    {
        $context = [
            'job_id' => $jobId,
            'user_id' => $userId,
            'message' => $e->getMessage(),
            'exception' => $e::class,
        ];

        if ($e instanceof OpenAiImageGenerationException) {
            $context = array_merge($context, $e->logContext());
        }

        Log::error('ai.image_generation_failed', $context);
    }
}
