<?php

declare(strict_types=1);

namespace App\Http\Controllers\Moderation;

use App\Http\Controllers\Controller;
use App\Models\EnhanceJob;
use App\Services\Enhance\EnhanceService;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Inertia\Inertia;
use Inertia\Response;

final class ModerationEnhanceController extends Controller
{
    public function __construct(
        private readonly EnhanceService $enhanceService,
    ) {
    }

    public function index(Request $request): Response
    {
        $filters = [
            'status' => trim((string) $request->query('status', 'all')),
            'engine' => trim((string) $request->query('engine', 'all')),
            'mode' => trim((string) $request->query('mode', 'all')),
            'scale' => trim((string) $request->query('scale', 'all')),
            'user' => trim((string) $request->query('user', '')),
            'date_from' => trim((string) $request->query('date_from', '')),
            'date_to' => trim((string) $request->query('date_to', '')),
        ];

        $jobs = EnhanceJob::query()
            ->with(['user:id,name,username', 'artwork:id,title,slug'])
            ->when($filters['status'] !== '' && $filters['status'] !== 'all', fn ($query) => $query->where('status', $filters['status']))
            ->when($filters['engine'] !== '' && $filters['engine'] !== 'all', fn ($query) => $query->where('engine', $filters['engine']))
            ->when($filters['mode'] !== '' && $filters['mode'] !== 'all', fn ($query) => $query->where('mode', $filters['mode']))
            ->when($filters['scale'] !== '' && $filters['scale'] !== 'all', fn ($query) => $query->where('scale', (int) $filters['scale']))
            ->when($filters['user'] !== '', function ($query) use ($filters): void {
                $query->whereHas('user', function ($userQuery) use ($filters): void {
                    $userQuery
                        ->where('name', 'like', '%' . $filters['user'] . '%')
                        ->orWhere('username', 'like', '%' . $filters['user'] . '%');
                });
            })
            ->when($filters['date_from'] !== '', fn ($query) => $query->whereDate('created_at', '>=', $filters['date_from']))
            ->when($filters['date_to'] !== '', fn ($query) => $query->whereDate('created_at', '<=', $filters['date_to']))
            ->latest('id')
            ->paginate(20)
            ->withQueryString()
            ->through(fn (EnhanceJob $job): array => $this->serializeJob($job));

        return Inertia::render('Moderation/Enhance/Index', [
            'title' => 'Enhance Jobs',
            'jobs' => $jobs,
            'filters' => $filters,
            'options' => [
                'statuses' => ['all', 'pending', 'queued', 'processing', 'completed', 'failed', 'cancelled', 'expired'],
                'engines' => ['all', 'stub', 'external_worker'],
                'modes' => array_merge(['all'], (array) config('enhance.allowed_modes', [])),
                'scales' => array_merge(['all'], array_map('intval', (array) config('enhance.allowed_scales', []))),
            ],
            'indexUrl' => route('admin.enhance.index'),
            'enhanceConfig' => $this->enhanceService->frontendConfig(),
        ])->rootView('moderation');
    }

    public function show(EnhanceJob $enhanceJob): Response
    {
        $enhanceJob->loadMissing(['user:id,name,username', 'artwork:id,title,slug']);

        return Inertia::render('Moderation/Enhance/Show', [
            'title' => 'Enhance Job #' . $enhanceJob->id,
            'job' => $this->serializeJob($enhanceJob, true),
            'indexUrl' => route('admin.enhance.index'),
            'enhanceConfig' => $this->enhanceService->frontendConfig(),
        ])->rootView('moderation');
    }

    public function retry(EnhanceJob $enhanceJob): RedirectResponse
    {
        $this->authorize('retry', $enhanceJob);

        $job = $this->enhanceService->retry($enhanceJob);

        return redirect()
            ->route('admin.enhance.show', ['enhanceJob' => $job])
            ->with('success', 'Enhance job queued again.');
    }

    public function markFailed(Request $request, EnhanceJob $enhanceJob): RedirectResponse
    {
        $this->authorize('markFailed', $enhanceJob);

        $job = $this->enhanceService->markFailedByModerator($enhanceJob, $request->user());

        return redirect()
            ->route('admin.enhance.show', ['enhanceJob' => $job])
            ->with('success', 'Enhance job marked as failed.');
    }

    public function destroy(EnhanceJob $enhanceJob): RedirectResponse
    {
        $this->authorize('delete', $enhanceJob);

        $this->enhanceService->delete($enhanceJob);

        return redirect()
            ->route('admin.enhance.index')
            ->with('success', 'Enhance job deleted.');
    }

    private function serializeJob(EnhanceJob $job, bool $detailed = false): array
    {
        return [
            'id' => $job->id,
            'status' => (string) $job->status,
            'engine' => (string) $job->engine,
            'mode' => (string) $job->mode,
            'scale' => (int) $job->scale,
            'source_url' => $job->sourceUrl(),
            'output_url' => $job->outputUrl(),
            'preview_url' => $job->previewUrl(),
            'input_width' => (int) ($job->input_width ?? 0),
            'input_height' => (int) ($job->input_height ?? 0),
            'input_filesize' => (int) ($job->input_filesize ?? 0),
            'input_mime' => $job->input_mime,
            'output_width' => (int) ($job->output_width ?? 0),
            'output_height' => (int) ($job->output_height ?? 0),
            'output_filesize' => (int) ($job->output_filesize ?? 0),
            'output_mime' => $job->output_mime,
            'processing_seconds' => $job->processing_seconds,
            'error_message' => $job->error_message,
            'metadata' => $job->metadata ?? [],
            'created_at' => optional($job->created_at)?->toIso8601String(),
            'queued_at' => optional($job->queued_at)?->toIso8601String(),
            'started_at' => optional($job->started_at)?->toIso8601String(),
            'finished_at' => optional($job->finished_at)?->toIso8601String(),
            'expires_at' => optional($job->expires_at)?->toIso8601String(),
            'user' => $job->user ? [
                'id' => $job->user->id,
                'name' => $job->user->name,
                'username' => $job->user->username,
            ] : null,
            'artwork' => $job->artwork ? [
                'id' => $job->artwork->id,
                'title' => $job->artwork->title,
                'slug' => $job->artwork->slug,
                'url' => route('art.show', ['id' => $job->artwork->id, 'slug' => $job->artwork->slug]),
            ] : null,
            'show_url' => route('admin.enhance.show', ['enhanceJob' => $job]),
            'download_url' => $job->outputUrl(),
            'retry_url' => route('admin.enhance.retry', ['enhanceJob' => $job]),
            'mark_failed_url' => route('admin.enhance.mark-failed', ['enhanceJob' => $job]),
            'delete_url' => route('admin.enhance.destroy', ['enhanceJob' => $job]),
            'can_retry' => $job->status === EnhanceJob::STATUS_FAILED,
            'can_mark_failed' => in_array($job->status, [EnhanceJob::STATUS_PENDING, EnhanceJob::STATUS_QUEUED, EnhanceJob::STATUS_PROCESSING], true),
            'detailed' => $detailed,
        ];
    }
}