<?php

namespace App\Modules\Parent\Controllers;

use App\Core\BaseApiController;
use App\Modules\Auth\Entities\Role;
use App\Modules\Auth\Services\AuthService;
use App\Modules\Attendance\Models\AttendanceSessionModel;
use App\Modules\Discipline\Models\DisciplineLevelModel;
use App\Modules\Discipline\Models\StudentViolationModel;
use App\Modules\Notification\Models\ParentModel;
use App\Modules\Notification\Models\StudentParentModel;
use CodeIgniter\HTTP\ResponseInterface;

/**
 * Parent Portal API Controller
 * 
 * Read-only APIs for parents to view their children's data.
 * Requires ORANG_TUA role.
 */
class ParentController extends BaseApiController
{
    protected AuthService $authService;
    protected ParentModel $parentModel;
    protected StudentParentModel $studentParentModel;

    public function __construct()
    {
        $this->authService       = new AuthService();
        $this->parentModel       = new ParentModel();
        $this->studentParentModel = new StudentParentModel();
    }

    /**
     * GET /api/parent/children
     * List all children linked to the current parent user.
     */
    public function children(): ResponseInterface
    {
        $user = $this->authService->currentUser();
        if (!$user) {
            return $this->errorResponse('Unauthorized', null, null, ResponseInterface::HTTP_UNAUTHORIZED);
        }

        $roleCodes = array_column($user['roles'], 'role_code');
        if (!in_array(Role::CODE_ORANG_TUA, $roleCodes, true)) {
            return $this->errorResponse('Forbidden: Parent access only', null, null, ResponseInterface::HTTP_FORBIDDEN);
        }

        // Find parent record linked to this user
        $parent = $this->parentModel->where('user_id', $user['id'])->first();
        if (!$parent) {
            return $this->successResponse([], 'No children found');
        }

        // Get all students linked to this parent
        $db = \Config\Database::connect();
        $children = $db->table('student_parents AS sp')
            ->select('s.id, s.nisn, s.name, s.gender, s.class_id,
                c.grade AS class_grade, c.major AS class_major, c.name AS class_name,
                sp.relationship')
            ->join('students AS s', 's.id = sp.student_id', 'inner')
            ->join('classes AS c', 'c.id = s.class_id', 'left')
            ->where('sp.parent_id', $parent->id)
            ->where('s.is_active', 1)
            ->orderBy('c.grade', 'ASC')
            ->orderBy('c.major', 'ASC')
            ->orderBy('c.name', 'ASC')
            ->orderBy('s.name', 'ASC')
            ->get()
            ->getResultArray();

        $data = array_map(function ($row) {
            $classLabel = null;
            if ($row['class_grade'] !== null || $row['class_major'] !== null || $row['class_name'] !== null) {
                $parts = array_filter([
                    trim((string) ($row['class_grade'] ?? '')),
                    trim((string) ($row['class_major'] ?? '')),
                    trim((string) ($row['class_name'] ?? '')),
                ]);
                $classLabel = implode(' ', $parts);
            }

            return [
                'id'           => (int) $row['id'],
                'nisn'         => $row['nisn'],
                'name'         => $row['name'],
                'gender'       => $row['gender'],
                'class_id'     => $row['class_id'] !== null ? (int) $row['class_id'] : null,
                'class_label'  => $classLabel,
                'relationship' => $row['relationship'],
            ];
        }, $children);

        return $this->successResponse($data, 'Children list');
    }

    /**
     * GET /api/parent/attendance?student_id=&from=&to=
     * Get attendance history for a specific child.
     */
    public function attendance(): ResponseInterface
    {
        $user = $this->authService->currentUser();
        if (!$user) {
            return $this->errorResponse('Unauthorized', null, null, ResponseInterface::HTTP_UNAUTHORIZED);
        }

        $roleCodes = array_column($user['roles'], 'role_code');
        if (!in_array(Role::CODE_ORANG_TUA, $roleCodes, true)) {
            return $this->errorResponse('Forbidden: Parent access only', null, null, ResponseInterface::HTTP_FORBIDDEN);
        }

        $studentId = (int) $this->request->getGet('student_id');
        $from      = $this->request->getGet('from');
        $to        = $this->request->getGet('to');

        if ($studentId <= 0) {
            return $this->errorResponse('student_id parameter is required', null, null, ResponseInterface::HTTP_BAD_REQUEST);
        }

        // Verify that this student belongs to the current parent
        $parent = $this->parentModel->where('user_id', $user['id'])->first();
        if (!$parent) {
            return $this->errorResponse('Parent record not found', null, null, ResponseInterface::HTTP_NOT_FOUND);
        }

        $hasAccess = $this->studentParentModel
            ->where('parent_id', $parent->id)
            ->where('student_id', $studentId)
            ->first();

        if (!$hasAccess) {
            return $this->errorResponse('Access denied: Student not linked to this parent', null, null, ResponseInterface::HTTP_FORBIDDEN);
        }

        // Query attendance sessions
        $db = \Config\Database::connect();
        $builder = $db->table('attendance_sessions AS att')
            ->select('att.id, att.student_id, att.schedule_id, att.attendance_date, att.checkin_at, att.status,
                sch.day_of_week, sch.lesson_slot_id, sch.subject_id, sch.teacher_user_id,
                ls.start_time, ls.end_time,
                sub.name AS subject_name,
                u.name AS teacher_name')
            ->join('schedules AS sch', 'sch.id = att.schedule_id', 'left')
            ->join('lesson_slots AS ls', 'ls.id = sch.lesson_slot_id', 'left')
            ->join('subjects AS sub', 'sub.id = sch.subject_id', 'left')
            ->join('users AS u', 'u.id = sch.teacher_user_id', 'left')
            ->where('att.student_id', $studentId)
            ->orderBy('att.attendance_date', 'DESC')
            ->orderBy('att.checkin_at', 'DESC');

        if ($from) {
            $builder->where('att.attendance_date >=', $from);
        }
        if ($to) {
            $builder->where('att.attendance_date <=', $to);
        }

        $rows = $builder->get()->getResultArray();

        $data = array_map(function ($row) {
            return [
                'id'              => (int) $row['id'],
                'student_id'      => (int) $row['student_id'],
                'schedule_id'     => $row['schedule_id'] !== null ? (int) $row['schedule_id'] : null,
                'attendance_date' => $row['attendance_date'],
                'checkin_at'      => $row['checkin_at'],
                'status'          => $row['status'],
                'subject_name'    => $row['subject_name'],
                'teacher_name'    => $row['teacher_name'],
                'start_time'      => $row['start_time'],
                'end_time'        => $row['end_time'],
            ];
        }, $rows);

        return $this->successResponse($data, 'Attendance history');
    }

    /**
     * GET /api/parent/discipline?student_id=
     * Get discipline data (total points, level, violation history) for a specific child.
     */
    public function discipline(): ResponseInterface
    {
        $user = $this->authService->currentUser();
        if (!$user) {
            return $this->errorResponse('Unauthorized', null, null, ResponseInterface::HTTP_UNAUTHORIZED);
        }

        $roleCodes = array_column($user['roles'], 'role_code');
        if (!in_array(Role::CODE_ORANG_TUA, $roleCodes, true)) {
            return $this->errorResponse('Forbidden: Parent access only', null, null, ResponseInterface::HTTP_FORBIDDEN);
        }

        $studentId = (int) $this->request->getGet('student_id');
        if ($studentId <= 0) {
            return $this->errorResponse('student_id parameter is required', null, null, ResponseInterface::HTTP_BAD_REQUEST);
        }

        // Verify that this student belongs to the current parent
        $parent = $this->parentModel->where('user_id', $user['id'])->first();
        if (!$parent) {
            return $this->errorResponse('Parent record not found', null, null, ResponseInterface::HTTP_NOT_FOUND);
        }

        $hasAccess = $this->studentParentModel
            ->where('parent_id', $parent->id)
            ->where('student_id', $studentId)
            ->first();

        if (!$hasAccess) {
            return $this->errorResponse('Access denied: Student not linked to this parent', null, null, ResponseInterface::HTTP_FORBIDDEN);
        }

        // Get total points from violations
        $db = \Config\Database::connect();
        $totalPointsResult = $db->table('student_violations AS sv')
            ->select('COALESCE(SUM(v.score), 0) AS total_points, COUNT(sv.id) AS violation_count')
            ->join('violations AS v', 'v.id = sv.violation_id', 'inner')
            ->where('sv.student_id', $studentId)
            ->where('v.is_active', 1)
            ->get()
            ->getRowArray();

        $totalPoints = (int) ($totalPointsResult['total_points'] ?? 0);
        $violationCount = (int) ($totalPointsResult['violation_count'] ?? 0);

        // Get discipline level based on total points
        $levelModel = new DisciplineLevelModel();
        $level = $levelModel
            ->where('is_active', 1)
            ->where('min_score <=', $totalPoints)
            ->where('max_score >=', $totalPoints)
            ->first();

        $levelData = null;
        if ($level) {
            $levelData = [
                'title'        => $level['title'],
                'school_action' => $level['school_action'],
                'executor'     => $level['executor'],
            ];
        }

        // Get violation history
        $violationModel = new StudentViolationModel();
        $violations = $db->table('student_violations AS sv')
            ->select('sv.id, sv.violation_id, sv.occurred_at, sv.notes,
                v.title AS violation_title, v.score AS violation_score,
                vc.code AS category_code, vc.name AS category_name')
            ->join('violations AS v', 'v.id = sv.violation_id', 'inner')
            ->join('violation_categories AS vc', 'vc.id = v.category_id', 'left')
            ->where('sv.student_id', $studentId)
            ->orderBy('sv.occurred_at', 'DESC')
            ->get()
            ->getResultArray();

        $violationHistory = array_map(function ($row) {
            return [
                'id'              => (int) $row['id'],
                'violation_id'    => (int) $row['violation_id'],
                'category_code'   => $row['category_code'],
                'category_name'   => $row['category_name'],
                'violation_title' => $row['violation_title'],
                'score'           => (int) $row['violation_score'],
                'occurred_at'     => $row['occurred_at'],
                'notes'           => $row['notes'],
            ];
        }, $violations);

        $data = [
            'total_points'     => $totalPoints,
            'violation_count'  => $violationCount,
            'discipline_level' => $levelData,
            'violations'       => $violationHistory,
        ];

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