<?php

namespace App\Services\Parents;

use App\Models\Event;
use App\Models\EventCharges;
use App\Models\Enrollment;
use App\Models\Student;
use App\Services\Invoices\InvoiceGenerationService;

class ParentEventParticipationService
{
    public function __construct(
        private ParentConfigService $configService,
        private InvoiceGenerationService $invoiceGeneration
    ) {
    }

    public function overview(int $parentId): array
    {
        $context = $this->configService->context();
        $schoolYear = $context['school_year'];
        $semester = $context['semester'];

        $activeEvents = Event::getActiveEvents($schoolYear, $semester) ?? [];
        $chargesList = EventCharges::getChargesWithEventInfo($parentId, $schoolYear) ?? [];

        $charges = [];
        foreach ($chargesList as $charge) {
            $key = $charge['student_id'] . ':' . $charge['event_id'];
            $charges[$key] = [
                'participation' => $charge['participation'],
                'date' => $charge['updated_at'] ?? $charge['created_at'],
            ];
        }

        $students = Enrollment::getEnrolledStudents($parentId, $schoolYear);

        return [
            'activeEvents' => $activeEvents,
            'charges' => $charges,
            'yourStudents' => $students,
        ];
    }

    public function updateParticipation(int $parentId, array $participations): void
    {
        $context = $this->configService->context();
        $schoolYear = $context['school_year'];
        $semester = $context['semester'];

        // First pass: parse + validate every `student_id:event_id` key and
        // collect the student ids that this parent actually owns. This stops
        // a parent from creating or deleting charges on another family's
        // students by manipulating the participation keys.
        $parsed = [];
        $candidateStudentIds = [];
        foreach ($participations as $key => $value) {
            $parts = explode(':', (string) $key, 2);
            if (count($parts) !== 2 || ! ctype_digit($parts[0]) || ! ctype_digit($parts[1])) {
                continue;
            }

            $studentId = (int) $parts[0];
            $eventId = (int) $parts[1];
            if ($studentId <= 0 || $eventId <= 0) {
                continue;
            }

            $normalized = strtolower(trim((string) $value));
            if (! in_array($normalized, ['yes', 'no'], true)) {
                continue;
            }

            $parsed[] = [
                'student_id' => $studentId,
                'event_id' => $eventId,
                'value' => $normalized,
            ];
            $candidateStudentIds[$studentId] = true;
        }

        if ($parsed === []) {
            return;
        }

        $ownedIds = Student::query()
            ->where('parent_id', $parentId)
            ->whereIn('id', array_keys($candidateStudentIds))
            ->pluck('id')
            ->map(fn ($id) => (int) $id)
            ->all();
        $ownedSet = array_flip($ownedIds);

        foreach ($parsed as $row) {
            if (! isset($ownedSet[$row['student_id']])) {
                continue;
            }

            $existing = EventCharges::query()
                ->where('parent_id', $parentId)
                ->where('student_id', $row['student_id'])
                ->where('event_id', $row['event_id'])
                ->first();

            if ($row['value'] === 'no') {
                if ($existing) {
                    $existing->delete();
                }
                continue;
            }

            if ($existing) {
                $existing->update(['participation' => $row['value']]);
            } else {
                $event = Event::getEvent($row['event_id'], $schoolYear);
                EventCharges::query()->create([
                    'parent_id' => $parentId,
                    'student_id' => $row['student_id'],
                    'event_id' => $row['event_id'],
                    'participation' => $row['value'],
                    'charged' => $event['amount'] ?? 0,
                    'school_year' => $schoolYear,
                    'semester' => $semester,
                    'updated_by' => $parentId,
                ]);
            }
        }

        $this->invoiceGeneration->generateInvoice($parentId, $schoolYear);
    }
}
