<?php

namespace App\Services;

use App\Models\Anime;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;

class AniListService
{
    const ENDPOINT = 'https://graphql.anilist.co';
    const CACHE_TTL = 60 * 60 * 24 * 7;

    // Maksimum genişlik (px) — oran korunur, WebP'ye çevrilir
    const COVER_MAX_W  = 600;
    const BANNER_MAX_W = 1920;
    const WEBP_QUALITY = 90;

    private function query(array $variables, string $gql): ?array
    {
        try {
            $res = Http::timeout(10)
                ->withHeaders(['Content-Type' => 'application/json', 'Accept' => 'application/json'])
                ->post(self::ENDPOINT, ['query' => $gql, 'variables' => $variables]);

            if (!$res->ok()) return null;
            if (!empty($res->json('errors'))) return null;

            return $res->json('data.Media');
        } catch (\Throwable $e) {
            Log::debug('AniList query failed', ['err' => $e->getMessage()]);
            return null;
        }
    }

    public function fetchByMalId(int $malId): ?array
    {
        return Cache::remember("anilist_mal_{$malId}", self::CACHE_TTL, function () use ($malId) {
            return $this->query(
                ['malId' => $malId],
                'query($malId:Int){Media(idMal:$malId,type:ANIME){coverImage{extraLarge}bannerImage}}'
            );
        });
    }

    public function fetchByTitle(string $title): ?array
    {
        return Cache::remember('anilist_title_' . md5($title), self::CACHE_TTL, function () use ($title) {
            return $this->query(
                ['search' => $title],
                'query($search:String){Media(search:$search,type:ANIME){coverImage{extraLarge}bannerImage}}'
            );
        });
    }

    /**
     * Resmi indir, yeniden boyutlandır, WebP olarak storage'a kaydet.
     * Başarılıysa storage-relative yolu döner (örn. anime/covers/123.webp).
     */
    /**
     * Resmi indir, max genişliğe orantılı küçült (asla büyütme), WebP kaydet.
     * Orijinalden küçükse olduğu gibi bırakır.
     */
    private function downloadAndResize(string $url, string $storagePath, int $maxW): ?string
    {
        try {
            $response = Http::timeout(20)->withHeaders([
                'User-Agent' => 'Mozilla/5.0',
                'Referer'    => 'https://anilist.co/',
            ])->get($url);

            if (!$response->ok()) return null;

            $raw = $response->body();
            $src = @imagecreatefromstring($raw);
            if (!$src) return null;

            $srcW = imagesx($src);
            $srcH = imagesy($src);

            if ($srcW > $maxW) {
                // Orantılı küçült
                $newW = $maxW;
                $newH = (int) round($srcH * ($maxW / $srcW));
                $dst  = imagecreatetruecolor($newW, $newH);
                imagecopyresampled($dst, $src, 0, 0, 0, 0, $newW, $newH, $srcW, $srcH);
                imagedestroy($src);
            } else {
                // Zaten küçük — olduğu gibi kullan
                $dst = $src;
            }

            $absPath = storage_path('app/public/' . $storagePath);
            @mkdir(dirname($absPath), 0755, true);

            $ok = imagewebp($dst, $absPath, self::WEBP_QUALITY);
            imagedestroy($dst);

            return $ok ? $storagePath : null;
        } catch (\Throwable $e) {
            Log::debug('AniList image download failed', ['url' => $url, 'err' => $e->getMessage()]);
            return null;
        }
    }

    /**
     * Anime'nin boş kapak/banner alanlarını AniList'ten doldur.
     * Resimleri indirir, boyutlandırır, WebP olarak storage'a kaydeder.
     * Dolu alanların üzerine yazmaz.
     */
    public function fillImages(Anime $anime): bool
    {
        $needCover  = empty($anime->cover_image);
        $needBanner = empty($anime->banner_image);
        if (!$needCover && !$needBanner) return false;

        $data = null;
        if ($anime->mal_id) {
            $data = $this->fetchByMalId((int) $anime->mal_id);
        }
        if (!$data) {
            $data = $this->fetchByTitle($anime->title);
        }
        if (!$data) return false;

        $updates = [];

        if ($needCover && !empty($data['coverImage']['extraLarge'])) {
            $path = $this->downloadAndResize(
                $data['coverImage']['extraLarge'],
                "anime/covers/{$anime->id}.webp",
                self::COVER_MAX_W
            );
            if ($path) $updates['cover_image'] = $path;
        }

        if ($needBanner && !empty($data['bannerImage'])) {
            $path = $this->downloadAndResize(
                $data['bannerImage'],
                "anime/banners/{$anime->id}.webp",
                self::BANNER_MAX_W
            );
            if ($path) $updates['banner_image'] = $path;
        }

        if (empty($updates)) return false;

        $anime->update($updates);
        return true;
    }
}
