<?php

namespace App\Services\Events;

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

class EventChargeService
{
    public function __construct(private InvoiceGenerationService $invoiceGeneration)
    {
    }

    public function seedChargesForEvent(Event $event, string $schoolYear, string $semester, float $amount, int $actorId): array
    {
        $enrollments = Enrollment::query()
            ->select('enrollments.student_id', 'students.parent_id')
            ->join('students', 'students.id', '=', 'enrollments.student_id')
            ->where('enrollments.school_year', $schoolYear)
            ->whereIn('enrollments.enrollment_status', ['enrolled', 'payment pending'])
            ->get()
            ->map(fn ($row) => (array) $row)
            ->all();

        $parentIds = [];
        $created = 0;

        foreach ($enrollments as $row) {
            $studentId = (int) ($row['student_id'] ?? 0);
            $parentId = (int) ($row['parent_id'] ?? 0);
            if ($studentId <= 0 || $parentId <= 0) {
                continue;
            }

            $exists = EventCharges::query()
                ->where('event_id', $event->id)
                ->where('student_id', $studentId)
                ->where('school_year', $schoolYear)
                ->where('semester', $semester)
                ->first();

            if ($exists) {
                continue;
            }

            EventCharges::query()->create([
                'event_id' => (int) $event->id,
                'parent_id' => $parentId,
                'student_id' => $studentId,
                'participation' => 'yes',
                'charged' => $amount,
                'school_year' => $schoolYear,
                'semester' => $semester,
                'updated_by' => $actorId ?: null,
                'created_at' => utc_now(),
                'updated_at' => utc_now(),
            ]);

            $created++;
            $parentIds[] = $parentId;
        }

        $parentIds = array_values(array_unique($parentIds));
        foreach ($parentIds as $parentId) {
            $this->invoiceGeneration->generateInvoice((int) $parentId, $schoolYear);
        }

        return [
            'created' => $created,
            'parent_ids' => $parentIds,
        ];
    }

    public function updateParticipation(
        int $parentId,
        int $eventId,
        array $participations,
        string $schoolYear,
        string $semester,
        int $actorId
    ): array {
        $event = Event::getEvent($eventId, $schoolYear);
        if (!$event) {
            return ['ok' => false, 'message' => 'Event not found.'];
        }

        $created = 0;
        $updated = 0;
        $deleted = 0;

        foreach ($participations as $studentId => $value) {
            $studentId = (int) $studentId;
            if ($studentId <= 0) {
                continue;
            }

            $existing = EventCharges::query()->where([
                'parent_id' => $parentId,
                'student_id' => $studentId,
                'event_id' => $eventId,
                'school_year' => $schoolYear,
                'semester' => $semester,
            ])->first();

            if ($value === 'no') {
                if ($existing) {
                    $existing->delete();
                    $deleted++;
                }
                continue;
            }

            if ($existing) {
                $existing->update([
                    'participation' => 'yes',
                    'charged' => $event->amount,
                    'updated_by' => $actorId,
                    'updated_at' => utc_now(),
                ]);
                $updated++;
            } else {
                EventCharges::query()->create([
                    'parent_id' => $parentId,
                    'student_id' => $studentId,
                    'event_id' => $eventId,
                    'participation' => 'yes',
                    'charged' => $event->amount,
                    'school_year' => $schoolYear,
                    'semester' => $semester,
                    'created_by' => $actorId,
                    'updated_by' => $actorId,
                    'created_at' => utc_now(),
                    'updated_at' => utc_now(),
                ]);
                $created++;
            }
        }

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

        return [
            'ok' => true,
            'created' => $created,
            'updated' => $updated,
            'deleted' => $deleted,
        ];
    }

    public function deleteChargesForEvent(int $eventId): array
    {
        $charges = EventCharges::query()
            ->where('event_id', $eventId)
            ->get()
            ->map(fn ($row) => (array) $row)
            ->all();

        $parentIds = [];
        foreach ($charges as $charge) {
            EventCharges::query()->whereKey($charge['id'])->delete();
            $parentIds[] = (int) ($charge['parent_id'] ?? 0);
        }

        return [
            'parent_ids' => array_values(array_unique(array_filter($parentIds))),
        ];
    }
}
