<?php
class User
{
    public static function find(int $id): ?array
    {
        Database::migrate();
        $stmt = Database::pdo()->prepare("SELECT id, role, name, cpf, email, whatsapp, uf, city, bairro, category, license_process, license_category, student_status, requested_lessons_a, requested_lessons_b, requested_lessons_other, registration_requested_at, registration_reviewed_at, student_level, student_level_note, student_level_updated_at, student_level_professional_id, admin_notes, finished_at, deleted_at, profile_photo_path, internal_code, created_at FROM users WHERE id = ? AND deleted_at IS NULL LIMIT 1");
        $stmt->execute([$id]);
        $user = $stmt->fetch();
        return $user ?: null;
    }

    public static function findByEmail(string $email): ?array
    {
        Database::migrate();
        $stmt = Database::pdo()->prepare('SELECT * FROM users WHERE email = ? AND deleted_at IS NULL LIMIT 1');
        $stmt->execute([strtolower(trim($email))]);
        $user = $stmt->fetch();
        return $user ?: null;
    }

    public static function createStudent(array $data): int
    {
        Database::migrate();
        if (!is_valid_cpf_basic($data['cpf'] ?? '')) {
            throw new InvalidArgumentException('CPF inválido. Informe 11 dígitos e não use sequência repetida.');
        }
        if (!is_valid_whatsapp_br($data['whatsapp'] ?? '')) {
            throw new InvalidArgumentException('WhatsApp inválido. Informe o número com DDD e 11 dígitos.');
        }
        $pdo = Database::pdo();
        $category = strtoupper(trim((string)($data['category'] ?? '')));
        $qtyA = max(0, (int)($data['lessons_a'] ?? 0));
        $qtyB = max(0, (int)($data['lessons_b'] ?? 0));
        $qtyOther = max(0, (int)($data['lessons_other'] ?? 0));
        $now = date('Y-m-d H:i:s');
        $stmt = $pdo->prepare('INSERT INTO users (role, name, cpf, email, whatsapp, uf, city, bairro, category, license_process, license_category, password_hash, student_status, requested_lessons_a, requested_lessons_b, requested_lessons_other, registration_requested_at, created_at) VALUES (:role, :name, :cpf, :email, :whatsapp, :uf, :city, :bairro, :category, :license_process, :license_category, :password_hash, :student_status, :qty_a, :qty_b, :qty_other, :requested_at, :created_at)');
        $process = in_array($category, ['A','B','AB'], true) ? 'first_license' : (in_array($category, ['C','D','E'], true) ? 'classification' : 'first_license');
        $stmt->execute([
            ':role' => 'student', ':name' => trim($data['name']), ':cpf' => only_digits($data['cpf']),
            ':email' => strtolower(trim($data['email'])), ':whatsapp' => normalize_whatsapp_br($data['whatsapp']),
            ':uf' => strtoupper(trim($data['uf'])), ':city' => trim($data['city']), ':bairro' => trim($data['bairro']),
            ':category' => $category, ':license_process' => $process, ':license_category' => $category,
            ':password_hash' => password_hash($data['password'], PASSWORD_DEFAULT), ':student_status' => 'pending',
            ':qty_a' => $qtyA, ':qty_b' => $qtyB, ':qty_other' => $qtyOther,
            ':requested_at' => $now, ':created_at' => $now,
        ]);
        return (int)$pdo->lastInsertId();
    }


