<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Models\Anime;
use App\Models\Season;
use App\Models\ContentPermission;
use App\Models\Genre;
use App\Models\PermissionSetting;
use App\Services\JikanService;
use App\Support\ImageOptimizer;
use Illuminate\Http\Request;
use Illuminate\Support\Str;

class AnimeController extends Controller
{
    public function index(Request $request)
    {
        $query = Anime::with('genres')->latest();

        if ($request->search) {
            $query->where('title', 'like', '%' . $request->search . '%');
        }
        if ($request->status) {
            $query->where('status', $request->status);
        }
        if ($request->type) {
            $query->where('type', $request->type);
        }
        if ($request->no_episodes) {
            $query->whereDoesntHave('episodes');
        }

        $animes = $query->paginate(20)->withQueryString();
        $zeroEpisodeCount = Anime::whereDoesntHave('episodes')->count();
        return view('admin.animes.index', compact('animes', 'zeroEpisodeCount'));
    }

    public function destroyZeroEpisodes()
    {
        $animes = Anime::whereDoesntHave('episodes')->get();
        $count  = $animes->count();
        foreach ($animes as $anime) {
            $anime->delete();
        }
        return response()->json(['success' => true, 'count' => $count]);
    }

    public function create()
    {
        $genres = Genre::where('is_active', true)->get();
        $permissions = PermissionSetting::all();
        return view('admin.animes.create', compact('genres', 'permissions'));
    }

    public function store(Request $request)
    {
        $data = $request->validate([
            'title'        => 'required|string|max:255',
            'title_en'     => 'nullable|string|max:255',
            'title_jp'     => 'nullable|string|max:255',
            'description'  => 'nullable|string',
            'type'         => 'required|in:series,movie,ova,ona,special',
            'status'       => 'required|in:ongoing,completed,upcoming',
            'release_year' => 'nullable|integer|min:1900|max:2099',
            'studio'       => 'nullable|string|max:255',
            'rating'       => 'nullable|numeric|min:0|max:10',
            'mal_id'       => 'nullable|string|max:50',
            'trailer_url'  => 'nullable|url',
            'is_featured'  => 'boolean',
            'is_published' => 'boolean',
            'is_dubbed'    => 'boolean',
        ]);

        $data['slug'] = Str::slug($data['title']);
        $data['is_featured'] = $request->boolean('is_featured');
        $data['is_published'] = $request->boolean('is_published');
        $data['is_dubbed'] = $request->boolean('is_dubbed');

        // Auto-fetch MAL ID if not provided
        if (empty($data['mal_id'])) {
            try {
                $data['mal_id'] = (new JikanService())->searchMalId(
                    $data['title'],
                    $data['title_en'] ?? null,
                    $data['title_jp'] ?? null,
                    $data['type']     ?? null,
                );
            } catch (\Throwable) {}
        }

        if ($request->hasFile('cover_image')) {
            $data['cover_image'] = ImageOptimizer::store($request->file('cover_image'), 'covers', 'cover');
        }
        if ($request->hasFile('banner_image')) {
            $data['banner_image'] = ImageOptimizer::store($request->file('banner_image'), 'banners', 'banner');
        }

        $anime = Anime::create($data);

        if ($request->genres) {
            $anime->genres()->sync($request->genres);
        }

        // Auto-fill season MAL IDs if mal_id was found
        if ($anime->mal_id) {
            dispatch(function () use ($anime) {
                try {
                    $chain = (new JikanService())->fetchSeasonMalIds($anime->mal_id);
                    foreach ($anime->seasons()->orderBy('season_number')->get() as $i => $season) {
                        if (isset($chain[$i])) $season->update(['mal_id' => $chain[$i]]);
                    }
                } catch (\Throwable) {}
            })->afterResponse();
        }

        return redirect()->route('admin.animes.show', $anime)->with('success', 'Anime eklendi.');
    }

    public function show(Anime $anime)
    {
        $anime->load(['genres', 'seasons.episodes']);
        $permissions = PermissionSetting::all();
        $contentPerms = ContentPermission::where('content_type', 'anime')
            ->where('content_id', $anime->id)
            ->pluck('required_membership', 'permission_key');

        return view('admin.animes.show', compact('anime', 'permissions', 'contentPerms'));
    }

    public function edit(Anime $anime)
    {
        $genres = Genre::where('is_active', true)->get();
        $permissions = PermissionSetting::all();
        $contentPerms = ContentPermission::where('content_type', 'anime')
            ->where('content_id', $anime->id)
            ->pluck('required_membership', 'permission_key');

        return view('admin.animes.edit', compact('anime', 'genres', 'permissions', 'contentPerms'));
    }

