<?php

namespace App\Services\FaceSwap;

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

class FaceMintDriver 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.facemint.base_url'), '/');
        $this->apiKey = config('faceswap.drivers.facemint.api_key');
        $this->timeout = (int) config('faceswap.drivers.facemint.timeout', 120);
        $this->pollInterval = (int) config('faceswap.drivers.facemint.poll_interval', 3);
        $this->maxPollAttempts = (int) config('faceswap.drivers.facemint.max_poll_attempts', 60);
    }

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

        try {
            // Inputs are hosted via TempImageHost (private storage + signed URL
            // in local mode, or DO Spaces presigned URL in cloud mode). Never
            // written to a public disk.
            $faceUrl = TempImageHost::upload($faceImageData, 'facemint', $tempFiles);
            $productUrl = TempImageHost::upload($productImageData, 'facemint', $tempFiles);

            $taskId = $this->createTask($productUrl, $faceUrl);

            Log::info('FaceMint task created', ['task_id' => $taskId]);

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

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

    protected function createTask(string $mediaUrl, string $faceUrl): string
    {
        $response = Http::timeout($this->timeout)
            ->withHeaders(['x-api-key' => $this->apiKey])
            ->post($this->baseUrl . '/api/create-face-swap-task', [
                'type' => 'image',
                'media_url' => $mediaUrl,
                'swap_list' => [
                    ['to_face' => $faceUrl],
                ],
                'enhance' => 1,
                'nsfw_check' => 0,
            ]);

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

        $data = $response->json();

        if (($data['code'] ?? -1) !== 0) {
            throw new \Exception('FaceMint API error: ' . ($data['info'] ?? 'Unknown error'));
        }

        return $data['data']['taskId'];
    }

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

            $response = Http::timeout(30)
                ->withHeaders(['x-api-key' => $this->apiKey])
                ->get($this->baseUrl . '/api/get-face-swap-task-info', [
                    'task_id' => $taskId,
                ]);

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

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

            if ($status === 'completed' || $status === 'success') {
                $outputUrl = $data['data']['output_url']
                    ?? $data['data']['media_url']
                    ?? $data['data']['result_url']
                    ?? null;

                if (!$outputUrl) {
                    throw new \Exception('FaceMint task completed but no output URL returned');
                }

                return $outputUrl;
            }

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

        throw new \Exception('FaceMint 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 FaceMint result: HTTP ' . $response->status());
        }

        return $response->body();
    }
}
