<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Http\Resources\VideoCardResource;
use App\Http\Resources\VideoResource;
use App\Models\Video;
use App\Support\Viewer;
use Illuminate\Http\Request;

class VideoController extends Controller
{
    /**
     * Paginated, filterable video grid.
     * Query params: category (slug), q (search), sort (latest|trending),
     * live (1), per_page.
     */
    public function index(Request $request)
    {
        $perPage = min((int) $request->integer('per_page', 12), 40) ?: 12;

        $query = Video::published()
            ->with('category')
            ->withCount(['likes', 'comments']);

        if ($slug = $request->query('category')) {
            $query->whereHas('category', fn ($q) => $q->where('slug', $slug));
        }

        if ($request->boolean('live')) {
            $query->where('is_live', true);
        }

        if ($term = trim((string) $request->query('q', ''))) {
            $like = '%' . $term . '%';
            $query->where(function ($q) use ($like, $term) {
                $q->where('title', 'like', $like)
                    ->orWhere('tags', 'like', '%"' . $term . '"%')
                    ->orWhereHas('category', fn ($c) => $c->where('name', 'like', $like));
            });
        }

        match ($request->query('sort')) {
            'trending' => $query->orderByDesc('views')->orderByDesc('created_at'),
            default => $query->orderByDesc('created_at'),
        };

        $videos = $query->paginate($perPage)->withQueryString();

        return VideoCardResource::collection($videos);
    }

    public function show(Request $request, Video $video)
    {
        abort_if($video->status !== 'published', 404);

        $video->load('category')->loadCount(['likes', 'comments']);

        $viewer = Viewer::fromRequest($request);
        if ($viewer->userId) {
            $video->viewer_liked = $video->likes()->where('user_id', $viewer->userId)->exists();
        }

        return new VideoResource($video);
    }

    /** Related videos: same category first, then shared tags. */
    public function related(Video $video)
    {
        abort_if($video->status !== 'published', 404);

        $related = Video::published()
            ->with('category')
            ->withCount(['likes', 'comments'])
            ->where('id', '!=', $video->id)
            ->where(function ($q) use ($video) {
                if ($video->category_id) {
                    $q->where('category_id', $video->category_id);
                }
                foreach ((array) $video->tags as $tag) {
                    $q->orWhere('tags', 'like', '%"' . $tag . '"%');
                }
            })
            ->orderByDesc('views')
            ->limit(12)
            ->get();

        return VideoCardResource::collection($related);
    }

    /** Record a real view. Called by the player once playback is allowed. */
    public function recordView(Request $request, Video $video)
    {
        abort_if($video->status !== 'published', 404);

        // Only count views for content the viewer is allowed to watch.
        $viewer = Viewer::fromRequest($request);
        if (! $video->isUnlockedFor($viewer->userId, $viewer->guestId)) {
            return response()->json(['message' => 'Video is locked.'], 403);
        }

        $video->increment('views');

        return response()->json(['views' => $video->displayViews()]);
    }
}
