<?php

namespace App\Http\Controllers\Api\Grading;

use App\Http\Controllers\Api\BaseApiController;
use App\Http\Requests\Grading\BelowSixtyEmailRequest;
use App\Http\Requests\Grading\BelowSixtyMeetingRequest;
use App\Http\Requests\Grading\BelowSixtyMeetingSaveRequest;
use App\Http\Requests\Grading\BelowSixtySendRequest;
use App\Http\Requests\Grading\BelowSixtyStatusRequest;
use App\Http\Requests\Grading\BelowSixtyListRequest;
use App\Http\Requests\Grading\GradingLockAllRequest;
use App\Http\Requests\Grading\GradingLockRequest;
use App\Http\Requests\Grading\GradingOverviewRequest;
use App\Http\Requests\Grading\GradingRefreshRequest;
use App\Http\Requests\Grading\GradingScoreShowRequest;
use App\Http\Requests\Grading\GradingScoreUpdateRequest;
use App\Http\Requests\Grading\PlacementBatchRequest;
use App\Http\Requests\Grading\PlacementBatchUpdateRequest;
use App\Http\Requests\Grading\PlacementLevelsRequest;
use App\Http\Requests\Grading\PlacementLevelRequest;
use App\Http\Requests\Grading\PlacementRequest;
use App\Http\Resources\Grading\BelowSixtyStudentResource;
use App\Http\Resources\Grading\GradingScoreResource;
use App\Services\Grading\GradingBelowSixtyService;
use App\Services\Grading\GradingLockService;
use App\Services\Grading\GradingOverviewService;
use App\Services\Grading\GradingPlacementService;
use App\Services\Grading\GradingRefreshService;
use App\Services\Grading\GradingScoreService;
use Illuminate\Http\JsonResponse;

class GradingController extends BaseApiController
{
    public function __construct(
        private GradingOverviewService $overviewService,
        private GradingScoreService $scoreService,
        private GradingLockService $lockService,
        private GradingRefreshService $refreshService,
        private GradingPlacementService $placementService,
        private GradingBelowSixtyService $belowSixtyService
    ) {
        parent::__construct();
    }