    public static function createStudentByAdmin(array $data): array
    {
        Database::migrate();
        $required = ['name', 'cpf', 'email', 'whatsapp', 'uf', 'city', 'bairro'];
        foreach ($required as $field) {
            if (trim($data[$field] ?? '') === '') {
                return ['ok' => false, 'message' => 'Preencha todos os campos obrigatórios do aluno.'];
            }
        }
        if (!is_valid_cpf_basic($data['cpf'] ?? '')) {
            return ['ok' => false, 'message' => 'CPF inválido. Informe os 11 dígitos e não use sequência repetida como 000.000.000-00.'];
        }
        if (!is_valid_whatsapp_br($data['whatsapp'] ?? '')) {
            return ['ok' => false, 'message' => 'WhatsApp inválido. Informe com DDD e 11 dígitos no formato (00) 00000-0000.'];
        }
        $password = trim((string)($data['password'] ?? ''));
        if ($password === '') {
            $cpfDigits = only_digits((string)($data['cpf'] ?? ''));
            $password = strlen($cpfDigits) >= 6 ? substr($cpfDigits, 0, 6) : '123456';
        }
        if (strlen($password) < 6) {
            return ['ok' => false, 'message' => 'A senha do aluno precisa ter no mínimo 6 caracteres.'];
        }
        try {
            $payload = $data;
            $payload['password'] = $password;
            $payload['category'] = trim((string)($data['category'] ?? ($data['license_category'] ?? '')));
            $studentId = self::createStudent($payload);
            if (!empty($data['license_process'])) {
                $packageResult = StudentLessonPackage::saveProcessAndPackages($studentId, $data);
                if (!$packageResult['ok']) {
                    Database::pdo()->prepare('DELETE FROM users WHERE id = ?')->execute([$studentId]);
                    return $packageResult;
                }
            }
            Database::pdo()->prepare("UPDATE users SET student_status='active', registration_reviewed_at=? WHERE id=?")->execute([date('Y-m-d H:i:s'),$studentId]);
            return ['ok' => true, 'message' => 'Aluno cadastrado com sucesso. Senha inicial: ' . $password];
        } catch (PDOException $e) {
            if ($e->getCode() === '23000') {
                return ['ok' => false, 'message' => 'CPF ou e-mail já cadastrado.'];
            }
            return ['ok' => false, 'message' => 'Não foi possivel cadastrar o aluno.'];
        }
    }


