<?php

namespace App\Http\Controllers\Api\Settings;

use App\Http\Controllers\Api\Core\BaseApiController;
use App\Http\Requests\Events\EventChargeIndexRequest;
use App\Http\Requests\Events\EventChargeUpdateRequest;
use App\Http\Requests\Events\EventIndexRequest;
use App\Http\Requests\Events\EventStoreRequest;
use App\Http\Requests\Events\EventStudentsWithChargesRequest;
use App\Http\Requests\Events\EventUpdateRequest;
use App\Http\Resources\Events\EventChargeResource;
use App\Http\Resources\Events\EventResource;
use App\Http\Resources\Events\EventStudentChargeResource;
use App\Services\Events\EventCategoryService;
use App\Services\Events\EventChargeQueryService;
use App\Services\Events\EventChargeService;
use App\Services\Events\EventListService;
use App\Services\Events\EventManagementService;
use App\Services\Events\EventStudentChargeService;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Log;

class EventController extends BaseApiController
{
    public function __construct(
        private EventListService $listService,
        private EventManagementService $managementService,
        private EventChargeQueryService $chargeQueryService,
        private EventChargeService $chargeService,
        private EventStudentChargeService $studentChargeService
    ) {
        parent::__construct();
    }

    public function index(EventIndexRequest $request): JsonResponse
    {
        $payload = $request->validated();
        $result = $this->listService->list($payload);

        return response()->json([
            'ok' => true,
            'events' => EventResource::collection($result['events']),
            'pagination' => $result['pagination'],
            'active_count' => $result['active_count'],
            'categories' => EventCategoryService::categories(),
        ]);
    }

    public function show(int $eventId): JsonResponse
    {
        $event = $this->listService->find($eventId);
        if (!$event) {
            return response()->json(['ok' => false, 'message' => 'Event not found.'], 404);
        }

        return response()->json([
            'ok' => true,
            'event' => new EventResource($event),
        ]);
    }

    public function store(EventStoreRequest $request): JsonResponse
    {
        $guard = $this->authenticatedUserIdOrUnauthorized();
        if ($guard instanceof JsonResponse) {
            return $guard;
        }

        $payload = $request->validated();

        try {
            $result = $this->managementService->create($payload, $request->file('flyer'), $guard);
        } catch (\Throwable $e) {
            Log::error('Event creation failed.', ['error' => $e->getMessage()]);
            return response()->json(['ok' => false, 'message' => 'Failed to create event.'], 500);
        }

        if (empty($result['ok'])) {
            return response()->json(['ok' => false, 'message' => 'Failed to create event.'], 422);
        }

        return response()->json([
            'ok' => true,
            'event' => new EventResource($result['event']),
            'charges_created' => $result['charges_created'] ?? 0,
        ], 201);
    }

    public function update(EventUpdateRequest $request, int $eventId): JsonResponse
    {
        $payload = $request->validated();

        $result = $this->managementService->update($eventId, $payload, $request->file('flyer'));
        if (empty($result['ok'])) {
            return response()->json(['ok' => false, 'message' => $result['message'] ?? 'Failed to update event.'], 404);
        }

        return response()->json([
            'ok' => true,
            'event' => new EventResource($result['event']),
        ]);
    }

    public function destroy(int $eventId): JsonResponse
    {
        $guard = $this->authenticatedUserIdOrUnauthorized();
        if ($guard instanceof JsonResponse) {
            return $guard;
        }

        $result = $this->managementService->delete($eventId, $guard);

        if (empty($result['ok'])) {
            return response()->json(['ok' => false, 'message' => $result['message'] ?? 'Failed to delete event.'], 404);
        }

        return response()->json(['ok' => true]);
    }

    public function charges(EventChargeIndexRequest $request): JsonResponse
    {
        $payload = $request->validated();
        $result = $this->chargeQueryService->list($payload);

        return response()->json([
            'ok' => true,
            'charges' => EventChargeResource::collection($result['charges']),
            'pagination' => $result['pagination'],
        ]);
    }

    public function updateCharges(EventChargeUpdateRequest $request, int $eventId): JsonResponse
    {
        $guard = $this->authenticatedUserIdOrUnauthorized();
        if ($guard instanceof JsonResponse) {
            return $guard;
        }

        $payload = $request->validated();

        $result = $this->chargeService->updateParticipation(
            (int) $payload['parent_id'],
            $eventId,
            $payload['participation'],
            (string) $payload['school_year'],
            (string) $payload['semester'],
            $guard
        );

        if (empty($result['ok'])) {
            return response()->json(['ok' => false, 'message' => $result['message'] ?? 'Failed to update charges.'], 422);
        }

        return response()->json([
            'ok' => true,
            'created' => $result['created'],
            'updated' => $result['updated'],
            'deleted' => $result['deleted'],
        ]);
    }

    public function studentsWithCharges(EventStudentsWithChargesRequest $request): JsonResponse
    {
        $payload = $request->validated();

        $students = $this->studentChargeService->listStudentsWithCharges(
            (int) $payload['parent_id'],
            (string) $payload['school_year'],
            (string) $payload['semester']
        );

        return response()->json([
            'ok' => true,
            'students' => EventStudentChargeResource::collection($students),
        ]);
    }

    /**
     * @return int|JsonResponse
     */
    private function authenticatedUserIdOrUnauthorized(): int|JsonResponse
    {
        $userId = (int) (auth()->id() ?? 0);
        if ($userId <= 0) {
            return response()->json(['ok' => false, 'message' => 'Unauthorized.'], 401);
        }

        return $userId;
    }
}
