using Jiaowu.Api.Domain.Common;

namespace Jiaowu.Api.Domain.Academic;

public sealed class SchedulePlan : EntityBase
{
    public Guid AcademicTermId { get; set; }
    public AcademicTerm? AcademicTerm { get; set; }
    public required string Name { get; set; }
    public required string Version { get; set; }
    public SchedulePlanStatus Status { get; set; } = SchedulePlanStatus.Draft;
    public string? Notes { get; set; }
    public DateTime? PublishedAt { get; set; }
    public ICollection<ScheduleEntry> Entries { get; set; } = [];
}

public sealed class ScheduleEntry : EntityBase
{
    public Guid SchedulePlanId { get; set; }
    public SchedulePlan? SchedulePlan { get; set; }
    public Guid TeachingTaskId { get; set; }
    public TeachingTask? TeachingTask { get; set; }
    public ScheduleEntryKind Kind { get; set; } = ScheduleEntryKind.Lecture;
    public Guid? ClassroomId { get; set; }
    public Classroom? Classroom { get; set; }
    public int DayOfWeek { get; set; }
    public int StartPeriod { get; set; }
    public int PeriodCount { get; set; }
    public int StartWeek { get; set; }
    public int EndWeek { get; set; }
    public WeekPattern WeekPattern { get; set; }
    public string? Notes { get; set; }
}

public sealed class ScheduleTimeSlot : EntityBase
{
    public Guid AcademicTermId { get; set; }
    public AcademicTerm? AcademicTerm { get; set; }
    public int PeriodNumber { get; set; }
    public required string Name { get; set; }
    public TimeOnly StartsAt { get; set; }
    public TimeOnly EndsAt { get; set; }
    public bool IsEnabled { get; set; } = true;
}

public sealed class TeachingTaskScheduleConstraint : EntityBase
{
    public Guid TeachingTaskId { get; set; }
    public TeachingTask? TeachingTask { get; set; }
    public bool RequiresClassroom { get; set; } = true;
    public Guid? RequiredCampusId { get; set; }
    public Campus? RequiredCampus { get; set; }
    public Guid? RequiredBuildingId { get; set; }
    public Building? RequiredBuilding { get; set; }
    public Guid? ExperimentRequiredCampusId { get; set; }
    public Campus? ExperimentRequiredCampus { get; set; }
    public Guid? ExperimentRequiredBuildingId { get; set; }
    public Building? ExperimentRequiredBuilding { get; set; }
    public string? AllowedDayOfWeeks { get; set; }
    public int? EarliestPeriod { get; set; }
    public int? LatestPeriod { get; set; }
    public TeachingVenueNature AllowedExperimentVenueNatures { get; set; }
    public ICollection<TeachingTaskAllowedClassroom> AllowedClassrooms { get; set; } = [];
    public ICollection<TeachingTaskAllowedExperimentClassroom> AllowedExperimentClassrooms { get; set; } = [];
}

public sealed class TeachingTaskAllowedClassroom
{
    public Guid TeachingTaskScheduleConstraintId { get; set; }
    public TeachingTaskScheduleConstraint? TeachingTaskScheduleConstraint { get; set; }
    public Guid ClassroomId { get; set; }
    public Classroom? Classroom { get; set; }
}

public sealed class PublishedScheduleOccurrence : EntityBase
{
    public Guid SchedulePlanId { get; set; }
    public Guid AcademicTermId { get; set; }
    public Guid ScheduleEntryId { get; set; }
    public Guid TeachingTaskId { get; set; }
    public Guid? ClassroomId { get; set; }
    public int Week { get; set; }
    public int DayOfWeek { get; set; }
    public int StartPeriod { get; set; }
    public int PeriodCount { get; set; }
    public ScheduleEntryKind Kind { get; set; }
    public ScheduleEntry? ScheduleEntry { get; set; }
    public TeachingTask? TeachingTask { get; set; }
    public Classroom? Classroom { get; set; }
}

public sealed class TeachingTaskAllowedExperimentClassroom
{
    public Guid TeachingTaskScheduleConstraintId { get; set; }
    public TeachingTaskScheduleConstraint? TeachingTaskScheduleConstraint { get; set; }
    public Guid ClassroomId { get; set; }
    public Classroom? Classroom { get; set; }
}

public sealed class AutomaticScheduleJob : EntityBase
{
    public Guid SchedulePlanId { get; set; }
    public SchedulePlan? SchedulePlan { get; set; }
    public Guid? ActiveSchedulePlanId { get; set; }
    public Guid? RequestedByUserId { get; set; }
    public AutomaticScheduleJobStatus Status { get; set; } =
        AutomaticScheduleJobStatus.Queued;
    public int TotalTasks { get; set; }
    public int ProcessedTasks { get; set; }
    public int CreatedEntries { get; set; }
    public int CompletedTasks { get; set; }
    public string? MessagesJson { get; set; }
    public string? ErrorMessage { get; set; }
    public DateTime? StartedAt { get; set; }
    public DateTime? CompletedAt { get; set; }
}

public sealed class SchedulePublishJob : EntityBase
{
    public Guid SchedulePlanId { get; set; }
    public SchedulePlan? SchedulePlan { get; set; }
    public Guid AcademicTermId { get; set; }
    public Guid? ActiveAcademicTermId { get; set; }
    public Guid? RequestedByUserId { get; set; }
    public SchedulePublishJobStatus Status { get; set; } =
        SchedulePublishJobStatus.Queued;
    public int TotalSteps { get; set; } = 5;
    public int CompletedSteps { get; set; }
    public string? CurrentStep { get; set; }
    public string? ErrorMessage { get; set; }
    public DateTime? StartedAt { get; set; }
    public DateTime? CompletedAt { get; set; }
}

public enum SchedulePlanStatus
{
    Draft = 1,
    Published = 2,
    Archived = 3
}

public enum AutomaticScheduleJobStatus
{
    Queued = 1,
    Running = 2,
    Succeeded = 3,
    Failed = 4
}

public enum SchedulePublishJobStatus
{
    Queued = 1,
    Running = 2,
    Succeeded = 3,
    Failed = 4
}

public enum WeekPattern
{
    All = 1,
    Odd = 2,
    Even = 3
}

public enum ScheduleEntryKind
{
    Lecture = 1,
    Experiment = 2
}
