<?php

namespace App\Http\Controllers\Frontend;

use App\Http\Controllers\Controller;
use App\Models\Anime;
use App\Models\Episode;
use App\Models\EpisodePrediction;
use App\Models\EpisodeTimestampComment;
use App\Models\FirstWatchSession;
use App\Models\PredictionVote;
use App\Models\SpoilerBox;
use App\Models\SpoilerBoxLike;
use App\Models\TimeCapsule;
use App\Models\User;
use App\Models\UserFollow;
use App\Models\WatchParty;
use App\Models\WatchPartyMember;
use App\Services\DeepSeekService;
use App\Support\MediaUrl;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;

class SocialController extends Controller
{
    // ─────────────────────────────────────────────────────────
    // Kullanıcı takip
    // ─────────────────────────────────────────────────────────

    public function followToggle(User $user)
    {
        $me = Auth::user();

        if ($me->id === $user->id) {
            return response()->json(['error' => 'Kendinizi takip edemezsiniz.'], 422);
        }

        $existing = UserFollow::where('follower_id', $me->id)
            ->where('following_id', $user->id)
            ->first();

        if ($existing) {
            $existing->delete();
            $following = false;
        } else {
            UserFollow::create(['follower_id' => $me->id, 'following_id' => $user->id]);
            $following = true;
        }

        return response()->json([
            'following'        => $following,
            'followers_count'  => UserFollow::where('following_id', $user->id)->count(),
        ]);
    }

    public function card(User $user)
    {
        $me = Auth::user();
        $isFollowing = $me
            ? UserFollow::where('follower_id', $me->id)->where('following_id', $user->id)->exists()
            : false;

        return response()->json([
            'id'           => $user->id,
            'name'         => $user->name,
            'username'     => $user->username,
            'avatar'       => $user->avatar ? MediaUrl::fromStoragePath($user->avatar) : null,
            'followers'    => UserFollow::where('following_id', $user->id)->count(),
            'following'    => UserFollow::where('follower_id', $user->id)->count(),
            'is_following' => $isFollowing,
            'profile_url'  => route('user.profile', $user),
            'follow_url'   => ($me && $me->id !== $user->id) ? route('user.follow', $user) : null,
            'msg_url'      => ($me && $me->id !== $user->id) ? route('messages.start', $user) : null,
            'is_me'        => $me && $me->id === $user->id,
        ]);
    }

    public function compatibility(User $user)
    {
        $me = Auth::user();
        if (!$me) return response()->json(['score' => 0]);

        return response()->json([
            'score' => $me->compatibilityWith($user),
        ]);
    }

    // ─────────────────────────────────────────────────────────
    // NicoNico — Timestamp Yorumları
    // ─────────────────────────────────────────────────────────

    public function timestampComments(Episode $episode)
    {
        $comments = EpisodeTimestampComment::with('user:id,name,username')
            ->where('episode_id', $episode->id)
            ->where('is_hidden', false)
            ->orderBy('timestamp_sec')
            ->get()
            ->map(fn($c) => [
                'id'            => $c->id,
                'user_id'       => $c->user_id,
                'timestamp_sec' => $c->timestamp_sec,
                'body'          => $c->body,
                'color'         => $c->color,
                'username'      => $c->user?->username ?? 'misafir',
                'created_at'    => $c->created_at,
            ]);

        return response()->json(['comments' => $comments]);
    }

