<?php

declare(strict_types=1);

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\Story;
use App\Models\StoryTag;
use App\Models\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;

/**
 * Stories API — JSON endpoints for React frontend.
 *
 * GET /api/stories                 list published stories (paginated)
 * GET /api/stories/{slug}          single story detail
 * GET /api/stories/tag/{tag}       stories by tag
 * GET /api/stories/author/{author} stories by author
 * GET /api/stories/featured        featured stories
 */
final class StoriesApiController extends Controller
{
    /**
     * List published stories (paginated).
     * GET /api/stories?page=1&per_page=12
     */
    public function index(Request $request): JsonResponse
    {
        $perPage = min((int) $request->get('per_page', 12), 50);
        $page    = (int) $request->get('page', 1);

        $cacheKey = "stories:api:list:{$perPage}:{$page}";

        $stories = Cache::remember($cacheKey, 300, fn () =>
            Story::published()
                ->with('creator.profile', 'tags')
                ->orderByDesc('published_at')
                ->paginate($perPage, ['*'], 'page', $page)
        );

        return response()->json([
            'data' => $stories->getCollection()->map(fn (Story $s) => $this->formatCard($s)),
            'meta' => [
                'current_page'  => $stories->currentPage(),
                'last_page'     => $stories->lastPage(),
                'per_page'      => $stories->perPage(),
                'total'         => $stories->total(),
            ],
        ]);
    }

    /**
     * Single story detail.
     * GET /api/stories/{slug}
     */
    public function show(string $slug): JsonResponse
    {
        $story = Cache::remember('stories:api:' . $slug, 600, fn () =>
            Story::published()
                ->with('creator.profile', 'tags')
                ->where('slug', $slug)
                ->firstOrFail()
        );

        return response()->json($this->formatFull($story));
    }

    /**
     * Featured story.
     * GET /api/stories/featured
     */
    public function featured(): JsonResponse
    {
        $story = Cache::remember('stories:api:featured', 300, fn () =>
            Story::published()->featured()
                ->with('creator.profile', 'tags')
                ->orderByDesc('published_at')
                ->first()
        );

        if (! $story) {
            return response()->json(null);
        }

        return response()->json($this->formatFull($story));
    }

    /**
     * Stories by tag.
     * GET /api/stories/tag/{tag}?page=1
     */
    public function byTag(Request $request, string $tag): JsonResponse
    {
        $storyTag = StoryTag::where('slug', $tag)->firstOrFail();
        $page     = (int) $request->get('page', 1);

        $stories = Cache::remember("stories:api:tag:{$tag}:{$page}", 300, fn () =>
            Story::published()
                ->with('creator.profile', 'tags')
                ->whereHas('tags', fn ($q) => $q->where('story_tags.id', $storyTag->id))
                ->orderByDesc('published_at')
                ->paginate(12, ['*'], 'page', $page)
        );

        return response()->json([
            'tag'  => ['id' => $storyTag->id, 'slug' => $storyTag->slug, 'name' => $storyTag->name],
            'data' => $stories->getCollection()->map(fn (Story $s) => $this->formatCard($s)),
            'meta' => [
                'current_page' => $stories->currentPage(),
                'last_page'    => $stories->lastPage(),
                'per_page'     => $stories->perPage(),
                'total'        => $stories->total(),
            ],
        ]);
    }

    /**
     * Stories by author.
     * GET /api/stories/author/{username}?page=1
     */
    public function byAuthor(Request $request, string $username): JsonResponse
    {
        $author = User::query()->whereRaw('LOWER(username) = ?', [strtolower($username)])->firstOrFail();

        $page = (int) $request->get('page', 1);

        $stories = Cache::remember("stories:api:author:{$author->id}:{$page}", 300, fn () =>
            Story::published()
            ->with('creator.profile', 'tags')
            ->where('creator_id', $author->id)
                ->orderByDesc('published_at')
                ->paginate(12, ['*'], 'page', $page)
        );

        return response()->json([
            'author' => $this->formatCreator($author),
            'data'   => $stories->getCollection()->map(fn (Story $s) => $this->formatCard($s)),
            'meta'   => [
                'current_page' => $stories->currentPage(),
                'last_page'    => $stories->lastPage(),
                'per_page'     => $stories->perPage(),
                'total'        => $stories->total(),
            ],
        ]);
    }

    // ── Private formatters ────────────────────────────────────────────────

    private function formatCard(Story $story): array
    {
        return [
            'id'           => $story->id,
            'slug'         => $story->slug,
            'url'          => $story->url,
            'title'        => $story->title,
            'excerpt'      => $story->excerpt,
            'cover_image'  => $story->cover_url,
            'author'       => $story->creator ? $this->formatCreator($story->creator) : null,
            'tags'         => $story->tags->map(fn ($t) => ['id' => $t->id, 'slug' => $t->slug, 'name' => $t->name, 'url' => $t->url]),
            'views'        => $story->views,
            'featured'     => $story->featured,
            'reading_time' => $story->reading_time,
            'published_at' => $story->published_at?->toIso8601String(),
        ];
    }

    private function formatFull(Story $story): array
    {
        return array_merge($this->formatCard($story), [
            'content' => $story->content,
        ]);
    }

    private function formatCreator(User $creator): array
    {
        $avatarHash = $creator->profile?->avatar_hash;

        return [
            'id'          => $creator->id,
            'name'        => $creator->username ?? $creator->name,
            'avatar_url'  => $avatarHash
                ? \App\Support\AvatarUrl::forUser((int) $creator->id, $avatarHash, 96)
                : \App\Support\AvatarUrl::default(),
            'bio'         => $creator->profile?->about,
            'profile_url' => '/@' . strtolower((string) ($creator->username ?? $creator->id)),
        ];
    }
}
