<?php

namespace App\Services\FaceSwap;

use App\Contracts\FaceSwapDriverInterface;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;

class WaveSpeedDriver implements FaceSwapDriverInterface
{
    protected string $baseUrl;
    protected string $apiKey;
    protected int $timeout;
    protected int $pollInterval;
    protected int $maxPollAttempts;

    public function __construct()
    {
        $this->baseUrl = rtrim(config('faceswap.drivers.wavespeed.base_url'), '/');
        $this->apiKey = config('faceswap.drivers.wavespeed.api_key');
        $this->timeout = (int) config('faceswap.drivers.wavespeed.timeout', 120);
        $this->pollInterval = (int) config('faceswap.drivers.wavespeed.poll_interval', 15);
        $this->maxPollAttempts = (int) config('faceswap.drivers.wavespeed.max_poll_attempts', 40);
    }

    public function process(string $faceImageData, string $productImageData): string
    {
        $tempFiles = [];

        try {
            // Inputs hosted via TempImageHost — never written to a public disk.
            // Cloud mode → DO Spaces presigned URL. Local mode → signed Laravel
            // route serving from tryon_local (requires APP_URL reachable from
            // the WaveSpeed servers; use a tunnel locally).
            $personUrl = TempImageHost::upload($faceImageData, 'wavespeed', $tempFiles);
            $garmentUrl = TempImageHost::upload($productImageData, 'wavespeed', $tempFiles);

            $predictionId = $this->createPrediction($personUrl, $garmentUrl);

            Log::info('WaveSpeed prediction created', ['prediction_id' => $predictionId]);

            $resultUrl = $this->pollUntilComplete($predictionId);

            return $this->downloadResult($resultUrl);
        } finally {
            TempImageHost::cleanup($tempFiles);
        }
    }

    protected function createPrediction(string $personUrl, string $garmentUrl): string
    {
        $response = Http::timeout($this->timeout)
            ->withHeaders([
                'Authorization' => 'Bearer ' . $this->apiKey,
                'Content-Type' => 'application/json',
            ])
            ->post($this->baseUrl . '/api/v3/wavespeed-ai/ai-virtual-outfit-tryon', [
                'image' => $personUrl,
                'clothes_images' => [$garmentUrl],
            ]);

        if (!$response->successful()) {
            throw new \Exception('WaveSpeed API error: HTTP ' . $response->status());
        }

        $data = $response->json();
        $id = $data['id'] ?? null;

        if (!$id) {
            throw new \Exception('WaveSpeed API error: no prediction ID returned');
        }

        return $id;
    }

    protected function pollUntilComplete(string $predictionId): string
    {
        for ($i = 0; $i < $this->maxPollAttempts; $i++) {
            sleep($this->pollInterval);

            $response = Http::timeout(30)
                ->withHeaders([
                    'Authorization' => 'Bearer ' . $this->apiKey,
                ])
                ->get($this->baseUrl . '/api/v3/predictions/' . $predictionId . '/result');

            if (!$response->successful()) {
                Log::warning('WaveSpeed poll error', [
                    'prediction_id' => $predictionId,
                    'attempt' => $i + 1,
                    'status' => $response->status(),
                ]);
                continue;
            }

            $data = $response->json();
            $status = $data['status'] ?? null;

            if ($status === 'completed') {
                $outputs = $data['outputs'] ?? [];

                if (empty($outputs)) {
                    throw new \Exception('WaveSpeed prediction completed but no outputs returned');
                }

                return $outputs[0];
            }

            if ($status === 'failed' || $status === 'error') {
                throw new \Exception('WaveSpeed processing failed: ' . ($data['error'] ?? 'Unknown'));
            }

            Log::debug('WaveSpeed polling', [
                'prediction_id' => $predictionId,
                'attempt' => $i + 1,
                'status' => $status,
            ]);
        }

        throw new \Exception('WaveSpeed processing timed out after ' . ($this->maxPollAttempts * $this->pollInterval) . ' seconds');
    }

    protected function downloadResult(string $url): string
    {
        $response = Http::timeout(60)->get($url);

        if (!$response->successful()) {
            throw new \Exception('Failed to download WaveSpeed result: HTTP ' . $response->status());
        }

        return $response->body();
    }
}
