namespace Domain.Exceptions;

/// <summary>
/// Base class for all domain exceptions.
/// Provides a machine-readable code for client error handling.
/// </summary>
public abstract class DomainException : Exception
{
    /// <summary>
    /// Machine-readable error code for client handling.
    /// </summary>
    public string Code { get; }

    protected DomainException(string code, string message) : base(message)
    {
        Code = code;
    }
}

/// <summary>
/// Thrown when a student attempts to enroll in more than 3 subjects.
/// </summary>
public class MaxEnrollmentsExceededException : DomainException
{
    public MaxEnrollmentsExceededException(int studentId)
        : base("MAX_ENROLLMENTS", $"Student {studentId} cannot enroll in more than 3 subjects") { }
}

/// <summary>
/// Thrown when a student attempts to enroll in a subject with a professor they already have.
/// </summary>
public class SameProfessorConstraintException : DomainException
{
    public SameProfessorConstraintException(int studentId, int professorId)
        : base("SAME_PROFESSOR", $"Student {studentId} already has a subject with professor {professorId}") { }
}

/// <summary>
/// Thrown when a requested student is not found.
/// </summary>
public class StudentNotFoundException : DomainException
{
    public StudentNotFoundException(int studentId)
        : base("STUDENT_NOT_FOUND", $"Student {studentId} was not found") { }
}

/// <summary>
/// Thrown when a requested subject is not found.
/// </summary>
public class SubjectNotFoundException : DomainException
{
    public SubjectNotFoundException(int subjectId)
        : base("SUBJECT_NOT_FOUND", $"Subject {subjectId} was not found") { }
}

/// <summary>
/// Thrown when a requested enrollment is not found.
/// </summary>
public class EnrollmentNotFoundException : DomainException
{
    public EnrollmentNotFoundException(int enrollmentId)
        : base("ENROLLMENT_NOT_FOUND", $"Enrollment {enrollmentId} was not found") { }
}

/// <summary>
/// Thrown when a student attempts to enroll in a subject they're already enrolled in.
/// </summary>
public class DuplicateEnrollmentException : DomainException
{
    public DuplicateEnrollmentException(int studentId, int subjectId)
        : base("DUPLICATE_ENROLLMENT", $"Student {studentId} is already enrolled in subject {subjectId}") { }
}

/// <summary>
/// Thrown when attempting to assign more than 2 subjects to a professor.
/// Business rule: Each professor teaches exactly 2 subjects.
/// </summary>
public class ProfessorMaxSubjectsExceededException : DomainException
{
    public ProfessorMaxSubjectsExceededException(int professorId)
        : base("PROFESSOR_MAX_SUBJECTS", $"Professor {professorId} already has the maximum of 2 subjects") { }
}

/// <summary>
/// Thrown when a requested professor is not found.
/// </summary>
public class ProfessorNotFoundException : DomainException
{
    public ProfessorNotFoundException(int professorId)
        : base("PROFESSOR_NOT_FOUND", $"Professor {professorId} was not found") { }
}
