<?php

namespace App\Services\Attendance;

use App\Models\AttendanceData;
use App\Models\Student;
use RuntimeException;

class StudentAttendanceWriterService
{
    public function __construct(
        protected AttendanceData $attendanceData,
        protected Student $student,
        protected AttendanceRecordSyncService $attendanceRecordSyncService,
    ) {}

    public function updateAttendanceData(
        int $attendanceId,
        string $newStatus,
        ?string $newReason = null,
        ?string $reported = null,
        ?int $userId = null
    ): void {
        $payload = [
            'status' => strtolower($newStatus),
            'reason' => $newReason ?: null,
            'modified_by' => $userId,
            'updated_at' => now(),
        ];

        if ($reported !== null) {
            $payload['is_reported'] = in_array(strtolower($reported), ['yes', 'no'], true)
                ? strtolower($reported)
                : 'no';
        }

        AttendanceData::query()->whereKey($attendanceId)->update($payload);
    }

    public function insertAttendanceData(
        int $classSectionId,
        int $studentId,
        string $studentSchoolId,
        string $status,
        ?string $reason,
        string $reported,
        string $semester,
        string $schoolYear,
        string $date,
        int $classId,
        ?int $userId = null
    ): void {
        AttendanceData::query()->create([
            'class_id' => $classId,
            'class_section_id' => $classSectionId,
            'student_id' => $studentId,
            'school_id' => $studentSchoolId,
            'status' => strtolower($status),
            'reason' => $reason ?: null,
            'is_reported' => $reported,
            'is_notified' => 'no',
            'semester' => $semester,
            'school_year' => $schoolYear,
            'date' => $date,
            'modified_by' => $userId,
            'created_at' => now(),
            'updated_at' => now(),
        ]);
    }

    public function resolveStudentSchoolId(int $studentId, ?string $studentSchoolId = null): string
    {
        $studentSchoolId = trim((string)$studentSchoolId);

        if ($studentSchoolId !== '') {
            return $studentSchoolId;
        }

        $studentRow = $this->student->query()->select('school_id')->find($studentId);

        if (!$studentRow || empty($studentRow->school_id)) {
            throw new RuntimeException('Student school ID not found.');
        }

        return (string)$studentRow->school_id;
    }

    public function saveOrUpdateStudentAttendance(array $payload): array
    {
        $classSectionId = (int)$payload['class_section_id'];
        $studentId = (int)$payload['student_id'];
        $studentSchoolId = $this->resolveStudentSchoolId($studentId, $payload['school_id'] ?? null);
        $status = strtolower((string)$payload['status']);
        $reason = $payload['reason'] ?? null;
        $reported = $payload['is_reported'] ?? null;
        $semester = (string)$payload['semester'];
        $schoolYear = (string)$payload['school_year'];
        $date = (string)$payload['date'];
        $classId = (int)$payload['class_id'];
        $userId = $payload['user_id'] ?? null;

        $existing = AttendanceData::query()
            ->where('student_id', $studentId)
            ->whereDate('date', $date)
            ->where('semester', $semester)
            ->where('school_year', $schoolYear)
            ->first();

        if ($existing) {
            $oldStatus = $existing->status;

            $this->updateAttendanceData(
                (int)$existing->id,
                $status,
                $reason,
                $reported,
                $userId
            );

            if ($status !== $oldStatus) {
                $this->attendanceRecordSyncService->updateAttendanceRecord(
                    $studentId,
                    $studentSchoolId,
                    $status,
                    $semester,
                    $schoolYear,
                    $oldStatus,
                    $userId
                );
            }

            return [
                'mode' => 'updated',
                'attendance_id' => (int)$existing->id,
                'old_status' => $oldStatus,
                'new_status' => $status,
                'school_id' => $studentSchoolId,
            ];
        }

        $this->insertAttendanceData(
            $classSectionId,
            $studentId,
            $studentSchoolId,
            $status,
            $reason,
            $reported ?? 'no',
            $semester,
            $schoolYear,
            $date,
            $classId,
            $userId
        );

        $this->attendanceRecordSyncService->addNewAttendanceRecord(
            $classSectionId,
            $studentId,
            $studentSchoolId,
            $status,
            $semester,
            $schoolYear,
            $userId
        );

        $created = AttendanceData::query()
            ->where('student_id', $studentId)
            ->whereDate('date', $date)
            ->where('semester', $semester)
            ->where('school_year', $schoolYear)
            ->latest('id')
            ->first();

        return [
            'mode' => 'created',
            'attendance_id' => (int)($created->id ?? 0),
            'old_status' => null,
            'new_status' => $status,
            'school_id' => $studentSchoolId,
        ];
    }
}