    public function update(Request $request, Anime $anime)
    {
        $data = $request->validate([
            'title'        => 'required|string|max:255',
            'title_en'     => 'nullable|string|max:255',
            'title_jp'     => 'nullable|string|max:255',
            'description'  => 'nullable|string',
            'type'         => 'required|in:series,movie,ova,ona,special',
            'status'       => 'required|in:ongoing,completed,upcoming',
            'release_year' => 'nullable|integer|min:1900|max:2099',
            'studio'       => 'nullable|string|max:255',
            'rating'       => 'nullable|numeric|min:0|max:10',
            'mal_id'       => 'nullable|string|max:50',
            'trailer_url'  => 'nullable|url',
            'is_featured'  => 'boolean',
            'is_published' => 'boolean',
            'is_dubbed'    => 'boolean',
        ]);

        $data['is_featured'] = $request->boolean('is_featured');
        $data['is_published'] = $request->boolean('is_published');
        $data['is_dubbed'] = $request->boolean('is_dubbed');

        // Auto-fetch MAL ID if not provided and anime doesn't already have one
        if (empty($data['mal_id']) && empty($anime->mal_id)) {
            try {
                $data['mal_id'] = (new JikanService())->searchMalId(
                    $data['title'],
                    $data['title_en'] ?? null,
                    $data['title_jp'] ?? null,
                );
            } catch (\Throwable) {}
        }

        if ($request->hasFile('cover_image')) {
            ImageOptimizer::delete($anime->cover_image);
            $data['cover_image'] = ImageOptimizer::store($request->file('cover_image'), 'covers', 'cover');
        }
        if ($request->hasFile('banner_image')) {
            ImageOptimizer::delete($anime->banner_image);
            $data['banner_image'] = ImageOptimizer::store($request->file('banner_image'), 'banners', 'banner');
        }

        $anime->update($data);

        if ($request->has('genres')) {
            $anime->genres()->sync($request->genres ?? []);
        }

        // MAL ID değiştiyse: AniSkip cache'lerini temizle + sezon MAL ID'lerini doldur
        if ($anime->mal_id) {
            dispatch(function () use ($anime) {
                try {
                    // AniSkip null cache'lerini temizle (tüm bölümler için)
                    foreach ($anime->seasons as $s) {
                        if ($s->mal_id) {
                            foreach ($anime->episodes()->where('season_id', $s->id)->pluck('episode_number') as $epNum) {
                                \Illuminate\Support\Facades\Cache::forget("aniskip_{$s->mal_id}_{$epNum}");
                            }
                        }
                    }
                    // S1 için doğrudan anime.mal_id kullan
                    $s1 = $anime->seasons()->where('season_number', 1)->first();
                    if ($s1 && !$s1->mal_id) {
                        $s1->update(['mal_id' => $anime->mal_id]);
                        foreach ($anime->episodes()->where('season_id', $s1->id)->pluck('episode_number') as $epNum) {
                            \Illuminate\Support\Facades\Cache::forget("aniskip_{$anime->mal_id}_{$epNum}");
                        }
                    }
                    // S2+ için Jikan chain
                    $chain = (new JikanService())->fetchSeasonMalIds($anime->mal_id);
                    \Illuminate\Support\Facades\Cache::put("jikan_chain_{$anime->mal_id}", $chain, 60 * 60 * 24 * 7);
                    foreach ($anime->seasons()->orderBy('season_number')->get() as $i => $season) {
                        if (!$season->mal_id && isset($chain[$i])) {
                            $season->update(['mal_id' => $chain[$i]]);
                        }
                    }
                } catch (\Throwable) {}
            })->afterResponse();
        }

        return redirect()->route('admin.animes.show', $anime)->with('success', 'Anime güncellendi.');
    }

    public function destroy(Anime $anime)
    {
        // CDN klasörü için örnek bir video_url al (anime_XXXXX/ path'ini çıkarmak için)
        $sampleVideoUrl = $anime->episodes()->whereNotNull('video_url')->value('video_url');

        $anime->delete();

        // CDN'den tüm anime klasörünü arka planda sil (anime_XXXXX/season_X/...)
        dispatch(function () use ($sampleVideoUrl) {
            \App\Services\BunnyCdnStorage::deleteAnimeFolder($sampleVideoUrl);
        })->afterResponse();

        return redirect()->route('admin.animes.index')->with('success', 'Anime silindi.');
    }

    public function updatePermissions(Request $request, Anime $anime)
    {
        $permissions = $request->permissions ?? [];

        // Mevcut override'ları sil
        ContentPermission::where('content_type', 'anime')
            ->where('content_id', $anime->id)
            ->delete();

        // Yeni override'ları kaydet
        foreach ($permissions as $key => $value) {
            if (in_array($value, ['free', 'premium'])) {
                ContentPermission::create([
                    'content_type'        => 'anime',
                    'content_id'          => $anime->id,
                    'permission_key'      => $key,
                    'required_membership' => $value,
                ]);
            }
        }

        return back()->with('success', 'İzinler güncellendi.');
    }

