<?php

namespace App\Services\Grading;

use App\Models\GradingLock;
use App\Models\ClassSection;
use RuntimeException;

class GradingLockService
{
    public function toggle(int $classSectionId, string $semester, string $schoolYear, ?int $userId): bool
    {
        if ($classSectionId <= 0 || $semester === '' || $schoolYear === '') {
            throw new RuntimeException('Missing class section or term.');
        }

        $existing = GradingLock::getLock($classSectionId, $semester, $schoolYear);

        if ($existing && $existing->is_locked) {
            $existing->update([
                'is_locked' => 0,
                'locked_by' => null,
                'locked_at' => null,
            ]);
            return false;
        }

        if ($existing) {
            $existing->update([
                'is_locked' => 1,
                'locked_by' => $userId ?: null,
                'locked_at' => now(),
            ]);
        } else {
            GradingLock::query()->create([
                'class_section_id' => $classSectionId,
                'semester' => $semester,
                'school_year' => $schoolYear,
                'is_locked' => 1,
                'locked_by' => $userId ?: null,
                'locked_at' => now(),
            ]);
        }

        return true;
    }

    public function lockAll(string $semester, string $schoolYear, ?int $userId): int
    {
        if ($semester === '' || $schoolYear === '') {
            throw new RuntimeException('Missing semester or school year.');
        }

        $sectionIds = ClassSection::query()
            ->select('class_section_id')
            ->groupBy('class_section_id')
            ->pluck('class_section_id')
            ->map(fn ($v) => (int) $v)
            ->filter(fn ($v) => $v > 0)
            ->values()
            ->all();

        if (empty($sectionIds)) {
            return 0;
        }

        $existingLocks = GradingLock::query()
            ->whereIn('class_section_id', $sectionIds)
            ->where('semester', $semester)
            ->where('school_year', $schoolYear)
            ->get();

        $existingBySection = [];
        foreach ($existingLocks as $row) {
            $sid = (int) $row->class_section_id;
            if ($sid > 0) {
                $existingBySection[$sid] = $row;
            }
        }

        $now = now();
        $insertRows = [];
        $count = 0;

        foreach ($sectionIds as $sid) {
            if (!empty($existingBySection[$sid])) {
                if ($existingBySection[$sid]->is_locked) {
                    continue;
                }
                $existingBySection[$sid]->update([
                    'is_locked' => 1,
                    'locked_by' => $userId ?: null,
                    'locked_at' => $now,
                ]);
                $count++;
                continue;
            }

            $insertRows[] = [
                'class_section_id' => $sid,
                'semester' => $semester,
                'school_year' => $schoolYear,
                'is_locked' => 1,
                'locked_by' => $userId ?: null,
                'locked_at' => $now,
                'created_at' => $now,
                'updated_at' => $now,
            ];
            $count++;
        }

        if (!empty($insertRows)) {
            GradingLock::query()->insert($insertRows);
        }

        return $count;
    }
}
