<?php

namespace App\Services\Incidents;

use App\Models\Incident;

class IncidentAnalysisService
{
    public function __construct(private IncidentLookupService $lookup)
    {
    }

    public function analyze(?string $schoolYear, ?string $semester): array
    {
        $builder = Incident::query()->orderBy('incident_datetime', 'DESC');
        if ($schoolYear !== null && $schoolYear !== '') {
            $builder->where('school_year', $schoolYear);
        }
        if ($semester !== null && $semester !== '') {
            $builder->where('semester', $semester);
        }

        $incidents = $builder->get()->map(fn ($row) => $row->toArray())->all();
        if (empty($incidents)) {
            return [];
        }

        $gradeMap = $this->lookup->gradeNameMap(array_column($incidents, 'grade'));
        $students = [];

        foreach ($incidents as $incident) {
            $studentId = (string) ($incident['student_id'] ?? '');
            $studentName = (string) ($incident['student_name'] ?? '');
            $studentKey = $studentId !== '' ? 'id:' . $studentId : 'name:' . strtolower(trim($studentName));

            $gradeValue = $incident['grade'] ?? '';
            $gradeLabel = $gradeValue;
            if (is_numeric($gradeValue)) {
                $gradeLabel = $gradeMap[(int) $gradeValue] ?? (string) $gradeValue;
            }

            if (!isset($students[$studentKey])) {
                $students[$studentKey] = [
                    'student_id' => $studentId,
                    'student_name' => $studentName,
                    'grade' => (string) $gradeLabel,
                    'total' => 0,
                    'open' => 0,
                    'closed' => 0,
                    'canceled' => 0,
                    'last_incident' => null,
                    'logs' => [],
                ];
            }

            $students[$studentKey]['total'] += 1;

            $state = (string) ($incident['incident_state'] ?? '');
            if ($state === 'Open') {
                $students[$studentKey]['open'] += 1;
            } elseif ($state === 'Closed') {
                $students[$studentKey]['closed'] += 1;
            } elseif ($state === 'Canceled') {
                $students[$studentKey]['canceled'] += 1;
            }

            if ($students[$studentKey]['last_incident'] === null) {
                $students[$studentKey]['last_incident'] = $this->formatIncidentDate($incident['incident_datetime'] ?? null);
            }

            $students[$studentKey]['logs'][] = [
                'incident' => $incident['incident'] ?? '',
                'incident_state' => $state,
                'incident_datetime' => $this->formatIncidentDate($incident['incident_datetime'] ?? null),
                'open_description' => $incident['open_description'] ?? null,
                'close_description' => $incident['close_description'] ?? null,
                'cancel_description' => $incident['cancel_description'] ?? null,
                'action_taken' => $incident['action_taken'] ?? null,
            ];
        }

        $studentRows = array_values($students);
        usort($studentRows, function ($a, $b) {
            if ($a['total'] === $b['total']) {
                return strcasecmp($a['student_name'], $b['student_name']);
            }
            return $b['total'] <=> $a['total'];
        });

        return $studentRows;
    }

    private function formatIncidentDate(mixed $value): ?string
    {
        if ($value === null || $value === '') {
            return null;
        }

        if ($value instanceof \DateTimeInterface) {
            return $value->format('Y-m-d H:i:s');
        }

        $raw = (string) $value;
        $ts = strtotime($raw);
        if ($ts !== false) {
            return date('Y-m-d H:i:s', $ts);
        }

        return $raw;
    }
}
