<?php

namespace App\Services\Students;

use App\Models\Student;
use App\Models\StudentAllergy;
use App\Models\StudentMedicalCondition;
use Illuminate\Support\Facades\DB;

class StudentProfileService
{
    public function updateStudent(int $studentId, array $payload): array
    {
        $student = Student::query()->find($studentId);
        if (!$student) {
            return ['ok' => false, 'message' => 'Student not found.'];
        }

        $studentData = array_filter([
            'school_id' => $payload['school_id'] ?? null,
            'firstname' => $payload['firstname'] ?? null,
            'lastname' => $payload['lastname'] ?? null,
            'dob' => $payload['dob'] ?? null,
            'age' => $payload['age'] ?? null,
            'gender' => $payload['gender'] ?? null,
            'registration_grade' => $payload['registration_grade'] ?? null,
            'photo_consent' => $payload['photo_consent'] ?? null,
            'parent_id' => $payload['parent_id'] ?? null,
            'registration_date' => $payload['registration_date'] ?? null,
            'tuition_paid' => $payload['tuition_paid'] ?? null,
            'year_of_registration' => $payload['year_of_registration'] ?? null,
            'school_year' => $payload['school_year'] ?? null,
            'rfid_tag' => $payload['rfid_tag'] ?? null,
            'semester' => $payload['semester'] ?? null,
            'is_new' => $payload['is_new'] ?? null,
            'is_active' => $payload['is_active'] ?? null,
        ], static fn ($value) => $value !== null);

        $conditionsInput = (string) ($payload['medical_conditions'] ?? '');
        $allergiesInput = (string) ($payload['allergies'] ?? '');
        $conditions = $this->normalizeHealthList($conditionsInput);
        $allergies = $this->normalizeHealthList($allergiesInput);
        $shouldSyncConditions = array_key_exists('medical_conditions', $payload);
        $shouldSyncAllergies = array_key_exists('allergies', $payload);

        DB::transaction(function () use ($student, $studentData, $conditions, $allergies): void {
            if (!empty($studentData)) {
                $student->update($studentData);
            }

            if ($shouldSyncConditions) {
                $this->syncHealthList($student->id, StudentMedicalCondition::class, 'condition_name', $conditions);
            }

            if ($shouldSyncAllergies) {
                $this->syncHealthList($student->id, StudentAllergy::class, 'allergy', $allergies);
            }
        });

        return ['ok' => true, 'message' => 'Student updated successfully.'];
    }

    private function normalizeHealthList(string $value, int $maxLen = 100): array
    {
        $value = trim($value);
        if ($value === '') {
            return [];
        }

        $parts = preg_split('/[,\n;]+/u', $value, -1, PREG_SPLIT_NO_EMPTY) ?: [];
        $out = [];
        foreach ($parts as $part) {
            $item = trim(preg_replace('/\s+/u', ' ', $part));
            if ($item === '') {
                continue;
            }
            if (preg_match('/^(none|n\/a|na|null|nil|no)$/i', $item)) {
                continue;
            }
            $out[mb_strtolower($item, 'UTF-8')] = mb_substr($item, 0, $maxLen, 'UTF-8');
        }

        return array_values($out);
    }

    private function syncHealthList(int $studentId, string $modelClass, string $field, array $newValues): void
    {
        $model = new $modelClass();
        $rows = $model->newQuery()->where('student_id', $studentId)->get(['id', $field])->toArray();

        $current = [];
        $byId = [];
        foreach ($rows as $row) {
            $val = (string) ($row[$field] ?? '');
            $key = mb_strtolower(trim($val), 'UTF-8');
            if ($key === '') {
                continue;
            }
            $current[$key] = $val;
            $byId[$key] = (int) ($row['id'] ?? 0);
        }

        $incoming = [];
        foreach ($newValues as $value) {
            $key = mb_strtolower(trim($value), 'UTF-8');
            if ($key === '') {
                continue;
            }
            $incoming[$key] = $value;
        }

        $toDeleteKeys = array_diff(array_keys($current), array_keys($incoming));
        $toInsertKeys = array_diff(array_keys($incoming), array_keys($current));

        if (!empty($toDeleteKeys)) {
            $ids = array_map(fn ($key) => $byId[$key], $toDeleteKeys);
            if (!empty($ids)) {
                $model->newQuery()->whereIn('id', $ids)->delete();
            }
        }

        if (!empty($toInsertKeys)) {
            $batch = [];
            foreach ($toInsertKeys as $key) {
                $batch[] = [
                    'student_id' => $studentId,
                    $field => $incoming[$key],
                ];
            }
            if (!empty($batch)) {
                $model->newQuery()->insert($batch);
            }
        }
    }
}
