<?php

namespace App\Http\Controllers\Frontend;

use App\Http\Controllers\Controller;
use App\Models\Anime;
use App\Models\Episode;
use App\Models\Watchlist;
use App\Models\EpisodeVote;
use App\Models\AnimeRating;
use App\Models\AnimeRequest;
use App\Models\AnimeRequestVote;
use App\Models\ContinueWatching;
use App\Models\UserAchievement;
use App\Models\AnimeFollow;
use App\Models\UserNotification;
use App\Models\EpisodeNote;
use App\Services\AchievementService;
use Illuminate\Http\Request;

class UserFeatureController extends Controller
{
    // ── Watchlist ─────────────────────────────────────────────────────────────

    public function watchlistIndex()
    {
        $items = Watchlist::where('user_id', auth()->id())
            ->with(['anime.genres'])
            ->orderByDesc('created_at')
            ->get()
            ->groupBy('status');

        $continues = ContinueWatching::where('user_id', auth()->id())
            ->with(['anime', 'episode'])
            ->where('percent_complete', '<', 95)
            ->orderByDesc('updated_at')
            ->limit(20)
            ->get();

        $achievements = UserAchievement::where('user_id', auth()->id())
            ->with('achievement')
            ->orderByDesc('earned_at')
            ->get();

        return view('frontend.profile', compact('items', 'continues', 'achievements'));
    }

    public function watchlistToggle(Request $request, Anime $anime)
    {
        $this->requireAuth();

        $status = $request->input('status', 'plan');
        if (!array_key_exists($status, Watchlist::STATUSES)) {
            $status = 'plan';
        }

        $existing = Watchlist::where('user_id', auth()->id())
            ->where('anime_id', $anime->id)
            ->first();

        if ($existing) {
            if ($existing->status === $status) {
                $existing->delete();
                $inList = false;
                $newStatus = null;
            } else {
                $existing->update(['status' => $status]);
                $inList = true;
                $newStatus = $status;
            }
        } else {
            Watchlist::create([
                'user_id'    => auth()->id(),
                'anime_id'   => $anime->id,
                'status'     => $status,
                'created_at' => now(),
            ]);
            $inList = true;
            $newStatus = $status;
        }

        $newlyEarned = AchievementService::check(auth()->user());

        return response()->json([
            'in_list'      => $inList,
            'status'       => $newStatus,
            'status_label' => $newStatus ? (Watchlist::STATUSES[$newStatus] ?? '') : null,
            'achievements' => array_map(fn($a) => ['title' => $a->title, 'icon' => $a->icon, 'color' => $a->color], $newlyEarned),
        ]);
    }

    // ── Watchlist Export ─────────────────────────────────────────────────────

    public function watchlistExport(Request $request)
    {
        $user = auth()->user();

        if (!$user->hasPerk('watchlist_export')) {
            abort(403, 'Bu özellik için premium üyelik gerekiyor.');
        }

        $format = in_array($request->query('format'), ['csv', 'json']) ? $request->query('format') : 'json';

        $items = Watchlist::where('user_id', $user->id)
            ->with('anime:id,title,mal_score,genres')
            ->orderBy('status')
            ->orderByDesc('created_at')
            ->get()
            ->map(fn($w) => [
                'title'      => $w->anime->title ?? '',
                'status'     => $w->status,
                'added_at'   => $w->created_at?->toDateString(),
                'mal_score'  => $w->anime->mal_score ?? null,
            ]);

        if ($format === 'csv') {
            $csv = "title,status,added_at,mal_score\n";
            foreach ($items as $row) {
                $csv .= '"' . str_replace('"', '""', $row['title']) . '",'
                    . $row['status'] . ','
                    . $row['added_at'] . ','
                    . $row['mal_score'] . "\n";
            }
            return response($csv, 200, [
                'Content-Type'        => 'text/csv; charset=utf-8',
                'Content-Disposition' => 'attachment; filename="watchlist.csv"',
            ]);
        }

        return response()->json($items, 200, [
            'Content-Disposition' => 'attachment; filename="watchlist.json"',
        ]);
    }

    // ── Episode Vote ──────────────────────────────────────────────────────────

    public function episodeVote(Request $request, Episode $episode)
    {
        $this->requireAuth();

        $vote = $request->input('vote') == 1 ? 1 : -1;

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

        if ($existing) {
            if ($existing->vote === $vote) {
                $existing->delete(); // toggle off
            } else {
                $existing->update(['vote' => $vote]);
            }
        } else {
            EpisodeVote::create([
                'user_id'    => auth()->id(),
                'episode_id' => $episode->id,
                'vote'       => $vote,
                'created_at' => now(),
            ]);
        }

        $likes    = EpisodeVote::where('episode_id', $episode->id)->where('vote', 1)->count();
        $dislikes = EpisodeVote::where('episode_id', $episode->id)->where('vote', -1)->count();
        $myVote   = EpisodeVote::where('user_id', auth()->id())->where('episode_id', $episode->id)->value('vote');

        return response()->json([
            'likes'    => $likes,
            'dislikes' => $dislikes,
            'my_vote'  => $myVote,
        ]);
    }

