<?php

namespace App\Services\Parents;

use App\Models\ClassProgressReport;
use App\Services\ClassProgress\ClassProgressQueryService;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;

/**
 * legacy {@see \App\Controllers\ParentProgressController} read-side logic.
 */
class ParentProgressQueryService
{
    public function __construct(
        private ClassProgressQueryService $classProgressQuery,
    ) {}

    /**
     * legacy `getParentStudents` — one row per distinct student (latest enrollment ordering).
     *
     * @return list<array<string, mixed>>
     */
    public function parentStudents(int $parentId): array
    {
        if ($parentId <= 0) {
            return [];
        }

        $rows = DB::table('enrollments as e')
            ->select(
                'e.student_id',
                'e.class_section_id',
                'e.updated_at',
                'e.created_at',
                's.firstname',
                's.lastname',
                'cs.class_section_name',
            )
            ->join('students as s', 's.id', '=', 'e.student_id')
            ->leftJoin('classSection as cs', 'cs.class_section_id', '=', 'e.class_section_id')
            ->where('e.parent_id', $parentId)
            ->where('e.is_withdrawn', 0)
            ->orderByDesc('e.updated_at')
            ->orderByDesc('e.created_at')
            ->get();

        $students = [];
        foreach ($rows as $row) {
            $arr = (array) $row;
            $studentId = (int) ($arr['student_id'] ?? 0);
            if ($studentId === 0 || isset($students[$studentId])) {
                continue;
            }
            $students[$studentId] = $arr;
        }

        return array_values($students);
    }

    /**
     * legacy `getParentSectionIds`.
     *
     * @return list<int>
     */
    public function parentSectionIds(int $parentId): array
    {
        if ($parentId <= 0) {
            return [];
        }

        $ids = DB::table('enrollments')
            ->where('parent_id', $parentId)
            ->where('is_withdrawn', 0)
            ->whereNotNull('class_section_id')
            ->distinct()
            ->pluck('class_section_id')
            ->map(fn ($id) => (int) $id)
            ->filter(fn ($id) => $id > 0)
            ->unique()
            ->values()
            ->all();

        return array_values($ids);
    }

    public function parentCanAccessSection(int $parentUserId, ?int $classSectionId): bool
    {
        if (! $classSectionId) {
            return false;
        }

        return in_array((int) $classSectionId, $this->parentSectionIds($parentUserId), true);
    }

    /**
     * Progress reports visible to the parent (all teachers) for allowed sections.
     *
     * @param  list<int>  $sectionIds
     */
    public function reportsForSections(array $sectionIds): Collection
    {
        $sectionIds = array_values(array_filter(array_map('intval', $sectionIds)));
        if ($sectionIds === []) {
            return collect();
        }

        return ClassProgressReport::query()
            ->select('class_progress_reports.*')
            ->addSelect([
                'cs.class_section_name',
                DB::raw('CONCAT(IFNULL(u.firstname, ""), " ", IFNULL(u.lastname, "")) AS teacher_name'),
            ])
            ->leftJoin('classSection as cs', 'cs.class_section_id', '=', 'class_progress_reports.class_section_id')
            ->leftJoin('users as u', 'u.id', '=', 'class_progress_reports.teacher_id')
            ->whereIn('class_progress_reports.class_section_id', $sectionIds)
            ->orderByDesc('class_progress_reports.week_start')
            ->get();
    }

    /**
     * legacy `groupReportsByWeek` — keys `"{week_start}:{class_section_id}"`.
     *
     * @param  iterable<int, ClassProgressReport>  $rows
     * @return array<string, array<string, mixed>>
     */
    public function groupReportsByWeek(iterable $rows): array
    {
        $statusOptions = (array) config('progress.status_options', []);
        $reportGroups = [];

        foreach ($rows as $row) {
            $statusLabel = $statusOptions[$row->status] ?? 'Unknown';
            $row->setAttribute('status_label', $statusLabel);

            $weekStart = $row->week_start instanceof \Carbon\CarbonInterface
                ? $row->week_start->format('Y-m-d')
                : (string) $row->week_start;
            $sectionId = (int) $row->class_section_id;
            if ($weekStart === '' || $sectionId === 0) {
                continue;
            }

            $key = $weekStart.':'.$sectionId;
            if (! isset($reportGroups[$key])) {
                $reportGroups[$key] = [
                    'week_start' => $weekStart,
                    'week_end' => $row->week_end instanceof \Carbon\CarbonInterface
                        ? $row->week_end->format('Y-m-d')
                        : (string) ($row->week_end ?? ''),
                    'class_section_name' => $row->class_section_name ?? '',
                    'class_section_id' => $sectionId,
                    'reports' => [],
                ];
            }

            $subject = (string) ($row->subject ?? '');
            if ($subject === '') {
                continue;
            }

            $reportGroups[$key]['reports'][$subject] = (new \App\Http\Resources\ClassProgress\ClassProgressReportResource($row))->toArray(request());
        }

        return $reportGroups;
    }

    /**
     * Weekly batch for a section/week (legacy parent `view`, all subjects).
     *
     * @return list<ClassProgressReport>
     */
    public function weeklyReportsForSectionWeek(int $classSectionId, string $weekStartYmd): array
    {
        return ClassProgressReport::query()
            ->with(['classSection', 'teacher'])
            ->where('class_section_id', $classSectionId)
            ->whereDate('week_start', $weekStartYmd)
            ->orderBy('subject')
            ->get()
            ->all();
    }

    /**
     * @return array<int, list<array{id:int,name:string}>>
     */
    public function attachmentMapForReportIds(array $reportIds): array
    {
        return $this->classProgressQuery->attachmentMap($reportIds);
    }
}