    public static function updateStudentByAdmin(int $studentId, array $data): array
    {
        Database::migrate();
        $student = self::find($studentId);
        if (!$student || ($student['role'] ?? '') !== 'student') {
            return ['ok' => false, 'message' => 'Aluno não encontrado.'];
        }
        foreach (['name', 'cpf', 'email', 'whatsapp', 'uf', 'city', 'bairro'] as $field) {
            if (trim((string)($data[$field] ?? '')) === '') {
                return ['ok' => false, 'message' => 'Preencha todos os campos obrigatórios do aluno.'];
            }
        }
        if (!is_valid_cpf_basic($data['cpf'] ?? '')) {
            return ['ok' => false, 'message' => 'CPF inválido. Informe os 11 dígitos corretamente.'];
        }
        if (!is_valid_whatsapp_br($data['whatsapp'] ?? '')) {
            return ['ok' => false, 'message' => 'WhatsApp inválido. Informe com DDD e 11 dígitos.'];
        }
        $email = strtolower(trim((string)$data['email']));
        if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
            return ['ok' => false, 'message' => 'Informe um e-mail válido.'];
        }
        $password = (string)($data['password'] ?? '');
        if ($password !== '' && strlen($password) < 6) {
            return ['ok' => false, 'message' => 'A nova senha precisa ter no mínimo 6 caracteres.'];
        }
        $pdo = Database::pdo();
        $duplicate = $pdo->prepare("SELECT COUNT(*) FROM users WHERE role='student' AND deleted_at IS NULL AND id<>? AND (cpf=? OR email=?)");
        $duplicate->execute([$studentId, only_digits((string)$data['cpf']), $email]);
        if ((int)$duplicate->fetchColumn() > 0) {
            return ['ok' => false, 'message' => 'CPF ou e-mail já está cadastrado para outro aluno.'];
        }
        $values = [
            trim((string)$data['name']), only_digits((string)$data['cpf']), $email,
            normalize_whatsapp_br((string)$data['whatsapp']), strtoupper(trim((string)$data['uf'])),
            trim((string)$data['city']), trim((string)$data['bairro'])
        ];
        if ($password !== '') {
            $stmt = $pdo->prepare("UPDATE users SET name=?, cpf=?, email=?, whatsapp=?, uf=?, city=?, bairro=?, password_hash=? WHERE id=? AND role='student' AND deleted_at IS NULL");
            $values[] = password_hash($password, PASSWORD_DEFAULT);
            $values[] = $studentId;
        } else {
            $stmt = $pdo->prepare("UPDATE users SET name=?, cpf=?, email=?, whatsapp=?, uf=?, city=?, bairro=? WHERE id=? AND role='student' AND deleted_at IS NULL");
            $values[] = $studentId;
        }
        $stmt->execute($values);
        return ['ok' => true, 'message' => 'Cadastro do aluno atualizado com sucesso.'];
    }

    public static function createAdmin(string $name, string $email, string $password): int
    {
        Database::migrate();
        $pdo = Database::pdo();
        $stmt = $pdo->prepare('INSERT INTO users (role, name, email, password_hash, created_at) VALUES (?, ?, ?, ?, ?)');
        $stmt->execute(['admin', trim($name), strtolower(trim($email)), password_hash($password, PASSWORD_DEFAULT), date('Y-m-d H:i:s')]);
        return (int)$pdo->lastInsertId();
    }

    public static function allStudents(): array
    {
        Database::migrate();
        $stmt = Database::pdo()->query("SELECT id, name, cpf, email, whatsapp, uf, city, bairro, category, license_process, license_category, student_status, requested_lessons_a, requested_lessons_b, requested_lessons_other, registration_requested_at, registration_reviewed_at, student_level, student_level_note, student_level_updated_at, admin_notes, finished_at, profile_photo_path, internal_code, created_at FROM users WHERE role = 'student' AND deleted_at IS NULL ORDER BY CASE student_status WHEN 'active' THEN 1 WHEN 'finished' THEN 2 ELSE 3 END, created_at DESC");
        return $stmt->fetchAll();
    }


    public static function pendingStudents(): array
    {
        Database::migrate();
        $stmt = Database::pdo()->query("SELECT id, name, cpf, email, whatsapp, uf, city, bairro, category, license_process, license_category, student_status, requested_lessons_a, requested_lessons_b, requested_lessons_other, registration_requested_at FROM users WHERE role = 'student' AND student_status = 'pending' AND deleted_at IS NULL ORDER BY registration_requested_at ASC, created_at ASC");
        return $stmt->fetchAll();
    }

    public static function approveStudent(int $id): array
    {
        Database::migrate();
        $pdo = Database::pdo();
        $stmt = $pdo->prepare("SELECT * FROM users WHERE id=? AND role='student' AND student_status='pending' AND deleted_at IS NULL LIMIT 1");
        $stmt->execute([$id]); $student=$stmt->fetch();
        if (!$student) return ['ok'=>false,'message'=>'Solicitação de cadastro não encontrada ou já analisada.'];
        $category = normalize_driving_category($student['category'] ?? '');
        $qa=max(0,(int)($student['requested_lessons_a']??0)); $qb=max(0,(int)($student['requested_lessons_b']??0)); $qo=max(0,(int)($student['requested_lessons_other']??0));
        if ($category==='AB') { if($qa<2)$qa=2; if($qb<2)$qb=2; $process='first_license'; $payload=['license_process'=>$process,'lessons_a'=>$qa,'lessons_b'=>$qb]; }
        elseif (in_array($category,['A','B'],true)) { if($category==='A')$qa=max(2,$qa); else $qb=max(2,$qb); $process='first_license'; $payload=['license_process'=>$process,'lessons_a'=>$qa,'lessons_b'=>$qb]; }
        elseif (in_array($category,['C','D','E'],true)) { $qo=max(2,$qo); $payload=['license_process'=>'classification','classification_category'=>$category,'classification_lessons'=>$qo]; }
        else return ['ok'=>false,'message'=>'Categoria do cadastro não possui uma regra de aulas práticas.'];
        try {
            $payload['category']=$category;
            $packageResult = StudentLessonPackage::saveProcessAndPackages($id,$payload);
            if(!$packageResult['ok']) return $packageResult;
            $up=$pdo->prepare("UPDATE users SET student_status='active', registration_reviewed_at=?, requested_lessons_a=?, requested_lessons_b=?, requested_lessons_other=? WHERE id=? AND student_status='pending'");
            $up->execute([date('Y-m-d H:i:s'),$qa,$qb,$qo,$id]);
            return ['ok'=>true,'message'=>'Cadastro aprovado. O aluno já pode acessar o sistema. Pacote de aulas liberado.'];
        } catch(Throwable $e){ return ['ok'=>false,'message'=>'Não foi possível aprovar o cadastro: '.$e->getMessage()]; }
    }

    public static function activeStudents(): array
    {
        Database::migrate();
        $stmt = Database::pdo()->query("SELECT id, name, cpf, email, whatsapp, category, license_process, license_category, student_status, requested_lessons_a, requested_lessons_b, requested_lessons_other, registration_requested_at, registration_reviewed_at, student_level, student_level_note, profile_photo_path, internal_code FROM users WHERE role = 'student' AND student_status = 'active' AND deleted_at IS NULL ORDER BY name ASC");
        return $stmt->fetchAll();
    }
    public static function updateAdminNotes(int $studentId, string $notes): array
    {
        Database::migrate();
        $stmt = Database::pdo()->prepare("UPDATE users SET admin_notes = ? WHERE id = ? AND role = 'student' AND deleted_at IS NULL");
        $stmt->execute([trim($notes), $studentId]);
        if ($stmt->rowCount() <= 0) {
            return ['ok' => false, 'message' => 'Aluno não encontrado para salvar informações.'];
        }
        return ['ok' => true, 'message' => 'Informações internas do aluno salvas.'];
    }

    public static function updateLevelByProfessional(int $professionalId, int $studentId, string $level, string $note = ''): array
    {
        Database::migrate();
        $level = trim($level);
        $allowed = array_keys(student_level_options());
        if (!in_array($level, $allowed, true)) {
            return ['ok' => false, 'message' => 'Nivel do aluno invalido.'];
        }
        $stmt = Database::pdo()->prepare("SELECT COUNT(*) FROM appointments WHERE professional_id = ? AND student_id = ? AND status IN ('booked','completed')");
        $stmt->execute([$professionalId, $studentId]);
        if ((int)$stmt->fetchColumn() <= 0) {
            return ['ok' => false, 'message' => 'Este aluno não está vinculado a uma aula sua.'];
        }
        $stmt = Database::pdo()->prepare("UPDATE users SET student_level = ?, student_level_note = ?, student_level_updated_at = ?, student_level_professional_id = ? WHERE id = ? AND role = 'student' AND deleted_at IS NULL");
        $stmt->execute([$level, trim($note), date('Y-m-d H:i:s'), $professionalId, $studentId]);
        return ['ok' => true, 'message' => 'Nível do aluno atualizado.'];
    }

    public static function finishStudent(int $id): bool
    {
        $stmt = Database::pdo()->prepare("UPDATE users SET student_status = 'finished', finished_at = ? WHERE id = ? AND role = 'student' AND deleted_at IS NULL");
        $stmt->execute([date('Y-m-d H:i:s'), $id]);
        return $stmt->rowCount() > 0;
    }

    public static function reactivateStudent(int $id): bool
    {
        $stmt = Database::pdo()->prepare("UPDATE users SET student_status = 'active', finished_at = NULL WHERE id = ? AND role = 'student' AND deleted_at IS NULL");
        $stmt->execute([$id]);
        return $stmt->rowCount() > 0;
    }

    public static function deleteFinishedStudent(int $id): array
    {
        $pdo = Database::pdo();
        $stmt = $pdo->prepare("SELECT id, student_status FROM users WHERE id = ? AND role = 'student' AND deleted_at IS NULL LIMIT 1");
        $stmt->execute([$id]);
        $student = $stmt->fetch();
        if (!$student) {
            return ['ok' => false, 'message' => 'Aluno não encontrado.'];
        }
        if (($student['student_status'] ?? '') !== 'finished') {
            return ['ok' => false, 'message' => 'Somente cadastros finalizados podem ser apagados.'];
        }
        $future = $pdo->prepare("SELECT COUNT(*) FROM appointments a INNER JOIN availability_slots s ON s.id = a.slot_id WHERE a.student_id = ? AND a.status = 'booked' AND s.start_at >= ?");
        $future->execute([$id, date('Y-m-d H:i:s')]);
        if ((int)$future->fetchColumn() > 0) {
            return ['ok' => false, 'message' => 'Este aluno ainda possui aula futura agendada. Cancele ou conclua antes de apagar.'];
        }
        // Nao remove fisicamente o aluno para preservar historico/contador de aulas.
        // O cadastro sai das listas normais porque deleted_at deixa de ser NULL.
        $delete = $pdo->prepare("UPDATE users SET deleted_at = ? WHERE id = ? AND role = 'student' AND student_status = 'finished' AND deleted_at IS NULL");
        $delete->execute([date('Y-m-d H:i:s'), $id]);
        return ['ok' => true, 'message' => 'Cadastro finalizado ocultado com sucesso. O historico de aulas foi preservado.'];
    }



    public static function updateAdminCredentials(int $adminId, string $name, string $email, string $currentPassword, string $newPassword = ''): array
    {
        Database::migrate();
        $pdo = Database::pdo();
        $stmt = $pdo->prepare("SELECT * FROM users WHERE id = ? AND role = 'admin' AND deleted_at IS NULL LIMIT 1");
        $stmt->execute([$adminId]);
        $admin = $stmt->fetch();
        if (!$admin) {
            return ['ok' => false, 'message' => 'Administrador não encontrado.'];
        }
        if (!password_verify($currentPassword, $admin['password_hash'])) {
            return ['ok' => false, 'message' => 'Senha atual incorreta.'];
        }
        $email = strtolower(trim($email));
        $name = trim($name);
        if ($name === '' || $email === '') {
            return ['ok' => false, 'message' => 'Informe nome e usuário/e-mail.'];
        }
        if ($newPassword !== '' && strlen($newPassword) < 6) {
            return ['ok' => false, 'message' => 'A nova senha precisa ter no mínimo 6 caracteres.'];
        }

        $duplicate = $pdo->prepare('SELECT COUNT(*) FROM users WHERE email = ? AND id <> ? AND deleted_at IS NULL');
        $duplicate->execute([$email, $adminId]);
        if ((int)$duplicate->fetchColumn() > 0) {
            return ['ok' => false, 'message' => 'Este usuário/e-mail já está em uso.'];
        }

        if ($newPassword !== '') {
            $stmt = $pdo->prepare('UPDATE users SET name = ?, email = ?, password_hash = ? WHERE id = ? AND role = \'admin\'');
            $stmt->execute([$name, $email, password_hash($newPassword, PASSWORD_DEFAULT), $adminId]);
        } else {
            $stmt = $pdo->prepare('UPDATE users SET name = ?, email = ? WHERE id = ? AND role = \'admin\'');
            $stmt->execute([$name, $email, $adminId]);
        }
        return ['ok' => true, 'message' => 'Acesso administrativo atualizado com sucesso.'];
    }

    public static function countStudents(): int
    {
        return (int)Database::pdo()->query("SELECT COUNT(*) FROM users WHERE role = 'student' AND deleted_at IS NULL")->fetchColumn();
    }

    public static function updateProfilePhoto(int $studentId, array $file): array
    {
        Database::migrate();
        $stmt = Database::pdo()->prepare("SELECT profile_photo_path FROM users WHERE id=? AND role='student' AND deleted_at IS NULL LIMIT 1");
        $stmt->execute([$studentId]);
        $current = $stmt->fetch();
        if (!$current) {
            return ['ok' => false, 'message' => 'Aluno não encontrado.'];
        }
        $saved = PortalMedia::saveImage($file, 'profile_photos', 8388608);
        if (!$saved['ok']) {
            return $saved;
        }
        $update = Database::pdo()->prepare("UPDATE users SET profile_photo_path=? WHERE id=? AND role='student'");
        $update->execute([$saved['path'], $studentId]);
        PortalMedia::delete($current['profile_photo_path'] ?? '');
        return ['ok' => true, 'message' => 'Foto de perfil atualizada.'];
    }

}
