<?php

namespace App\Http\Controllers;

use App\Exceptions\ScheduleStatusTransitionException;
use App\Http\Requests\ScheduleRequest;
use App\Http\Resources\ScheduleResource;
use App\Services\ScheduleService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

class ScheduleController extends Controller
{
    protected $scheduleService;

    public function __construct(ScheduleService $scheduleService)
    {
        $this->scheduleService = $scheduleService;
    }

    public function index(): JsonResponse
    {
        $schedules = $this->scheduleService->getAll();

        return $this->successResponse(
            ScheduleResource::collection($schedules),
        );
    }

    public function store(ScheduleRequest $request): JsonResponse
    {
        try {
            $validated = $request->validated();

            $schedule = $this->scheduleService->create($validated);

            return $this->successResponse(
                payload: new ScheduleResource($schedule),
                message: __('messages.created'),
                code:    201,
            );
        } catch (\Exception $e) {
            return $this->errorResponse($e->getMessage(), 422);
        }
    }

    public function show(string $id): JsonResponse
    {
        $schedule = $this->scheduleService->getById($id);

        return $this->successResponse(
            new ScheduleResource($schedule),
        );
    }

    public function update(ScheduleRequest $request, string $id): JsonResponse
    {
        try {
            $schedule = $this->scheduleService->update($id, $request->validated());

            return $this->successResponse(
                payload: new ScheduleResource($schedule),
                message: __('messages.updated'),
            );
        } catch (\Exception $e) {
            return $this->errorResponse($e->getMessage(), 422);
        }
    }

    public function destroy(string $id): JsonResponse
    {
        $this->scheduleService->delete($id);

        return $this->successResponse(
            message: __('messages.deleted'),
            code:    204,
        );
    }

    //

    public function finished(): JsonResponse
    {
        $schedules = $this->scheduleService->getFinished();

        return $this->successResponse(
            ScheduleResource::collection($schedules),
        );
    }

    public function clientProviderBlocks(Request $request): JsonResponse
    {
        $validated = $request->validate([
            'client_id'   => 'required|integer|exists:clients,id',
            'provider_id' => 'required|integer|exists:providers,id',
        ]);

        $blocks = $this->scheduleService->getClientProviderBlocks(
            (int) data_get($validated, 'client_id'),
            (int) data_get($validated, 'provider_id'),
        );

        return $this->successResponse(payload: $blocks);
    }

    public function groupedByClient(): JsonResponse
    {
        $grouped = $this->scheduleService->getSchedulesDefaultGroupedByClient();

        return $this->successResponse($grouped);
    }

    //

    public function cancelWithReason(string $id, Request $request): JsonResponse
    {
        try {
            $validated = $request->validate([
                'cancel_text' => 'required|string|min:5|max:1000',
            ]);

            $schedule = $this->scheduleService->cancelWithReason((int) $id, data_get($validated, 'cancel_text'));

            return $this->successResponse(
                payload: new ScheduleResource($schedule),
                message: __('messages.updated'),
            );
        } catch (ScheduleStatusTransitionException) {
            return $this->errorResponse(__('messages.cancellation_not_allowed_for_status'), 422);
        } catch (\Exception $e) {
            return $this->errorResponse($e->getMessage(), 422);
        }
    }

    public function updateStatus(string $id, ScheduleRequest $request): JsonResponse
    {
        try {
            $validated = $request->validate([
                'status' => 'required|in:pending,accepted,rejected,paid,cancelled,started,finished',
            ]);

            $schedule = $this->scheduleService->updateStatus($id, data_get($validated, 'status'));

            return $this->successResponse(
                payload: new ScheduleResource($schedule),
                message: __('messages.updated'),
            );
        } catch (ScheduleStatusTransitionException) {
            return $this->errorResponse(__('messages.status_transition_not_allowed'), 422);
        } catch (\Exception $e) {
            return $this->errorResponse($e->getMessage(), 422);
        }
    }
}