    // ── Anime Rating ─────────────────────────────────────────────────────────

    public function animeRate(Request $request, Anime $anime)
    {
        $this->requireAuth();

        $rating = (int) $request->input('rating');
        if ($rating < 1 || $rating > 10) {
            return response()->json(['error' => 'Geçersiz puan'], 422);
        }

        AnimeRating::updateOrCreate(
            ['user_id' => auth()->id(), 'anime_id' => $anime->id],
            ['rating' => $rating]
        );

        $avg   = AnimeRating::where('anime_id', $anime->id)->avg('rating');
        $count = AnimeRating::where('anime_id', $anime->id)->count();

        // Anime tablosunu güncelle (ağırlıklı ortalama)
        $anime->update(['rating' => round($avg, 1)]);

        $newlyEarned = AchievementService::check(auth()->user());

        return response()->json([
            'avg'          => round($avg, 1),
            'count'        => $count,
            'my_rating'    => $rating,
            'achievements' => array_map(fn($a) => ['title' => $a->title, 'icon' => $a->icon, 'color' => $a->color], $newlyEarned),
        ]);
    }

    // ── Continue Watching (güncelleme) ───────────────────────────────────────

    public function continueWatchingUpdate(Request $request)
    {
        if (!auth()->check()) {
            return response()->json(['ok' => false]);
        }

        $data = $request->validate([
            'anime_id'       => 'required|integer',
            'episode_id'     => 'required|integer',
            'season_number'  => 'required|integer',
            'episode_number' => 'required|integer',
            'seconds'        => 'required|integer|min:0',
            'total'          => 'nullable|integer|min:0',
            'percent'        => 'nullable|integer|min:0|max:100',
        ]);

        $userId = auth()->id();

        ContinueWatching::updateOrCreate(
            ['user_id' => $userId, 'anime_id' => $data['anime_id']],
            [
                'episode_id'      => $data['episode_id'],
                'season_number'   => $data['season_number'],
                'episode_number'  => $data['episode_number'],
                'seconds_watched' => $data['seconds'],
                'total_seconds'   => $data['total'] ?? 0,
                'percent_complete'=> $data['percent'] ?? 0,
                'updated_at'      => now(),
            ]
        );

        // stream_history perki yoksa en eski kayıtları silerek 30 limiti uygula
        if (!auth()->user()->hasPerk('stream_history')) {
            $count = ContinueWatching::where('user_id', $userId)->count();
            if ($count > 30) {
                $idsToDelete = ContinueWatching::where('user_id', $userId)
                    ->orderBy('updated_at')
                    ->limit($count - 30)
                    ->pluck('id');
                ContinueWatching::whereIn('id', $idsToDelete)->delete();
            }
        }

        // Başarım kontrolü (her 5 bölümde bir — performans için)
        if ($data['seconds'] % 300 < 35) {
            AchievementService::check(auth()->user());
        }

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

    // ── Anime İsteği ─────────────────────────────────────────────────────────

    public function requestIndex()
    {
        $requests = AnimeRequest::withCount('votes')
            ->whereIn('status', ['pending', 'approved', 'added'])
            ->orderByDesc('vote_count')
            ->orderByDesc('created_at')
            ->paginate(20);

        $myRequests = auth()->check()
            ? AnimeRequest::where('user_id', auth()->id())->orderByDesc('id')->limit(5)->get()
            : collect();

        $votedIds = [];
        if (auth()->check()) {
            $votedIds = AnimeRequestVote::where('user_id', auth()->id())
                ->pluck('anime_request_id')->toArray();
        }

        return view('frontend.anime-request', compact('requests', 'myRequests', 'votedIds'));
    }

    public function requestStore(Request $request)
    {
        $this->requireAuth();

        $data = $request->validate([
            'title'          => 'required|string|max:200',
            'original_title' => 'nullable|string|max:200',
            'note'           => 'nullable|string|max:1000',
        ]);

        // Benzer istek var mı?
        $existing = AnimeRequest::whereRaw('LOWER(title) = ?', [strtolower($data['title'])])->first();
        if ($existing) {
            // Oy ekle
            $voted = AnimeRequestVote::where('anime_request_id', $existing->id)
                ->where('user_id', auth()->id())
                ->exists();
            if (!$voted) {
                AnimeRequestVote::create(['anime_request_id' => $existing->id, 'user_id' => auth()->id(), 'created_at' => now()]);
                $existing->increment('vote_count');
            }
            return response()->json(['ok' => true, 'merged' => true, 'request_id' => $existing->id, 'vote_count' => $existing->fresh()->vote_count]);
        }

        $req = AnimeRequest::create([
            'user_id'        => auth()->id(),
            'title'          => $data['title'],
            'original_title' => $data['original_title'] ?? null,
            'note'           => $data['note'] ?? null,
            'status'         => 'pending',
            'vote_count'     => 1,
        ]);

        AnimeRequestVote::create(['anime_request_id' => $req->id, 'user_id' => auth()->id(), 'created_at' => now()]);

        AchievementService::check(auth()->user());

        return response()->json(['ok' => true, 'merged' => false, 'request_id' => $req->id, 'vote_count' => 1]);
    }

    public function requestVote(AnimeRequest $animeRequest)
    {
        $this->requireAuth();

        $voted = AnimeRequestVote::where('anime_request_id', $animeRequest->id)
            ->where('user_id', auth()->id())
            ->exists();

        if ($voted) {
            AnimeRequestVote::where('anime_request_id', $animeRequest->id)
                ->where('user_id', auth()->id())
                ->delete();
            $animeRequest->decrement('vote_count');
            $isVoted = false;
        } else {
            AnimeRequestVote::create(['anime_request_id' => $animeRequest->id, 'user_id' => auth()->id(), 'created_at' => now()]);
            $animeRequest->increment('vote_count');
            $isVoted = true;
        }

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

    // ── Anime Takip ──────────────────────────────────────────────────────────

    public function followToggle(Anime $anime)
    {
        $this->requireAuth();
        $userId = auth()->id();

        $existing = AnimeFollow::where('user_id', $userId)->where('anime_id', $anime->id)->first();

        if ($existing) {
            $existing->delete();
            $following = false;
        } else {
            AnimeFollow::create(['user_id' => $userId, 'anime_id' => $anime->id]);
            $following = true;
        }

        $count = AnimeFollow::where('anime_id', $anime->id)->count();

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

    // ── Bildirimler ───────────────────────────────────────────────────────────

    public function notificationsIndex()
    {
        $this->requireAuth();

        $notifications = UserNotification::where('user_id', auth()->id())
            ->orderByDesc('created_at')
            ->paginate(30);

        // Görüntülenince hepsini okundu yap
        UserNotification::where('user_id', auth()->id())
            ->whereNull('read_at')
            ->update(['read_at' => now()]);

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

    public function notificationsCount()
    {
        if (!auth()->check()) {
            return response()->json(['count' => 0]);
        }
        $count = UserNotification::where('user_id', auth()->id())->whereNull('read_at')->count();
        return response()->json(['count' => $count]);
    }

    // ── Bölüm Notları ─────────────────────────────────────────────────────────

    public function noteStore(Request $request, Episode $episode)
    {
        $this->requireAuth();

        $data = $request->validate([
            'content'      => 'required|string|max:500',
            'timestamp_at' => 'nullable|integer|min:0',
        ]);

        $note = EpisodeNote::create([
            'user_id'      => auth()->id(),
            'episode_id'   => $episode->id,
            'anime_id'     => $episode->anime_id,
            'content'      => $data['content'],
            'timestamp_at' => $data['timestamp_at'] ?? null,
        ]);

        return response()->json([
            'ok'   => true,
            'note' => [
                'id'              => $note->id,
                'content'         => $note->content,
                'timestamp_label' => $note->timestamp_label,
                'timestamp_at'    => $note->timestamp_at,
                'created_at'      => $note->created_at->format('d.m.Y H:i'),
            ],
        ]);
    }

    public function noteDelete(EpisodeNote $note)
    {
        $this->requireAuth();

        if ($note->user_id !== auth()->id()) {
            abort(403);
        }

        $note->delete();

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

    public function episodeNotesList(Episode $episode)
    {
        $this->requireAuth();

        $notes = EpisodeNote::where('user_id', auth()->id())
            ->where('episode_id', $episode->id)
            ->orderBy('timestamp_at')
            ->orderBy('created_at')
            ->get()
            ->map(fn($n) => [
                'id'              => $n->id,
                'content'         => $n->content,
                'timestamp_label' => $n->timestamp_label,
                'timestamp_at'    => $n->timestamp_at,
                'created_at'      => $n->created_at->format('d.m.Y H:i'),
            ]);

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

    // ── Helper ───────────────────────────────────────────────────────────────

    private function requireAuth()
    {
        if (!auth()->check()) {
            abort(401);
        }
    }
}