    /**
     * POST admin/animes/{anime}/fetch-mal-seasons
     * Walks the Jikan sequel chain and fills seasons.mal_id automatically.
     */
    public function fetchMalSeasons(Request $request, Anime $anime)
    {
        // Formdan gelen mal_id varsa önce güncelle
        if ($request->filled('mal_id')) {
            $anime->update(['mal_id' => $request->input('mal_id')]);
        }

        if (!$anime->mal_id) {
            return response()->json(['error' => 'MAL ID girilmemiş. MyAnimeList.net\'ten anime sayfasını açıp URL\'deki numarayı gir.'], 422);
        }

        $jikan  = new JikanService();
        $chain  = $jikan->fetchSeasonMalIds($anime->mal_id);

        if (empty($chain)) {
            return response()->json(['error' => 'Jikan API\'den veri alınamadı.'], 502);
        }

        $seasons = Season::where('anime_id', $anime->id)
            ->orderBy('season_number')
            ->get();

        $updated = [];
        foreach ($seasons as $index => $season) {
            $malId = $chain[$index] ?? null;
            if ($malId) {
                $season->update(['mal_id' => $malId]);
                $updated[] = [
                    'season' => $season->season_number,
                    'mal_id' => $malId,
                ];
            }
        }

        // If anime has more seasons than chain entries, remaining seasons stay null
        return response()->json([
            'success' => true,
            'chain'   => $chain,
            'updated' => $updated,
            'message' => count($updated) . ' sezon güncellendi.',
        ]);
    }

    /**
     * POST admin/animes/{anime}/fetch-mal
     * Tek bir anime için MAL ID arar ve kaydeder.
     */
    public function fetchMalSingle(Anime $anime)
    {
        try {
            $malId = (new JikanService())->searchMalId(
                $anime->title, $anime->title_en, $anime->title_jp, $anime->type
            );
            if ($malId) {
                $anime->update(['mal_id' => $malId]);
                $s1 = $anime->seasons()->where('season_number', 1)->first();
                if ($s1 && !$s1->mal_id) $s1->update(['mal_id' => $malId]);
                return response()->json(['found' => true, 'mal_id' => $malId]);
            }
            return response()->json(['found' => false]);
        } catch (\Throwable $e) {
            return response()->json(['found' => false, 'error' => $e->getMessage()], 500);
        }
    }

    public function bulkDestroy(Request $request)
    {
        if ($request->boolean('all')) {
            $query = Anime::query();
            $f = $request->input('filters', []);
            if (!empty($f['search'])) $query->where('title', 'like', '%'.$f['search'].'%');
            if (!empty($f['status'])) $query->where('status', $f['status']);
            if (!empty($f['type']))   $query->where('type', $f['type']);
            $animes = $query->get();
        } else {
            $request->validate(['ids' => 'required|array', 'ids.*' => 'integer']);
            $animes = Anime::whereIn('id', $request->ids)->get();
        }

        $sampleUrls = [];
        foreach ($animes as $anime) {
            $url = $anime->episodes()->whereNotNull('video_url')->value('video_url');
            if ($url) $sampleUrls[] = $url;
            $anime->delete();
        }

        dispatch(function () use ($sampleUrls) {
            foreach ($sampleUrls as $url) {
                \App\Services\BunnyCdnStorage::deleteAnimeFolder($url);
            }
        })->afterResponse();

        return response()->json(['success' => true, 'deleted' => count($animes)]);
    }

    /**
     * POST admin/animes/bulk-find-mal
     * MAL ID'si olmayan animeleri Jikan title search ile toplu doldurur.
     * Her seferinde 1 anime işler (AJAX loop), Jikan rate limit aşılmaz.
     */
    public function bulkFindMal(Request $request)
    {
        $skipIds = $request->input('skip_ids', []);

        $anime = Anime::where(fn($q) => $q->whereNull('mal_id')->orWhere('mal_id', ''))
            ->when($skipIds, fn($q) => $q->whereNotIn('id', $skipIds))
            ->orderBy('id')
            ->first();

        if (!$anime) {
            return response()->json(['done' => true, 'message' => 'Tüm animelerin MAL ID\'si dolu!']);
        }

        $jikan = new JikanService();
        $malId = $jikan->searchMalId($anime->title, $anime->title_en, $anime->title_jp, $anime->type);

        if ($malId) {
            $anime->update(['mal_id' => $malId]);

            // S1 için season.mal_id de doldur
            $s1 = $anime->seasons()->where('season_number', 1)->first();
            if ($s1 && !$s1->mal_id) $s1->update(['mal_id' => $malId]);

            return response()->json([
                'done'    => false,
                'found'   => true,
                'anime'   => $anime->title,
                'mal_id'  => $malId,
                'remaining' => Anime::whereNull('mal_id')->orWhere('mal_id', '')->count(),
            ]);
        }

        // Bulunamadı — bir sonrakine geç (geçici olarak dummy değer koy, sonra temizle)
        return response()->json([
            'done'    => false,
            'found'   => false,
            'anime'   => $anime->title,
            'mal_id'  => null,
            'remaining' => Anime::whereNull('mal_id')->orWhere('mal_id', '')->count() - 1,
            'skipped_id' => $anime->id,
        ]);
    }
}
