<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Models\Anime;
use App\Models\ContentPermission;
use App\Models\Episode;
use App\Models\PermissionSetting;
use App\Models\Season;
use App\Models\VideoSource;
use App\Support\ImageOptimizer;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Http;

class EpisodeController extends Controller
{
    public function index(Request $request)
    {
        $query = Episode::with(['anime', 'season'])->latest();

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

        $episodes = $query->paginate(30)->withQueryString();
        $animes = Anime::orderBy('title')->get();

        return view('admin.episodes.index', compact('episodes', 'animes'));
    }

    public function create(Request $request)
    {
        $animes = Anime::orderBy('title')->get();
        $seasons = [];
        $selectedAnime = null;

        if ($request->anime_id) {
            $selectedAnime = Anime::find($request->anime_id);
            $seasons = Season::where('anime_id', $request->anime_id)->get();
        }

        $permissions = PermissionSetting::all();
        return view('admin.episodes.create', compact('animes', 'seasons', 'selectedAnime', 'permissions'));
    }

    public function store(Request $request)
    {
        $data = $request->validate([
            'anime_id'       => 'required|exists:animes,id',
            'season_id'      => 'required|exists:seasons,id',
            'episode_number' => 'required|integer|min:1',
            'title'          => 'nullable|string|max:255',
            'description'    => 'nullable|string',
            'duration'       => 'nullable|integer',
            'source_url'     => 'nullable|string',
            'video_url'      => 'nullable|string',
            'm3u8_url'       => 'nullable|string',
            'source'         => 'required|in:bunnycdn,external,direct',
            'is_published'   => 'boolean',
        ]);

        $data['status'] = $data['is_published'] ? 'published' : 'pending';
        $data['is_published'] = $request->boolean('is_published');

        if ($request->hasFile('thumbnail')) {
            $data['thumbnail'] = ImageOptimizer::store($request->file('thumbnail'), 'thumbnails', 'thumbnail');
        }

        $episode = Episode::create($data);

        // İzin override'ları
        $this->savePermissions($episode, $request->permissions ?? []);

        // Takipçilere bildirim gönder
        if ($episode->is_published) {
            $this->notifyFollowers($episode);
        }

        return redirect()->route('admin.episodes.index', ['anime_id' => $episode->anime_id])
            ->with('success', 'Bölüm eklendi.');
    }

    public function show(Episode $episode)
    {
        return redirect()->route('admin.episodes.edit', $episode);
    }

    public function edit(Episode $episode)
    {
        $animes = Anime::orderBy('title')->get();
        $seasons = Season::where('anime_id', $episode->anime_id)->get();
        $permissions = PermissionSetting::all();
        $contentPerms = ContentPermission::where('content_type', 'episode')
            ->where('content_id', $episode->id)
            ->pluck('required_membership', 'permission_key');

        return view('admin.episodes.edit', compact('episode', 'animes', 'seasons', 'permissions', 'contentPerms'));
    }

    public function update(Request $request, Episode $episode)
    {
        $data = $request->validate([
            'anime_id'       => 'required|exists:animes,id',
            'season_id'      => 'required|exists:seasons,id',
            'episode_number' => 'required|integer|min:1',
            'title'          => 'nullable|string|max:255',
            'description'    => 'nullable|string',
            'duration'       => 'nullable|integer',
            'intro_start'    => 'nullable|integer|min:0',
            'intro_end'      => 'nullable|integer|min:0',
            'source_url'     => 'nullable|string',
            'video_url'      => 'nullable|string',
            'm3u8_url'       => 'nullable|string',
            'source'         => 'required|in:bunnycdn,external,direct',
            'is_published'   => 'boolean',
        ]);

        $wasPublished = $episode->is_published;

        $data['is_published'] = $request->boolean('is_published');
        $data['status'] = $data['is_published'] ? 'published' : 'pending';

        if ($request->hasFile('thumbnail')) {
            $data['thumbnail'] = ImageOptimizer::store($request->file('thumbnail'), 'thumbnails', 'thumbnail');
        }

        $episode->update($data);
        $this->savePermissions($episode, $request->permissions ?? []);

        // Sadece yeni yayınlandıysa bildirim gönder (zaten yayındaysa tekrar gönderme)
        if (!$wasPublished && $episode->is_published) {
            $this->notifyFollowers($episode);
        }

        return redirect()->route('admin.episodes.edit', $episode)->with('success', 'Bölüm güncellendi.');
    }

    public function destroy(Episode $episode)
    {
        $animeId   = $episode->anime_id;
        $videoUrl  = $episode->video_url;
        $subUrls   = $episode->subtitles()->pluck('url')->all();

        $episode->delete();

        // CDN'den dosyaları arka planda sil
        dispatch(function () use ($videoUrl, $subUrls) {
            \App\Services\BunnyCdnStorage::deleteFile($videoUrl);
            foreach ($subUrls as $url) {
                \App\Services\BunnyCdnStorage::deleteFile($url);
            }
        })->afterResponse();

        return redirect()->route('admin.episodes.index', ['anime_id' => $animeId])
            ->with('success', 'Bölüm silindi.');
    }