    public function overview(GradingOverviewRequest $request): JsonResponse
    {
        $payload = $request->validated();
        $data = $this->overviewService->overview(
            isset($payload['class_id']) ? (int) $payload['class_id'] : null,
            $payload['semester'] ?? null,
            $payload['school_year'] ?? null
        );

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

    public function show(GradingScoreShowRequest $request, string $type, int $classSectionId, int $studentId): JsonResponse
    {
        $payload = $request->validated();
        $data = $this->scoreService->show(
            $type,
            $classSectionId,
            $studentId,
            (string) $payload['semester'],
            (string) $payload['school_year']
        );

        return response()->json([
            'ok' => true,
            'student' => $data['student'],
            'scores' => GradingScoreResource::collection($data['scores']),
            'type' => $data['type'],
            'class_section_id' => $data['class_section_id'],
            'semester' => $data['semester'],
            'scores_locked' => $data['scores_locked'],
        ]);
    }

    public function update(GradingScoreUpdateRequest $request): JsonResponse
    {
        $payload = $request->validated();
        $this->scoreService->update($payload, (int) (auth()->id() ?? 0));

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

    public function toggleLock(GradingLockRequest $request): JsonResponse
    {
        $payload = $request->validated();
        $locked = $this->lockService->toggle(
            (int) $payload['class_section_id'],
            (string) $payload['semester'],
            (string) $payload['school_year'],
            (int) (auth()->id() ?? 0)
        );

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

    public function lockAll(GradingLockAllRequest $request): JsonResponse
    {
        $payload = $request->validated();
        $count = $this->lockService->lockAll(
            (string) $payload['semester'],
            (string) $payload['school_year'],
            (int) (auth()->id() ?? 0)
        );

        return response()->json(['ok' => true, 'locked_count' => $count]);
    }

    public function refresh(GradingRefreshRequest $request): JsonResponse
    {
        $payload = $request->validated();
        $this->refreshService->refreshSemesterScores(
            (int) $payload['class_section_id'],
            (string) $payload['semester'],
            (string) $payload['school_year']
        );

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

    public function placement(PlacementRequest $request): JsonResponse
    {
        $payload = $request->validated();
        $data = $this->placementService->placementContext(
            isset($payload['class_section_id']) ? (int) $payload['class_section_id'] : null,
            (string) $payload['school_year'],
            $payload['placement_test'] ?? null,
            $payload['open'] ?? null
        );

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

    public function updatePlacementLevel(PlacementLevelRequest $request): JsonResponse
    {
        $payload = $request->validated();
        $this->placementService->updatePlacementLevel(
            (int) $payload['student_id'],
            (string) $payload['school_year'],
            $payload['placement_level'] ?? null,
            (int) (auth()->id() ?? 0)
        );

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

    public function updatePlacementLevels(PlacementLevelsRequest $request): JsonResponse
    {
        $payload = $request->validated();
        $this->placementService->updatePlacementLevels(
            (int) $payload['class_section_id'],
            (string) $payload['school_year'],
            $payload['placement_level'] ?? [],
            (int) (auth()->id() ?? 0)
        );

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

    public function createPlacementBatch(PlacementBatchRequest $request): JsonResponse
    {
        $payload = $request->validated();
        $batchId = $this->placementService->createPlacementBatch(
            (string) $payload['school_year'],
            (string) $payload['placement_test'],
            $payload['placement_level'] ?? [],
            (int) (auth()->id() ?? 0)
        );

        return response()->json(['ok' => true, 'batch_id' => $batchId]);
    }

    public function showPlacementBatch(int $batchId): JsonResponse
    {
        $data = $this->placementService->getPlacementBatch($batchId);

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

    public function updatePlacementBatch(PlacementBatchUpdateRequest $request, int $batchId): JsonResponse
    {
        $payload = $request->validated();
        $this->placementService->updatePlacementBatch(
            $batchId,
            (string) $payload['school_year'],
            $payload['placement_level'] ?? [],
            (int) (auth()->id() ?? 0)
        );

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

    public function belowSixty(BelowSixtyListRequest $request): JsonResponse
    {
        $payload = $request->validated();
        $rows = $this->belowSixtyService->listRows(
            (string) $payload['school_year'],
            (string) $payload['semester']
        );

        return response()->json([
            'ok' => true,
            'rows' => BelowSixtyStudentResource::collection($rows),
            'semester' => $payload['semester'],
            'school_year' => $payload['school_year'],
        ]);
    }

    public function belowSixtyEmail(BelowSixtyEmailRequest $request): JsonResponse
    {
        $payload = $request->validated();
        $data = $this->belowSixtyService->emailContext(
            (int) $payload['student_id'],
            (string) $payload['school_year'],
            (string) $payload['semester']
        );

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

    public function sendBelowSixtyEmail(BelowSixtySendRequest $request): JsonResponse
    {
        $payload = $request->validated();
        $data = $this->belowSixtyService->emailContext(
            (int) $payload['student_id'],
            (string) $payload['school_year'],
            (string) $payload['semester']
        );

        $subject = trim((string) ($payload['subject'] ?? ''));
        if ($subject !== '') {
            $data['subject'] = $subject;
        }
        if (isset($payload['html']) && trim((string) $payload['html']) !== '') {
            $data['html'] = (string) $payload['html'];
        }

        $this->belowSixtyService->sendEmail($data);

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

    public function updateBelowSixtyStatus(BelowSixtyStatusRequest $request): JsonResponse
    {
        $payload = $request->validated();
        $this->belowSixtyService->updateStatus(
            (int) $payload['student_id'],
            (string) $payload['semester'],
            (string) $payload['school_year'],
            (string) $payload['status'],
            (string) ($payload['note'] ?? ''),
            (int) (auth()->id() ?? 0)
        );

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

    public function belowSixtyMeeting(BelowSixtyMeetingRequest $request): JsonResponse
    {
        $payload = $request->validated();
        $data = $this->belowSixtyService->meetingContext(
            (int) $payload['student_id'],
            (string) $payload['school_year'],
            (string) $payload['semester']
        );

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

    public function saveBelowSixtyMeeting(BelowSixtyMeetingSaveRequest $request): JsonResponse
    {
        $payload = $request->validated();
        $this->belowSixtyService->saveMeeting($payload, (int) (auth()->id() ?? 0));

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