@startuml sequence-enrollment
!theme plain
skinparam sequenceMessageAlign center
skinparam responseMessageBelowArrow true
skinparam sequenceParticipantBackgroundColor #F8F9FA
skinparam sequenceParticipantBorderColor #495057

title Secuencia: Inscripción de Estudiante en Materia (con JWT)

actor "Estudiante" as user
participant "Frontend\n(Angular)" as frontend
participant "API GraphQL\n(HotChocolate)" as api
participant "JWT Middleware" as jwt
participant "EnrollStudentHandler" as handler
participant "EnrollmentDomainService" as domainService
participant "StudentRepository" as studentRepo
participant "SubjectRepository" as subjectRepo
participant "EnrollmentRepository" as enrollRepo
database "SQL Server" as db

== Autenticación (previo) ==

note over user, frontend
  El estudiante ya inició sesión
  y tiene un JWT válido almacenado
end note

== Solicitud de Inscripción ==

user -> frontend : Selecciona materia\ny hace clic en "Inscribir"
activate frontend

frontend -> api : mutation enrollStudent(\n  studentId, subjectId)\n[Authorization: Bearer <JWT>]
activate api

api -> jwt : Validate JWT
activate jwt
jwt -> jwt : Verify signature\n& expiration
jwt --> api : ClaimsPrincipal
deactivate jwt

api -> handler : Handle(EnrollStudentCommand)
activate handler

== Obtención de Datos ==

handler -> studentRepo : GetByIdWithEnrollmentsAsync(studentId)
activate studentRepo
studentRepo -> db : SELECT Student + Enrollments
db --> studentRepo : Student data
studentRepo --> handler : Student
deactivate studentRepo

alt Cuenta no activada
    handler --> api : Error: "Cuenta no activada"
    api --> frontend : { errors: [...] }
    frontend --> user : Muestra mensaje:\n"Activa tu cuenta primero"
end

handler -> subjectRepo : GetByIdAsync(subjectId)
activate subjectRepo
subjectRepo -> db : SELECT Subject
db --> subjectRepo : Subject data
subjectRepo --> handler : Subject
deactivate subjectRepo

== Validación de Reglas de Negocio ==

handler -> domainService : ValidateEnrollment(student, subject)
activate domainService

domainService -> domainService : CheckMaxEnrollments()\n[máx 3 materias]

alt Estudiante tiene 3 materias
    domainService --> handler : throw MaxEnrollmentsExceededException
    handler --> api : Error: "Límite de materias alcanzado"
    api --> frontend : { errors: [...] }
    frontend --> user : Muestra mensaje de error
end

domainService -> domainService : CheckProfessorConstraint()\n[no repetir profesor]

alt Ya tiene materia con el profesor
    domainService --> handler : throw SameProfessorConstraintException
    handler --> api : Error: "Ya tienes materia con este profesor"
    api --> frontend : { errors: [...] }
    frontend --> user : Muestra mensaje de error
end

domainService --> handler : Validación OK
deactivate domainService

== Persistencia ==

handler -> enrollRepo : AddAsync(enrollment)
activate enrollRepo
enrollRepo -> db : INSERT Enrollment
db --> enrollRepo : OK
enrollRepo --> handler : Enrollment
deactivate enrollRepo

handler --> api : EnrollmentPayload
deactivate handler

api --> frontend : { enrollment: {...} }
deactivate api

frontend --> user : Muestra confirmación:\n"Inscrito en [materia]"
deactivate frontend

@enduml
