<?php

namespace App\Services\School;

use App\Models\AcademicYear;
use App\Models\Student;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
use InvalidArgumentException;

class StudentImportExportService
{
    /**
     * @return \Symfony\Component\HttpFoundation\StreamedResponse
     */
    public function exportCsv()
    {
        $filename = 'students-'.now()->format('Y-m-d').'.csv';

        return response()->streamDownload(function () {
            $handle = fopen('php://output', 'w');
            fputcsv($handle, [
                'admission_number', 'first_name', 'last_name', 'other_names', 'gender',
                'email', 'phone', 'date_of_birth', 'admission_date', 'status', 'leadership_role',
            ]);

            Student::query()->orderBy('last_name')->chunk(200, function ($students) use ($handle) {
                foreach ($students as $student) {
                    fputcsv($handle, [
                        $student->admission_number,
                        $student->first_name,
                        $student->last_name,
                        $student->other_names,
                        $student->gender,
                        $student->email,
                        $student->phone,
                        optional($student->date_of_birth)->format('Y-m-d'),
                        optional($student->admission_date)->format('Y-m-d'),
                        $student->status,
                        $student->leadership_role,
                    ]);
                }
            });

            fclose($handle);
        }, $filename, ['Content-Type' => 'text/csv']);
    }

    /**
     * @return array{created: int, updated: int, errors: list<string>}
     */
    public function importCsv(UploadedFile $file): array
    {
        $handle = fopen($file->getRealPath(), 'r');
        if ($handle === false) {
            throw new InvalidArgumentException('Unable to read CSV file.');
        }

        $header = fgetcsv($handle);
        $created = 0;
        $updated = 0;
        $errors = [];
        $rowNum = 1;
        $yearId = AcademicYear::query()->where('is_current', true)->value('id');

        while (($row = fgetcsv($handle)) !== false) {
            $rowNum++;
            if (trim(implode('', $row)) === '') {
                continue;
            }

            $data = array_combine($header, $row);
            if (! $data || empty($data['first_name']) || empty($data['last_name'])) {
                $errors[] = "Row {$rowNum}: missing first_name or last_name";

                continue;
            }

            try {
                $attrs = [
                    'first_name' => $data['first_name'],
                    'last_name' => $data['last_name'],
                    'other_names' => $data['other_names'] ?? null,
                    'gender' => $data['gender'] ?? null,
                    'email' => $data['email'] ?? null,
                    'phone' => $data['phone'] ?? null,
                    'date_of_birth' => ! empty($data['date_of_birth']) ? $data['date_of_birth'] : null,
                    'admission_date' => ! empty($data['admission_date']) ? $data['admission_date'] : now()->toDateString(),
                    'status' => $data['status'] ?? 'active',
                    'leadership_role' => $data['leadership_role'] ?? null,
                    'academic_year_id' => $yearId,
                ];

                if (! empty($data['admission_number'])) {
                    $student = Student::query()->updateOrCreate(
                        ['admission_number' => $data['admission_number']],
                        $attrs
                    );
                    $student->wasRecentlyCreated ? $created++ : $updated++;
                } else {
                    Student::query()->create(array_merge($attrs, [
                        'admission_number' => app(AdmissionNumberGenerator::class)->generate(),
                    ]));
                    $created++;
                }
            } catch (\Throwable $e) {
                $errors[] = "Row {$rowNum}: {$e->getMessage()}";
            }
        }

        fclose($handle);

        return compact('created', 'updated', 'errors');
    }

    public function storeDocument(Student $student, UploadedFile $file, string $title, int $userId): \App\Models\StudentDocument
    {
        $path = $file->store('student-documents/'.$student->id, 'public');

        return $student->documents()->create([
            'title' => $title,
            'file_path' => $path,
            'file_name' => $file->getClientOriginalName(),
            'mime_type' => $file->getMimeType(),
            'uploaded_by' => $userId,
        ]);
    }
}
