<?php

namespace App\Http\Controllers;

use App\Jobs\GenerateImagenBatch;
use App\Models\ImageProcessingStatus;
use Illuminate\Bus\Batch;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Bus;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Validator;

class ImageBatchController extends Controller
{
	/**
	 * Start batch image generation
	 */
	public function startBatch(Request $request)
	{
		$validator = Validator::make($request->all(), [
			'images'       => 'required|array|min:1|max:20',
			'images.*.id'  => 'required|string|max:255',
			'images.*.alt' => 'required|string|max:1000'
		]);
		
		if ($validator->fails()) {
			return response()->json([
				'success' => false,
				'error'   => 'Validation failed',
				'errors'  => $validator->errors()
			], 422);
		}
		
		try {
			$images = $request->input('images');
			
			// Create jobs array for batch processing
			$jobs = [];
			foreach ($images as $image) {
				$jobs[] = new GenerateImagenBatch(
					imageId: $image['id'],
					prompt: $this->getValidLengthPrompt($image['alt'])
				);
			}
			
			// Dispatch batch with callbacks
			$batch = Bus::batch($jobs)
				->name("Image_Generation_Batch_" . uniqid() . '_' . now()->format('YmdHis'))
				->then(function (Batch $batch) {
					Log::info("All image generation jobs completed successfully", [
						'batch_id'       => $batch->id,
						'total_jobs'     => $batch->totalJobs,
						'processed_jobs' => $batch->processedJobs(),
						'failed_jobs'    => $batch->failedJobs
					]);
				})
				->catch(function (Batch $batch, \Throwable $e) {
					Log::error("Image generation batch failed", [
						'batch_id'    => $batch->id,
						'error'       => $e->getMessage(),
						'failed_jobs' => $batch->failedJobs
					]);
				})
				->finally(function (Batch $batch) {
					Log::info("Image generation batch finished", [
						'batch_id'       => $batch->id,
						'total_jobs'     => $batch->totalJobs,
						'processed_jobs' => $batch->processedJobs(),
						'failed_jobs'    => $batch->failedJobs,
						'finished_at'    => now()->toISOString()
					]);
				})
				->dispatch();
			
			Log::info("Image generation batch started", [
				'batch_id'              => $batch->id,
				'total_expected_images' => count($images)
			]);
			
			return response()->json([
				'success'               => true,
				'batch_id'              => $batch->id,
				'total_expected_images' => count($images),
				'message'               => 'Batch image generation started successfully'
			]);
			
		} catch (\Exception $e) {
			Log::error('Failed to start batch image generation', [
				'error' => $e->getMessage(),
				'trace' => $e->getTraceAsString()
			]);
			
			return response()->json([
				'success' => false,
				'error'   => 'Failed to start batch processing: ' . $e->getMessage()
			], 500);
		}
	}
	
	/**
	 * Check batch processing status
	 */
	public function checkBatchStatus($batchId = null)
	{
		if (empty($batchId)) {
			return response()->json([
				'success' => false,
				'error'   => 'Validation failed',
				'errors'  => 'No data found.'
			], 422);
		}
		
		try {
			// Get batch processing status from database
			$statusRecords = ImageProcessingStatus::where('batch_job_id', $batchId)
				->get(['image_id', 'status', 'image_path', 'error_message', 'metadata', 'completed_at'])
				->keyBy('image_id');
			
			// Get Laravel batch info
			$batch = Bus::findBatch($batchId);
			
			$batchInfo = null;
			if ($batch) {
				$batchInfo = [
					'id'             => $batch->id,
					'name'           => $batch->name,
					'total_jobs'     => $batch->totalJobs,
					'pending_jobs'   => $batch->pendingJobs,
					'processed_jobs' => $batch->processedJobs(),
					'progress'       => $batch->progress(),
					'finished'       => $batch->finished(),
					'cancelled'      => $batch->cancelled(),
					'failed_jobs'    => $batch->failedJobs,
					'created_at'     => $batch->createdAt,
					'finished_at'    => $batch->finishedAt,
				];
			}
			
			// Transform status records for frontend
			$images = [];
			foreach ($statusRecords as $imageId => $record) {
				$images[] = [
					'image_id'      => $imageId,
					'status'        => $record->status,
					'image_url'     => $record->image_path ? '/storage/' . $record->image_path : null,
					'error_message' => $record->error_message,
					'completed_at'  => $record->completed_at?->toISOString(),
					'metadata'      => $record->metadata
				];
			}
			
			return response()->json([
				'success'    => true,
				'batch_info' => $batchInfo,
				'images'     => $images,
				'summary'    => [
					'total'      => count($images),
					'completed'  => collect($images)->where('status', 'completed')->count(),
					'processing' => collect($images)->where('status', 'processing')->count(),
					'failed'     => collect($images)->where('status', 'failed')->count(),
					'pending'    => collect($images)->where('status', 'pending')->count(),
					'retrying'   => collect($images)->where('status', 'retrying')->count(),
				]
			]);
			
		} catch (\Exception $e) {
			Log::error('Failed to check batch status', [
				'batch_id' => $batchId,
				'error'    => $e->getMessage()
			]);
			
			return response()->json([
				'success' => false,
				'error'   => 'Failed to check batch status: ' . $e->getMessage()
			], 500);
		}
	}
	
