<?php

namespace App\Http\Controllers\Api\V1;

use App\Enums\ClothingOccasion;
use App\Enums\ClothingSeason;
use App\Http\Controllers\Controller;
use App\Http\Resources\OutfitResource;
use App\Http\Resources\OutfitSuggestionCollection;
use App\Models\Outfit;
use App\Services\OutfitSuggestionService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
use Illuminate\Pagination\LengthAwarePaginator;

class OutfitController extends Controller
{
    public function index(Request $request, OutfitSuggestionService $service): OutfitSuggestionCollection
    {
        $season = $request->filled('season')
            ? ClothingSeason::tryFrom($request->string('season')->toString())
            : null;

        $occasion = $request->filled('occasion')
            ? ClothingOccasion::tryFrom($request->string('occasion')->toString())
            : null;

        $shuffle = $request->boolean('shuffle');

        $suggestions = $service->suggest($request->user(), $season, $occasion, $shuffle);

        $perPage = min((int) $request->input('per_page', 15), 100);
        $page = max((int) $request->input('page', 1), 1);

        $total = $suggestions->count();
        $items = $suggestions->slice(($page - 1) * $perPage, $perPage)->values();

        $paginator = new LengthAwarePaginator(
            $items,
            $total,
            $perPage,
            $page,
            ['path' => $request->url(), 'query' => $request->query()],
        );

        return new OutfitSuggestionCollection($paginator);
    }

    public function saved(Request $request): AnonymousResourceCollection
    {
        $outfits = $request->user()
            ->outfits()
            ->with('clothingItems')
            ->latest()
            ->paginate(min((int) $request->input('per_page', 15), 100));

        return OutfitResource::collection($outfits);
    }

    public function store(Request $request): JsonResponse
    {
        $validated = $request->validate([
            'name' => ['required', 'string', 'max:255'],
            'occasion' => ['required', 'string'],
            'season' => ['required', 'string'],
            'item_ids' => ['required', 'array', 'min:1'],
            'item_ids.*' => ['required', 'integer', 'exists:clothing_items,id'],
        ]);

        $userItemIds = $request->user()->clothingItems()->pluck('id')->all();

        foreach ($validated['item_ids'] as $id) {
            abort_unless(in_array($id, $userItemIds), 403);
        }

        $outfit = new Outfit([
            'name' => $validated['name'],
            'occasion' => $validated['occasion'],
            'season' => $validated['season'],
        ]);
        $outfit->user_id = $request->user()->id;
        $outfit->save();

        $outfit->clothingItems()->attach($validated['item_ids']);
        $outfit->load('clothingItems');

        return (new OutfitResource($outfit))
            ->response()
            ->setStatusCode(201);
    }

    public function destroy(Request $request, Outfit $outfit): JsonResponse
    {
        abort_unless($outfit->user_id === $request->user()->id, 403);

        $outfit->delete();

        return response()->json(null, 204);
    }
}
