<?php

namespace App\Console\Commands;

use App\Models\Avatar;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Str;
use Laravel\Ai\Image;

/**
 * One-off/backfill command: generates a real portrait photo per Avatar row missing
 * `source_path`, via the Gemini image model, so the wizard/details pages can
 * show an actual picture instead of the initials-badge fallback. Saved under
 * public/assets/avatars (a shipped static asset, tracked in git — not the `storage` disk,
 * since these are stock catalogue photos rather than per-user uploads).
 */
class GenerateAvatarPhotos extends Command
{
    protected $signature = 'avatars:generate-photos {--force : Regenerate even avatars that already have a source_path}';

    protected $description = 'Generate a portrait photo for each stock Avatar via Gemini';

    public function handle(): int
    {
        $avatars = $this->option('force')
            ? Avatar::all()
            : Avatar::whereNull('source_path')->get();

        if ($avatars->isEmpty()) {
            $this->info('No avatars need a photo.');

            return self::SUCCESS;
        }

        $failedCount = 0;

        foreach ($avatars as $avatar) {
            $this->line("Generating photo for {$avatar->name} ({$avatar->gender}, {$avatar->accent})...");

            $prompt = sprintf(
                'A professional headshot portrait photo of a fictional, non-identifiable %s %s person, '
                .'friendly neutral expression, plain studio background, soft even lighting, shoulders-up '
                .'framing, photorealistic, anatomically correct, no text, no logos, no watermarks.',
                $avatar->accent ?: 'international',
                $avatar->gender ?: 'person',
            );

            try {
                $image = Image::of($prompt)
                    ->size('1:1')
                    ->quality('high')
                    ->generate(provider: 'gemini', model: config('ai.providers.gemini.models.image.default'))
                    ->firstImage();

                $source = imagecreatefromstring($image->content());
                if ($source === false) {
                    throw new \RuntimeException('Gemini returned an unreadable portrait image.');
                }

                $scaled = imagescale($source, 1024, 1024);
                if ($scaled === false) {
                    throw new \RuntimeException('Could not resize the generated portrait.');
                }

                ob_start();
                $encoded = imagejpeg($scaled, null, 85);
                $jpeg = ob_get_clean();
                if (! $encoded || ! is_string($jpeg)) {
                    throw new \RuntimeException('Could not encode the generated portrait.');
                }

                $relativePath = 'assets/avatars/'.Str::random(40).'.jpg';
                File::ensureDirectoryExists(public_path('assets/avatars'));
                if (File::put(public_path($relativePath), $jpeg) === false) {
                    throw new \RuntimeException('Could not save the generated portrait.');
                }

                $avatar->update(['source_path' => $relativePath]);
                $this->info("Saved {$relativePath}");
            } catch (\Throwable $e) {
                $failedCount++;
                $this->error("Failed to generate a photo for {$avatar->name}: {$e->getMessage()}");
            }
        }

        return $failedCount === 0 ? self::SUCCESS : self::FAILURE;
    }
}