	/**
	 * Get specific image status by image IDs
	 */
	public function getImageStatuses(Request $request)
	{
		$validator = Validator::make($request->all(), [
			'image_ids'   => 'required|array|min:1',
			'image_ids.*' => 'required|string',
		]);
		
		if ($validator->fails()) {
			return response()->json([
				'success' => false,
				'error'   => 'Validation failed',
				'errors'  => $validator->errors()
			], 422);
		}
		
		try {
			$imageIds = $request->input('image_ids');
			
			$statusRecords = ImageProcessingStatus::whereIn('image_id', $imageIds)
				->where('status', 'completed')
				->whereNotNull('image_path')
				->get(['image_id', 'image_path', 'completed_at', 'metadata'])
				->keyBy('image_id');
			
			$completedImages = [];
			foreach ($statusRecords as $imageId => $record) {
				$completedImages[] = [
					'image_id'     => $imageId,
					'image_url'    => $record->image_path ? '/storage/' . $record->image_path : null,
					'completed_at' => $record->completed_at?->toISOString(),
					'metadata'     => $record->metadata
				];
			}
			
			return response()->json([
				'success'          => true,
				'completed_images' => $completedImages,
				'total_requested'  => count($imageIds),
				'total_completed'  => count($completedImages)
			]);
			
		} catch (\Exception $e) {
			Log::error('Failed to get image statuses', [
				'image_ids' => $request->input('image_ids'),
				'error'     => $e->getMessage()
			]);
			
			return response()->json([
				'success' => false,
				'error'   => 'Failed to get image statuses: ' . $e->getMessage()
			], 500);
		}
	}
	
	/**
	 * Generate a single image immediately (not batched)
	 */
	public function generateSingle(Request $request)
	{
		$validator = Validator::make($request->all(), [
			'prompt' => 'required|string|max:1000',
			'alt' => 'required|string|max:500',
			'type' => 'nullable|string|in:thumbnail,article'
		]);
		
		if ($validator->fails()) {
			return response()->json([
				'success' => false,
				'error' => 'Validation failed',
				'errors' => $validator->errors()
			], 422);
		}
		
		try {
			$prompt = $this->getValidLengthPrompt($request->input('prompt'));
			$alt = $request->input('alt');
			$type = $request->input('type', 'article');
			$imageId = 'single_' . uniqid() . '_' . now()->format('YmdHis');
			
			// For now, use GenerateImagenBatch job synchronously for single image
			// In production, you might want to use a different API endpoint or service
			$job = new GenerateImagenBatch(
				imageId: $imageId,
				prompt: $prompt
			);
			
			// Dispatch the job synchronously
			dispatch_sync($job);
			
			// Get the result from database
			$status = ImageProcessingStatus::where('image_id', $imageId)->first();
			
			if ($status && $status->status === 'completed' && $status->image_path) {
				return response()->json([
					'success' => true,
					'image_url' => '/storage/' . $status->image_path,
					'image_id' => $imageId,
					'alt' => $alt,
					'type' => $type,
					'message' => 'Image generated successfully'
				]);
			} elseif ($status && $status->status === 'failed') {
				throw new \Exception($status->error_message ?? 'Image generation failed');
			} else {
				// If not completed immediately, return a pending status
				// Frontend can poll for the result if needed
				return response()->json([
					'success' => true,
					'status' => 'pending',
					'image_id' => $imageId,
					'message' => 'Image generation started, please wait...'
				]);
			}
			
		} catch (\Exception $e) {
			Log::error('Failed to generate single image', [
				'error' => $e->getMessage(),
				'prompt' => $request->input('prompt')
			]);
			
			return response()->json([
				'success' => false,
				'error' => 'Failed to generate image: ' . $e->getMessage()
			], 500);
		}
	}
	
	/**
	 * Limit prompt to valid length (max 350 words for safety)
	 */
	private function getValidLengthPrompt(string $prompt, int $maxWords = 350): string
	{
		$words = explode(' ', $prompt);
		if (count($words) <= $maxWords) {
			return $prompt;
		}
		
		return implode(' ', array_slice($words, 0, $maxWords));
	}
}