<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\Tribunal;
use App\Models\TribunalArgument;
use App\Models\TribunalArgumentVote;
use App\Models\TribunalVote;
use App\Support\MediaUrl;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class TribunalApiController extends Controller
{
    public function index(Request $request)
    {
        $query = Tribunal::with(['anime:id,title,slug,cover_image', 'creator:id,name,username'])
            ->withCount('votes');

        if ($request->filled('anime_id')) {
            $query->where('anime_id', $request->anime_id);
        }
        if ($request->filled('status')) {
            $query->where('status', $request->status);
        }

        $tribunals = $query->latest()->paginate(15);

        return response()->json([
            'data'      => collect($tribunals->items())->map(fn($t) => $this->formatTribunal($t))->values(),
            'has_more'  => $tribunals->hasMorePages(),
            'next_page' => $tribunals->hasMorePages() ? $tribunals->currentPage() + 1 : null,
        ]);
    }

    public function show(Tribunal $tribunal)
    {
        $tribunal->load(['anime:id,title,slug,cover_image', 'creator:id,name,username']);
        $me    = Auth::id();
        $sides = $tribunal->allSides();

        $vcounts = [];
        foreach (array_keys($sides) as $key) {
            $vcounts[$key] = TribunalVote::where('tribunal_id', $tribunal->id)->where('side', $key)->count();
        }

        $myVote = $me ? TribunalVote::where('tribunal_id', $tribunal->id)->where('user_id', $me)->value('side') : null;
        $myArg  = $me ? TribunalArgument::where('tribunal_id', $tribunal->id)->where('user_id', $me)->first() : null;

        $arguments = TribunalArgument::with('user:id,name,username')
            ->where('tribunal_id', $tribunal->id)
            ->orderByDesc('vote_count')
            ->get()
            ->map(fn($a) => [
                'id'         => $a->id,
                'side'       => $a->side,
                'body'       => $a->body,
                'vote_count' => $a->vote_count,
                'username'   => $a->user?->username,
                'is_mine'    => $me && $a->user_id === $me,
                'voted'      => $me ? TribunalArgumentVote::where('argument_id', $a->id)->where('user_id', $me)->exists() : false,
            ]);

        return response()->json([
            'tribunal'    => $this->formatTribunal($tribunal),
            'sides'       => $sides,
            'vote_counts' => $vcounts,
            'total_votes' => array_sum($vcounts),
            'my_vote'     => $myVote,
            'my_argument' => $myArg ? ['id' => $myArg->id, 'side' => $myArg->side, 'body' => $myArg->body] : null,
            'arguments'   => $arguments,
        ]);
    }

    public function store(Request $request)
    {
        $data = $request->validate([
            'anime_id'     => 'required|exists:animes,id',
            'question'     => 'required|string|min:10|max:280',
            'side_a'       => 'required|string|min:2|max:100',
            'side_b'       => 'required|string|min:2|max:100',
            'extra_sides'  => 'nullable|array|max:4',
            'extra_sides.*'=> 'required|string|min:2|max:100',
            'closes_at'    => 'nullable|date|after:today',
        ]);

        $me = Auth::user();

        $tribunal = Tribunal::create([
            'anime_id'    => $data['anime_id'],
            'created_by'  => $me->id,
            'question'    => $data['question'],
            'side_a'      => $data['side_a'],
            'side_b'      => $data['side_b'],
            'extra_sides' => $data['extra_sides'] ?? [],
            'status'      => 'open',
            'closes_at'   => $data['closes_at'] ?? now()->addDays(7),
        ]);

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

    public function vote(Request $request, Tribunal $tribunal)
    {
        if ($tribunal->status !== 'open') {
            return response()->json(['error' => 'Bu dava kapalı.'], 422);
        }

        $sides = array_keys($tribunal->allSides());
        $data  = $request->validate(['side' => 'required|in:' . implode(',', $sides)]);
        $me    = Auth::id();

        $existing = TribunalVote::where('tribunal_id', $tribunal->id)->where('user_id', $me)->first();

        if ($existing) {
            if ($existing->side === $data['side']) {
                $existing->delete();
                $voted = null;
            } else {
                $existing->update(['side' => $data['side']]);
                $voted = $data['side'];
            }
        } else {
            TribunalVote::create(['tribunal_id' => $tribunal->id, 'user_id' => $me, 'side' => $data['side']]);
            $voted = $data['side'];
        }

        $vcounts = [];
        foreach (array_keys($tribunal->allSides()) as $key) {
            $vcounts[$key] = TribunalVote::where('tribunal_id', $tribunal->id)->where('side', $key)->count();
        }

        return response()->json(['voted' => $voted, 'vote_counts' => $vcounts, 'total_votes' => array_sum($vcounts)]);
    }

    public function argue(Request $request, Tribunal $tribunal)
    {
        if ($tribunal->status !== 'open') {
            return response()->json(['error' => 'Bu dava kapalı.'], 422);
        }

        $sides = array_keys($tribunal->allSides());
        $data  = $request->validate([
            'side' => 'required|in:' . implode(',', $sides),
            'body' => 'required|string|min:5|max:500',
        ]);

        $me       = Auth::user();
        $existing = TribunalArgument::where('tribunal_id', $tribunal->id)->where('user_id', $me->id)->first();

        if ($existing) {
            $existing->update(['side' => $data['side'], 'body' => $data['body']]);
            return response()->json(['ok' => true, 'id' => $existing->id, 'updated' => true]);
        }

        $arg = TribunalArgument::create([
            'tribunal_id' => $tribunal->id,
            'user_id'     => $me->id,
            'side'        => $data['side'],
            'body'        => $data['body'],
        ]);

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

    public function argVote(TribunalArgument $argument)
    {
        $me       = Auth::id();
        $existing = TribunalArgumentVote::where('argument_id', $argument->id)->where('user_id', $me)->first();

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

        TribunalArgumentVote::create(['argument_id' => $argument->id, 'user_id' => $me]);
        $argument->increment('vote_count');
        return response()->json(['voted' => true, 'vote_count' => $argument->fresh()->vote_count]);
    }

    private function formatTribunal(Tribunal $t): array
    {
        return [
            'id'          => $t->id,
            'question'    => $t->question,
            'status'      => $t->status,
            'sides'       => $t->allSides(),
            'votes_count' => $t->votes_count ?? TribunalVote::where('tribunal_id', $t->id)->count(),
            'closes_at'   => $t->closes_at?->toIso8601String(),
            'created_at'  => $t->created_at->diffForHumans(),
            'anime'       => $t->anime ? [
                'id'    => $t->anime->id,
                'title' => $t->anime->title,
                'slug'  => $t->anime->slug,
                'cover' => $t->anime->cover_image ? MediaUrl::fromStoragePath($t->anime->cover_image) : null,
            ] : null,
            'creator' => $t->creator ? [
                'name'     => $t->creator->name,
                'username' => $t->creator->username,
            ] : null,
        ];
    }
}
