using Jiaowu.Api.Domain.Common;

namespace Jiaowu.Api.Domain.Academic;

public sealed class ExperimentGradeSheet : EntityBase
{
    public Guid ExperimentProjectId { get; set; }
    public ExperimentProject? ExperimentProject { get; set; }
    public decimal ContributionWeight { get; set; } = 1;
    public decimal PassScore { get; set; } = 60;
    public ExperimentGradeSheetStatus Status { get; set; } =
        ExperimentGradeSheetStatus.Draft;
    public string? ReviewComment { get; set; }
    public DateTime? SubmittedAt { get; set; }
    public DateTime? ReviewedAt { get; set; }
    public DateTime? PublishedAt { get; set; }
    public ICollection<ExperimentGradeItem> Items { get; set; } = [];
    public ICollection<ExperimentGradeRecord> Records { get; set; } = [];
}

public sealed class ExperimentGradeItem : EntityBase
{
    public Guid ExperimentGradeSheetId { get; set; }
    public ExperimentGradeSheet? ExperimentGradeSheet { get; set; }
    public required string Name { get; set; }
    public ExperimentGradeItemKind Kind { get; set; } =
        ExperimentGradeItemKind.Other;
    public decimal Weight { get; set; }
    public int SortOrder { get; set; }
    public ICollection<ExperimentGradeItemScore> Scores { get; set; } = [];
}

public sealed class ExperimentGradeRecord : EntityBase
{
    public Guid ExperimentGradeSheetId { get; set; }
    public ExperimentGradeSheet? ExperimentGradeSheet { get; set; }
    public Guid StudentId { get; set; }
    public Student? Student { get; set; }
    public Guid? ExperimentSessionId { get; set; }
    public ExperimentSession? ExperimentSession { get; set; }
    public ExperimentParticipationStatus ParticipationStatus { get; set; } =
        ExperimentParticipationStatus.Pending;
    public decimal? TotalScore { get; set; }
    public bool? IsPassed { get; set; }
    public bool SafetyViolation { get; set; }
    public int AttemptNumber { get; set; } = 1;
    public string? SubmissionReference { get; set; }
    public DateTime? SubmittedAt { get; set; }
    public bool IsLate { get; set; }
    public string? TeacherComment { get; set; }
    public ICollection<ExperimentGradeItemScore> ItemScores { get; set; } = [];
}

/// <summary>
/// A student's persisted experiment-part score for one teaching task.
/// The score is the weighted average of every published experiment project.
/// </summary>
public sealed class ExperimentCourseGrade : EntityBase
{
    public Guid TeachingTaskId { get; set; }
    public TeachingTask? TeachingTask { get; set; }
    public Guid StudentId { get; set; }
    public Student? Student { get; set; }
    public decimal? WeightedAverageScore { get; set; }
    public decimal TotalWeight { get; set; }
    public int PublishedProjectCount { get; set; }
    public DateTime RefreshedAt { get; set; }
}

public sealed class ExperimentGradeItemScore
{
    public Guid ExperimentGradeRecordId { get; set; }
    public ExperimentGradeRecord? ExperimentGradeRecord { get; set; }
    public Guid ExperimentGradeItemId { get; set; }
    public ExperimentGradeItem? ExperimentGradeItem { get; set; }
    public decimal? Score { get; set; }
    public string? Comment { get; set; }
}

public enum ExperimentGradeSheetStatus
{
    Draft = 1,
    Submitted = 2,
    Approved = 3,
    Published = 4,
    Returned = 5
}

public enum ExperimentGradeItemKind
{
    Operation = 1,
    Report = 2,
    Result = 3,
    Defense = 4,
    Attendance = 5,
    Safety = 6,
    Other = 7
}

public enum ExperimentParticipationStatus
{
    Pending = 1,
    Completed = 2,
    Absent = 3,
    Excused = 4,
    Makeup = 5,
    Exempt = 6
}