    private function notifyFollowers(Episode $episode): void
    {
        $anime  = Anime::find($episode->anime_id);
        $season = Season::find($episode->season_id);

        if (!$anime) return;

        $followers = \App\Models\AnimeFollow::where('anime_id', $episode->anime_id)
            ->join('users', 'users.id', '=', 'anime_follows.user_id')
            ->select('users.id as user_id', 'users.fcm_token')
            ->get();

        if ($followers->isEmpty()) return;

        $seasonNum = $season?->season_number ?? 1;
        $notifData = json_encode([
            'anime_id'       => $anime->id,
            'anime_title'    => $anime->title,
            'anime_slug'     => $anime->slug,
            'episode_number' => $episode->episode_number,
            'season_number'  => $seasonNum,
            'episode_title'  => $episode->title,
        ]);

        $rows = [];
        $now  = now();
        foreach ($followers as $follower) {
            $rows[] = [
                'user_id'    => $follower->user_id,
                'type'       => 'episode',
                'data'       => $notifData,
                'created_at' => $now,
            ];
        }

        \App\Models\UserNotification::insert($rows);

        // FCM Push
        $fcmTokens = $followers->pluck('fcm_token')->filter()->values()->toArray();
        if (!empty($fcmTokens)) {
            $title = $anime->title . ' — Yeni Bölüm!';
            $body  = "Sezon {$seasonNum}, {$episode->episode_number}. Bölüm"
                   . ($episode->title ? ' — ' . $episode->title : '') . ' eklendi.';
            $fcm = new \App\Services\FcmService();
            $fcm->sendToTokens($fcmTokens, $title, $body, [
                'type'           => 'episode',
                'anime_slug'     => $anime->slug,
                'season_number'  => (string)$seasonNum,
                'episode_number' => (string)$episode->episode_number,
            ]);
        }
    }

    private function savePermissions(Episode $episode, array $permissions): void
    {
        ContentPermission::where('content_type', 'episode')
            ->where('content_id', $episode->id)
            ->delete();

        foreach ($permissions as $key => $value) {
            if (in_array($value, ['free', 'premium'])) {
                ContentPermission::create([
                    'content_type'        => 'episode',
                    'content_id'          => $episode->id,
                    'permission_key'      => $key,
                    'required_membership' => $value,
                ]);
            }
        }
    }

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

        $videoUrls = [];
        $subUrls   = [];
        foreach ($episodes as $ep) {
            if ($ep->video_url) $videoUrls[] = $ep->video_url;
            foreach ($ep->subtitles()->pluck('url') as $u) $subUrls[] = $u;
            $ep->delete();
        }

        dispatch(function () use ($videoUrls, $subUrls) {
            foreach ($videoUrls as $url) \App\Services\BunnyCdnStorage::deleteFile($url);
            foreach ($subUrls   as $url) \App\Services\BunnyCdnStorage::deleteFile($url);
        })->afterResponse();

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

    public function bulkIntro(Request $request)
    {
        $request->validate([
            'anime_id'    => 'required|exists:animes,id',
            'season'      => 'required|integer|min:0',
            'intro_start' => 'required|integer|min:0',
            'intro_end'   => 'required|integer|min:1',
        ]);

        $query = Episode::where('anime_id', $request->anime_id);

        if ((int)$request->season > 0) {
            $season = \App\Models\Season::where('anime_id', $request->anime_id)
                ->where('season_number', $request->season)->first();
            if ($season) $query->where('season_id', $season->id);
        }

        $updated = $query->update([
            'intro_start' => $request->intro_start,
            'intro_end'   => $request->intro_end,
        ]);

        return response()->json(['ok' => true, 'updated' => $updated]);
    }

    // POST /admin/episodes/{episode}/scan-hevc
    // Admin panelinden bölümün HLS kaynaklarını sunucu tarafında tarar, HEVC olanları işaretler
    public function scanHevc(Episode $episode)
    {
        $sources = VideoSource::where('episode_id', $episode->id)
            ->where('type', 'hls')
            ->get();

        $results = [];
        foreach ($sources as $src) {
            $isHevc = $this->probeM3u8ForHevc($src->url);
            $src->update(['is_hevc' => $isHevc, 'hevc_checked_at' => now()]);
            $results[] = [
                'id'      => $src->id,
                'label'   => $src->label,
                'quality' => $src->quality,
                'is_hevc' => $isHevc,
            ];
        }

        return response()->json(['ok' => true, 'results' => $results]);
    }

    private function probeM3u8ForHevc(string $url): bool
    {
        try {
            $response = Http::timeout(8)->withHeaders(['User-Agent' => 'Mozilla/5.0'])->get($url);
            if (!$response->ok()) return false;
            $text = $response->body();

            preg_match_all('/#EXT-X-STREAM-INF:([^\n]+)/i', $text, $matches);
            if (empty($matches[1])) return false;

            $isHevcCodec = fn($attrs) => (bool) preg_match('/CODECS="[^"]*(?:hev1|hvc1|dvh1)[^"]*"/i', $attrs);

            foreach ($matches[1] as $attrs) {
                // CODECS tag yoksa bilinmiyor — H.264 uyumlu say, HEVC değil
                if (!str_contains(strtoupper($attrs), 'CODECS=')) return false;
                if (!$isHevcCodec($attrs)) return false;
            }

            return true; // tüm stream'ler HEVC
        } catch (\Throwable) {
            return false;
        }
    }
}
