<?php

namespace App\Modules\Academic\Controllers;

use App\Core\BaseApiController;
use App\Modules\Academic\Models\StudentModel;
use App\Modules\Academic\Models\ClassModel;
use CodeIgniter\HTTP\ResponseInterface;

/**
 * Student CRUD API (ADMIN only).
 */
class StudentController extends BaseApiController
{
    /**
     * GET /api/academic/students
     * Query: class_id (optional), search (optional), unmapped_only (optional), page (default 1), per_page (default 25).
     */
    public function index(): ResponseInterface
    {
        $classId      = $this->request->getGet('class_id');
        $search       = $this->request->getGet('search');
        $search       = is_string($search) ? trim($search) : '';
        $unmappedOnly = $this->request->getGet('unmapped_only') === '1' || $this->request->getGet('unmapped_only') === 'true';
        $page         = max(1, (int) ($this->request->getGet('page') ?? 1));
        $perPage      = max(5, min(100, (int) ($this->request->getGet('per_page') ?? 20)));

        $db = \Config\Database::connect();
        $builder = $db->table('students')
            ->select('students.id, students.nisn, students.name, students.gender, students.class_id, students.is_active,
                classes.grade, classes.major, classes.name AS class_name')
            ->join('classes', 'classes.id = students.class_id', 'left')
            ->orderBy('students.name', 'ASC');

        if ($unmappedOnly) {
            $builder->where('students.class_id', null);
        } elseif ($classId !== null && $classId !== '') {
            $builder->where('students.class_id', (int) $classId);
        }
        if ($search !== '') {
            $builder->groupStart()
                ->like('students.name', $search)
                ->orLike('students.nisn', $search)
                ->groupEnd();
        }

        $total = $builder->countAllResults(false);
        $rows  = $builder->limit($perPage, ($page - 1) * $perPage)->get()->getResultArray();

        $data = array_map(static function ($r) {
            $grade   = $r['grade'] !== null ? trim((string) $r['grade']) : '';
            $major   = $r['major'] !== null ? trim((string) $r['major']) : '';
            $cName   = $r['class_name'] !== null ? trim((string) $r['class_name']) : '';
            $parts   = array_filter([$grade, $major, $cName], static fn ($v) => $v !== '');
            $fullLabel = $parts !== [] ? implode(' ', $parts) : null;

            return [
                'id'          => (int) $r['id'],
                'nisn'        => (string) $r['nisn'],
                'name'        => (string) $r['name'],
                'gender'      => $r['gender'] !== null ? (string) $r['gender'] : null,
                'class_id'    => $r['class_id'] !== null ? (int) $r['class_id'] : null,
                'class_label' => $fullLabel,
                'is_active'   => (int) ($r['is_active'] ?? 1),
            ];
        }, $rows);

        $totalPages = $total > 0 ? (int) ceil($total / $perPage) : 0;
        $meta = [
            'total'       => $total,
            'page'        => $page,
            'per_page'    => $perPage,
            'total_pages' => $totalPages,
        ];

        return $this->successResponse($data, 'Students', $meta);
    }

    /**
     * POST /api/academic/students
     */
    public function create(): ResponseInterface
    {
        $payload = $this->request->getJSON(true) ?? [];
        $data    = $this->payloadToStudentData($payload);

        $model = new StudentModel();
        if (! $model->validate($data)) {
            return $this->errorResponse(
                implode(' ', $model->errors()),
                $model->errors(),
                null,
                ResponseInterface::HTTP_UNPROCESSABLE_ENTITY
            );
        }

        $id = $model->insert($data);
        if ($id === false) {
            return $this->errorResponse('Gagal menyimpan siswa', null, null, ResponseInterface::HTTP_INTERNAL_SERVER_ERROR);
        }

        $row = $model->find($id);
        return $this->successResponse($this->rowToResponse($row), 'Siswa berhasil ditambahkan', null, ResponseInterface::HTTP_CREATED);
    }

    /**
     * PUT /api/academic/students/{id}
     */
    public function update(int $id): ResponseInterface
    {
        $model = new StudentModel();
        $row   = $model->find($id);
        if (! $row) {
            return $this->errorResponse('Siswa tidak ditemukan', null, null, ResponseInterface::HTTP_NOT_FOUND);
        }

        $payload = $this->request->getJSON(true) ?? [];
        $data    = $this->payloadToStudentData($payload, $row);

        if (! $model->validate(array_merge(['id' => $id], $data))) {
            return $this->errorResponse(
                implode(' ', $model->errors()),
                $model->errors(),
                null,
                ResponseInterface::HTTP_UNPROCESSABLE_ENTITY
            );
        }

        if ($model->update($id, $data) === false) {
            return $this->errorResponse('Gagal mengubah siswa', null, null, ResponseInterface::HTTP_INTERNAL_SERVER_ERROR);
        }

        $updated = $model->find($id);
        return $this->successResponse($this->rowToResponse($updated), 'Siswa berhasil diubah');
    }

    /**
     * DELETE /api/academic/students/{id}
     */
    public function delete(int $id): ResponseInterface
    {
        $model = new StudentModel();
        if (! $model->find($id)) {
            return $this->errorResponse('Siswa tidak ditemukan', null, null, ResponseInterface::HTTP_NOT_FOUND);
        }
        if ($model->delete($id) === false) {
            return $this->errorResponse('Gagal menghapus siswa', null, null, ResponseInterface::HTTP_INTERNAL_SERVER_ERROR);
        }
        return $this->successResponse(null, 'Siswa berhasil dihapus');
    }

    private function payloadToStudentData(array $payload, $existing = null): array
    {
        $classId = isset($payload['class_id']) && $payload['class_id'] !== '' && $payload['class_id'] !== null
            ? (int) $payload['class_id']
            : null;
        $gender = isset($payload['gender']) && in_array($payload['gender'], ['L', 'P'], true)
            ? $payload['gender']
            : ($existing && isset($existing->gender) ? $existing->gender : null);
        $isActive = array_key_exists('is_active', $payload)
            ? (int) (bool) $payload['is_active']
            : ($existing && isset($existing->is_active) ? (int) $existing->is_active : 1);

        return [
            'nisn'     => trim($payload['nisn'] ?? $existing->nisn ?? ''),
            'name'     => trim($payload['name'] ?? $existing->name ?? ''),
            'gender'   => $gender,
            'class_id' => $classId,
            'is_active'=> $isActive,
        ];
    }

    private function rowToResponse($row): array
    {
        $classId   = $row->class_id ?? null;
        $classLabel = null;
        if ($classId !== null) {
            $classModel = new ClassModel();
            $c = $classModel->find($classId);
            if ($c) {
                $classLabel = trim($c->grade . ' ' . $c->major . ' ' . $c->name) ?: (string) $c->name;
            }
        }

        return [
            'id'          => (int) $row->id,
            'nisn'        => (string) $row->nisn,
            'name'        => (string) $row->name,
            'gender'      => $row->gender !== null ? (string) $row->gender : null,
            'class_id'    => $classId !== null ? (int) $classId : null,
            'class_label' => $classLabel,
            'is_active'   => (int) ($row->is_active ?? 1),
        ];
    }
}
