<?php

namespace App\Http\Controllers\Api\Parents;

use App\Http\Controllers\Api\Core\BaseApiController;
use App\Http\Requests\Promotions\ParentEnrollmentStepRequest;
use App\Http\Requests\Promotions\ParentPromotionOverviewRequest;
use App\Http\Resources\Promotions\StudentPromotionResource;
use App\Models\Student;
use App\Models\StudentPromotionRecord;
use App\Services\Promotions\PromotionEnrollmentService;
use App\Services\Promotions\PromotionQueryService;
use Illuminate\Http\JsonResponse;
use Symfony\Component\HttpFoundation\Response;

/**
 * Parent portal endpoints for the promotion + enrollment workflow
 * (plan section 12). The parent sees the promoted level and can step
 * through the enrollment checklist defined in plan section 8.
 */
class ParentPromotionController extends BaseApiController
{
    public function __construct(
        private PromotionEnrollmentService $service,
        private PromotionQueryService $query
    ) {
        parent::__construct();
    }

    public function overview(ParentPromotionOverviewRequest $request): JsonResponse
    {
        $guard = $this->parentIdOrUnauthorized();
        if ($guard instanceof JsonResponse) {
            return $guard;
        }

        $data = $this->service->overviewForParent(
            $guard,
            $request->validated()['next_school_year'] ?? null
        );

        return response()->json([
            'ok' => true,
            'records' => $data['records'],
            'next_school_year' => $data['next_school_year'],
            'message' => $data['message'],
        ]);
    }

    public function show(int $promotionId): JsonResponse
    {
        $guard = $this->parentIdOrUnauthorized();
        if ($guard instanceof JsonResponse) {
            return $guard;
        }

        $record = $this->loadOwnedRecord($promotionId, $guard);
        if ($record instanceof JsonResponse) {
            return $record;
        }

        return response()->json([
            'ok' => true,
            'data' => new StudentPromotionResource($this->query->detail($record)),
        ]);
    }

    public function start(int $promotionId): JsonResponse
    {
        $guard = $this->parentIdOrUnauthorized();
        if ($guard instanceof JsonResponse) {
            return $guard;
        }

        $record = $this->loadOwnedRecord($promotionId, $guard);
        if ($record instanceof JsonResponse) {
            return $record;
        }

        try {
            $updated = $this->service->startEnrollment($record, $guard, $guard);
        } catch (\RuntimeException $e) {
            return response()->json(['ok' => false, 'message' => $e->getMessage()], Response::HTTP_CONFLICT);
        }

        return response()->json([
            'ok' => true,
            'data' => new StudentPromotionResource($this->query->detail($updated->refresh())),
        ]);
    }

    public function updateSteps(ParentEnrollmentStepRequest $request, int $promotionId): JsonResponse
    {
        $guard = $this->parentIdOrUnauthorized();
        if ($guard instanceof JsonResponse) {
            return $guard;
        }

        $record = $this->loadOwnedRecord($promotionId, $guard);
        if ($record instanceof JsonResponse) {
            return $record;
        }

        try {
            $updated = $this->service->updateSteps($record, $guard, $request->steps(), $guard);
        } catch (\RuntimeException $e) {
            return response()->json(['ok' => false, 'message' => $e->getMessage()], Response::HTTP_CONFLICT);
        }

        return response()->json([
            'ok' => true,
            'data' => new StudentPromotionResource($this->query->detail($updated->refresh())),
        ]);
    }

    public function submit(int $promotionId): JsonResponse
    {
        $guard = $this->parentIdOrUnauthorized();
        if ($guard instanceof JsonResponse) {
            return $guard;
        }

        $record = $this->loadOwnedRecord($promotionId, $guard);
        if ($record instanceof JsonResponse) {
            return $record;
        }

        try {
            $updated = $this->service->submitEnrollment($record, $guard, $guard);
        } catch (\RuntimeException $e) {
            return response()->json(['ok' => false, 'message' => $e->getMessage()], Response::HTTP_CONFLICT);
        }

        return response()->json([
            'ok' => true,
            'data' => new StudentPromotionResource($this->query->detail($updated->refresh())),
        ]);
    }

    private function loadOwnedRecord(int $promotionId, int $parentId): StudentPromotionRecord|JsonResponse
    {
        $record = StudentPromotionRecord::query()->find($promotionId);
        if (!$record) {
            return response()->json(['ok' => false, 'message' => 'Promotion record not found.'], Response::HTTP_NOT_FOUND);
        }

        $owns = (int) $record->parent_id === $parentId;
        if (!$owns) {
            $studentParentId = (int) (Student::query()
                ->where('id', $record->student_id)
                ->value('parent_id') ?? 0);
            $owns = $studentParentId === $parentId;
        }
        if (!$owns) {
            return response()->json(['ok' => false, 'message' => 'You are not authorised to view this promotion record.'], Response::HTTP_FORBIDDEN);
        }
        return $record;
    }

    private function parentIdOrUnauthorized(): int|JsonResponse
    {
        $request = request();
        $primary = (int) ($request?->attributes?->get('primary_parent_id') ?? 0);
        if ($primary > 0) {
            return $primary;
        }
        $parentId = (int) (auth()->id() ?? 0);
        if ($parentId <= 0) {
            return response()->json(['ok' => false, 'message' => 'Unauthorized.'], Response::HTTP_UNAUTHORIZED);
        }
        return $parentId;
    }
}