    public function timestampCommentStore(Request $request, Episode $episode)
    {
        $data = $request->validate([
            'timestamp_sec' => 'required|integer|min:0|max:86400',
            'body'          => 'required|string|max:100',
            'color'         => 'nullable|regex:/^#[0-9a-fA-F]{6}$/',
        ]);

        $me = Auth::user();

        // Flood koruması: aynı kullanıcı 5 saniye içinde 2+ yorum atmasın
        $recent = EpisodeTimestampComment::where('user_id', $me->id)
            ->where('episode_id', $episode->id)
            ->where('created_at', '>=', now()->subSeconds(5))
            ->count();

        if ($recent >= 2) {
            return response()->json(['error' => 'Çok hızlı yorum yapıyorsunuz.'], 429);
        }

        $comment = EpisodeTimestampComment::create([
            'episode_id'    => $episode->id,
            'user_id'       => $me->id,
            'timestamp_sec' => $data['timestamp_sec'],
            'body'          => $data['body'],
            'color'         => $data['color'] ?? '#ffffff',
        ]);

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

    // ─────────────────────────────────────────────────────────
    // Tahmin Oyunu
    // ─────────────────────────────────────────────────────────

    public function predictions(Episode $episode)
    {
        $me = Auth::id();

        $predictions = EpisodePrediction::with('user:id,name,username')
            ->where('episode_id', $episode->id)
            ->orderByDesc('vote_count')
            ->get()
            ->map(fn($p) => [
                'id'         => $p->id,
                'body'       => $p->body,
                'is_correct' => $p->is_correct,
                'vote_count' => $p->vote_count,
                'username'   => $p->user?->username,
                'is_mine'    => $me && $p->user_id === $me,
                'voted'      => $me
                    ? PredictionVote::where('prediction_id', $p->id)->where('user_id', $me)->exists()
                    : false,
                'created_at' => $p->created_at->diffForHumans(),
            ]);

        $myPrediction = $me
            ? EpisodePrediction::where('episode_id', $episode->id)->where('user_id', $me)->first()?->id
            : null;

        return response()->json([
            'predictions'   => $predictions,
            'my_prediction' => $myPrediction,
        ]);
    }

    public function predictionStore(Request $request, Episode $episode)
    {
        $me = Auth::user();

        $data = $request->validate([
            'body' => 'required|string|min:5|max:280',
        ]);

        $existing = EpisodePrediction::where('episode_id', $episode->id)
            ->where('user_id', $me->id)
            ->first();

        if ($existing) {
            return response()->json(['error' => 'Bu bölüm için zaten bir tahmininiz var.'], 422);
        }

        $prediction = EpisodePrediction::create([
            'episode_id' => $episode->id,
            'user_id'    => $me->id,
            'body'       => $data['body'],
        ]);

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

    public function predictionVote(Request $request, EpisodePrediction $prediction)
    {
        $me = Auth::user();

        $existing = PredictionVote::where('prediction_id', $prediction->id)
            ->where('user_id', $me->id)
            ->first();

        if ($existing) {
            $existing->delete();
            $prediction->decrement('vote_count');
            return response()->json(['voted' => false, 'vote_count' => $prediction->fresh()->vote_count]);
        }

        PredictionVote::create(['prediction_id' => $prediction->id, 'user_id' => $me->id]);
        $prediction->increment('vote_count');

        return response()->json(['voted' => true, 'vote_count' => $prediction->fresh()->vote_count]);
    }

    // ─────────────────────────────────────────────────────────
    // Watch Party
    // ─────────────────────────────────────────────────────────

    public function partyCreate(Request $request)
    {
        $me = Auth::user();

        $data = $request->validate([
            'episode_id' => 'required|exists:episodes,id',
            'is_private' => 'boolean',
            'password'   => 'nullable|string|max:30',
            'max_members'=> 'nullable|integer|min:2|max:20',
        ]);

        // Kullanıcının zaten aktif bir odası varsa sil
        WatchParty::where('host_user_id', $me->id)->delete();

        $party = WatchParty::create([
            'room_code'    => WatchParty::generateCode(),
            'host_user_id' => $me->id,
            'episode_id'   => $data['episode_id'],
            'is_private'   => $data['is_private'] ?? false,
            'password'     => isset($data['password']) ? Hash::make($data['password']) : null,
            'max_members'  => $data['max_members'] ?? 10,
        ]);

        WatchPartyMember::create([
            'party_id' => $party->id,
            'user_id'  => $me->id,
        ]);

        return response()->json([
            'ok'        => true,
            'room_code' => $party->room_code,
            'party_url' => route('watch.party', $party->room_code),
        ]);
    }

    public function partyJoin(Request $request, string $roomCode)
    {
        $party = WatchParty::where('room_code', $roomCode)->firstOrFail();
        $me    = Auth::user();

        // Şifre kontrolü
        if ($party->is_private && $party->password) {
            $pw = $request->input('password', '');
            if (!Hash::check($pw, $party->password)) {
                return response()->json(['error' => 'Yanlış şifre.'], 403);
            }
        }

        // Kapasite
        $activeCount = $party->activeMembers()->count();
        if ($activeCount >= $party->max_members) {
            return response()->json(['error' => 'Oda dolu.'], 403);
        }

        WatchPartyMember::updateOrCreate(
            ['party_id' => $party->id, 'user_id' => $me->id],
            ['last_ping' => now()]
        );

        return response()->json([
            'ok'          => true,
            'current_sec' => $party->current_sec,
            'is_playing'  => $party->is_playing,
            'host_id'     => $party->host_user_id,
            'members'     => $this->partyMemberList($party),
        ]);
    }

    public function partySync(Request $request, string $roomCode)
    {
        $party = WatchParty::where('room_code', $roomCode)->firstOrFail();
        $me    = Auth::user();

        // Sadece host senkron durumu güncelleyebilir
        if ($party->host_user_id === $me->id) {
            $data = $request->validate([
                'current_sec' => 'required|integer|min:0',
                'is_playing'  => 'required|boolean',
            ]);
            $party->update([
                'current_sec' => $data['current_sec'],
                'is_playing'  => $data['is_playing'],
            ]);
        }

        // Herkes ping atar
        WatchPartyMember::where('party_id', $party->id)
            ->where('user_id', $me->id)
            ->update(['last_ping' => now()]);

        return response()->json([
            'current_sec' => $party->fresh()->current_sec,
            'is_playing'  => $party->fresh()->is_playing,
            'members'     => $this->partyMemberList($party),
        ]);
    }

    public function partyLeave(string $roomCode)
    {
        $party = WatchParty::where('room_code', $roomCode)->firstOrFail();
        $me    = Auth::user();

        WatchPartyMember::where('party_id', $party->id)->where('user_id', $me->id)->delete();

        if ($party->host_user_id === $me->id) {
            $party->delete();
            return response()->json(['ok' => true, 'dissolved' => true]);
        }

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

    public function partyShow(string $roomCode)
    {
        $party = WatchParty::with(['episode.anime', 'host'])->where('room_code', $roomCode)->firstOrFail();
        return view('frontend.watch-party', compact('party'));
    }

    private function partyMemberList(WatchParty $party): array
    {
        return $party->activeMembers()->with('user:id,name,username')->get()
            ->map(fn($m) => [
                'id'       => $m->user_id,
                'name'     => $m->user?->name,
                'username' => $m->user?->username,
                'is_host'  => $m->user_id === $party->host_user_id,
            ])->toArray();
    }

    // ─────────────────────────────────────────────────────────
    // İlk Kez İzleyenler
    // ─────────────────────────────────────────────────────────

    public function firstWatchRegister(Request $request, Episode $episode)
    {
        $me        = Auth::user();
        $sessionId = $request->header('X-Session-ID') ?? session()->getId();

        FirstWatchSession::updateOrCreate(
            [
                'episode_id' => $episode->id,
                'user_id'    => $me?->id,
                'session_id' => $me ? null : $sessionId,
            ],
            [
                'is_first_time' => (bool)$request->input('is_first_time', true),
                'last_seen'     => now(),
            ]
        );

        $count = FirstWatchSession::where('episode_id', $episode->id)
            ->where('is_first_time', true)
            ->where('last_seen', '>=', now()->subMinutes(10))
            ->count();

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

    public function firstWatchCount(Episode $episode)
    {
        $count = FirstWatchSession::where('episode_id', $episode->id)
            ->where('is_first_time', true)
            ->where('last_seen', '>=', now()->subMinutes(10))
            ->count();

        return response()->json(['count' => $count]);
    }

    // ─────────────────────────────────────────────────────────
    // Ruh Hali Motoru
    // ─────────────────────────────────────────────────────────

    private static array $moodGenres = [
        'sad'     => ['Drama', 'Romantizm'],
        'funny'   => ['Komedi', 'Slice of Life'],
        'hype'    => ['Aksiyon', 'Shounen', 'Spor'],
        'think'   => ['Bilim Kurgu', 'Gerilim', 'Supernatural'],
        'romance' => ['Romantizm', 'Shoujo'],
        'scary'   => ['Korku', 'Supernatural', 'Gerilim'],
    ];

    public function moodRecommend(Request $request)
    {
        $mood = $request->validate(['mood' => 'required|in:sad,funny,hype,think,romance,scary'])['mood'];
        $genres = self::$moodGenres[$mood] ?? [];

        $animes = Anime::whereHas('genres', fn($q) => $q->whereIn('name', $genres))
            ->where('is_published', true)
            ->inRandomOrder()
            ->limit(6)
            ->get(['id', 'title', 'cover_image', 'slug', 'rating']);

        return response()->json([
            'animes' => $animes->map(fn($a) => [
                'id'    => $a->id,
                'title' => $a->title,
                'cover' => $a->cover_image ? \App\Support\MediaUrl::fromStoragePath($a->cover_image) : null,
                'url'   => route('anime.show', $a->slug),
                'rating'=> $a->rating,
            ]),
        ]);
    }

    // ─────────────────────────────────────────────────────────
    // Zaman Kapsülü
    // ─────────────────────────────────────────────────────────

    public function capsuleStore(Request $request)
    {
        $me   = Auth::user();
        $data = $request->validate([
            'anime_id'  => 'required|exists:animes,id',
            'message'   => 'required|string|min:5|max:1000',
            'unlock_at' => 'required|date|after:' . now()->addDays(30)->toDateString(),
        ]);

        $data['user_id'] = $me->id;

        $capsule = TimeCapsule::create($data);

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

    public function capsuleIndex()
    {
        $capsules = TimeCapsule::with('anime:id,title,slug,cover_image')
            ->where('user_id', Auth::id())
            ->orderBy('unlock_at')
            ->get()
            ->map(fn($c) => [
                'id'         => $c->id,
                'anime'      => $c->anime?->title,
                'anime_url'  => $c->anime ? route('anime.show', $c->anime->slug) : null,
                'cover'      => $c->anime?->cover_image ? MediaUrl::fromStoragePath($c->anime->cover_image) : null,
                'unlock_at'  => $c->unlock_at->format('d.m.Y'),
                'unlocked'   => $c->isUnlocked(),
                'opened'     => $c->isOpened(),
                'message'    => $c->isOpened() || $c->isUnlocked() ? $c->message : null,
                'created_at' => $c->created_at->format('d.m.Y'),
            ]);

        return view('frontend.capsules', compact('capsules'));
    }

    public function capsuleOpen(TimeCapsule $capsule)
    {
        if ($capsule->user_id !== Auth::id()) {
            return response()->json(['error' => 'Yetkisiz.'], 403);
        }
        if (!$capsule->isUnlocked()) {
            return response()->json(['error' => 'Kapsül henüz açılamaz.'], 422);
        }

        $capsule->update(['opened_at' => now()]);

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

    // ─────────────────────────────────────────────────────────
    // Spoiler Kilitli Kutu
    // ─────────────────────────────────────────────────────────

    public function spoilerBoxes(Episode $episode)
    {
        $me    = Auth::id();
        $boxes = SpoilerBox::with('user:id,name,username')
            ->where('episode_id', $episode->id)
            ->orderByDesc('likes')
            ->orderByDesc('created_at')
            ->get()
            ->map(fn($b) => [
                'id'            => $b->id,
                'body'          => $b->body,
                'is_spoiler'    => $b->is_spoiler,
                'spoiler_score' => $b->spoiler_score,
                'likes'         => $b->likes,
                'username'      => $b->user?->username,
                'name'          => $b->user?->name,
                'is_mine'       => $me && $b->user_id === $me,
                'liked'         => $me ? SpoilerBoxLike::where('box_id', $b->id)->where('user_id', $me)->exists() : false,
                'created_at'    => $b->created_at->diffForHumans(),
            ]);

        return response()->json(['boxes' => $boxes]);
    }

    public function spoilerBoxStore(Request $request, Episode $episode)
    {
        $me   = Auth::user();
        $data = $request->validate([
            'body' => 'required|string|min:3|max:600',
        ]);

        // AI spoiler tespiti
        $isSpoiler   = false;
        $spoilerScore = 0;
        $ai = new DeepSeekService();
        if ($ai->isConfigured()) {
            $prompt = "Aşağıdaki metin bir anime bölümü hakkında yazılmış. Bu metin spoiler içeriyor mu? "
                . "Sadece JSON döndür: {\"is_spoiler\": true/false, \"score\": 0-100}\n\nMetin: " . $data['body'];
            try {
                $raw = $ai->checkSpoiler($data['body']);
                if ($raw) {
                    $isSpoiler    = $raw['is_spoiler'] ?? false;
                    $spoilerScore = $raw['score'] ?? 0;
                }
            } catch (\Throwable $e) {}
        }

        $box = SpoilerBox::create([
            'episode_id'    => $episode->id,
            'user_id'       => $me->id,
            'body'          => $data['body'],
            'is_spoiler'    => $isSpoiler,
            'spoiler_score' => $spoilerScore,
        ]);

        return response()->json([
            'ok'         => true,
            'id'         => $box->id,
            'is_spoiler' => $isSpoiler,
        ]);
    }

    public function spoilerBoxLike(SpoilerBox $box)
    {
        $me = Auth::id();

        $existing = SpoilerBoxLike::where('box_id', $box->id)->where('user_id', $me)->first();

        if ($existing) {
            $existing->delete();
            $box->decrement('likes');
            return response()->json(['liked' => false, 'likes' => $box->fresh()->likes]);
        }

        SpoilerBoxLike::create(['box_id' => $box->id, 'user_id' => $me, 'created_at' => now()]);
        $box->increment('likes');

        return response()->json(['liked' => true, 'likes' => $box->fresh()->likes]);
    }
}
