<?php

namespace App\Http\Controllers;

use App\Http\Requests\StoreHuntRequest;
use App\Http\Requests\UpdateHuntRequest;
use App\Models\Hunts;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Log;

class HuntsController extends Controller
{
    /**
     * Display a listing of the resource.
     */
    public function index(Request $request): JsonResponse
    {
        try {
            $searchTerm = $this->resolveSearchTerm($request);

            if ($searchTerm !== null) {
                $hunts = Hunts::search($searchTerm)
                    ->query(fn (Builder $query) => $this->applyHuntFilters(
                        $query->with('participants:id,avatar_uri'),
                        $request
                    ))
                    ->paginate(10);

                return response()->json($hunts);
            }

            $query = $this->applyHuntFilters(
                Hunts::with('participants:id,avatar_uri'),
                $request
            );

            $hunts = $query->paginate(10);

            return response()->json($hunts);
        } catch (\Throwable $e) {
            Log::error('Error fetching hunts: '.$e->getMessage());

            return response()->json([
                'error' => 'Server Error',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    private function applyHuntFilters(Builder $query, Request $request): Builder
    {
        if ($request->has('participating')) {
            $participating = filter_var(
                $request->query('participating'),
                FILTER_VALIDATE_BOOLEAN,
                FILTER_NULL_ON_FAILURE
            );

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

            Log::info('Participating filter resolved', [
                'participating' => $participating,
                'user_id' => $userId,
            ]);

            if (! $userId) {
                if ($participating === true) {
                    $query->whereRaw('1 = 0');
                }
            } else {
                if ($participating === true) {
                    $query->whereHas('participants', function ($q) use ($userId) {
                        $q->where('user_id', $userId);
                    });
                } else {
                    $query->whereDoesntHave('participants', function ($q) use ($userId) {
                        $q->where('user_id', $userId);
                    });
                }
            }
        }

        if ($request->has('active')) {
            $now = Carbon::now();
            $active = filter_var($request->query('active'), FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE);

            if ($active === true) {
                $query->where('start_at', '<=', $now)
                    ->where(function ($q) use ($now) {
                        $q->whereNull('end_at')
                            ->orWhere('end_at', '>=', $now);
                    });
            } else {
                $query->where(function ($q) use ($now) {
                    $q->whereNull('start_at')
                        ->orWhere('start_at', '>', $now)
                        ->orWhere(function ($q2) use ($now) {
                            $q2->whereNotNull('end_at')
                                ->where('end_at', '<', $now);
                        });
                });
            }
        }

        return $query;
    }

    private function resolveSearchTerm(Request $request): ?string
    {
        $searchTerm = $request->query('search') ?? $request->query('q');

        if (! is_string($searchTerm)) {
            return null;
        }

        $searchTerm = trim($searchTerm);

        return $searchTerm !== '' ? $searchTerm : null;
    }

    /**
     * Store a newly created resource in storage.
     */
    public function store(StoreHuntRequest $request): JsonResponse
    {
        $validated = $request->validated();

        $validated['creator_id'] = auth()->id();

        $hunt = Hunts::create($validated);

        return response()->json($hunt, 201);
    }

    /**
     * Display the specified resource.
     */
    /**
     * Display the specified resource.
     */
    public function show(Request $request, int $id): JsonResponse
    {
        $hunt = Hunts::with(['steps', 'participants:id,avatar_uri'])->find($id);

        if (! $hunt) {
            return response()->json(['message' => 'Hunt not found'], 404);
        }

        $user = $request->user('sanctum');

        if ($user) {
            $participation = $user->participations()->where('hunt_id', $hunt->id)->first();

            if ($participation) {
                // User is a participant
                $currentStepNumber = $participation->pivot->current_step_number;

                // Filter steps
                $hunt->setRelation('steps', $hunt->steps->filter(function ($step) use ($currentStepNumber) {
                    if ($step->step_number < $currentStepNumber) {
                        return true; // Show past steps fully
                    }
                    if ($step->step_number == $currentStepNumber) {
                        // Show hints but hide location for current step
                        $step->makeHidden(['latitude', 'longitude', 'radius_m']);

                        return true;
                    }

                    return false; // Hide future steps
                })->values());

                $hunt->participation_status = $participation->pivot;
            } elseif ($hunt->creator_id !== $user->id) {
                // User is logged in but not participant and not creator
                // Show only first step or nothing specific (keep as is for now, maybe hide all steps or just show basic info)
                // For now, let's just hide hints of all steps if not participating?
                // Or maybe just show nothing of steps if not participating?
                // Requirement: "fetch the hunt in question it retrieves me the hunt steps already passed and the next one" implying context of participation.
                // If not participating, maybe just return basic hunt info without steps?
                $hunt->unsetRelation('steps');
            }
            // If creator, show everything (default)
        } else {
            // Guest
            $hunt->unsetRelation('steps');
        }

        return response()->json($hunt);
    }

    public function participate(Request $request, int $id): JsonResponse
    {
        $hunt = Hunts::findOrFail($id);
        $user = $request->user();

        if ($user->participations()->where('hunt_id', $hunt->id)->exists()) {
            return response()->json(['message' => 'Already participating'], 409);
        }

        $hunt->participants()->attach($user->id, ['current_step_number' => 1, 'status' => 'started']);

        return response()->json(['message' => 'Participation started'], 201);
    }

    public function unparticipate(Request $request, int $id): JsonResponse
    {
        $hunt = Hunts::findOrFail($id);
        $user = $request->user();

        if (! $user->participations()->where('hunt_id', $hunt->id)->exists()) {
            return response()->json(['message' => 'Not participating'], 404);
        }

        $hunt->participants()->detach($user->id);

        return response()->json(['message' => 'Participation stopped'], 200);
    }

    /**
     * Update the specified resource in storage.
     */
    public function update(UpdateHuntRequest $request, int $id): JsonResponse
    {
        $hunt = Hunts::find($id);

        if (! $hunt) {
            return response()->json(['message' => 'Hunt not found'], 404);
        }

        $validated = $request->validated();

        $hunt->update($validated);

        return response()->json($hunt);
    }

    /**
     * Remove the specified resource from storage.
     */
    public function destroy(int $id): JsonResponse
    {
        $hunt = Hunts::find($id);

        if (! $hunt) {
            return response()->json(['message' => 'Hunt not found'], 404);
        }

        $hunt->delete();

        return response()->json(['message' => 'Hunt deleted successfully']);
    }
}
