using DotNext;
using LinqToDB;
using LinqToDB.Mapping;

namespace Database;

/// <summary>
/// 用户权限枚举
/// </summary>
public enum UserPermission
{
    /// <summary>
    /// 管理员权限，可以管理用户和实验板
    /// </summary>
    Admin,

    /// <summary>
    /// 普通用户权限，只能使用实验板
    /// </summary>
    Normal,
}

/// <summary>
/// 用户类，表示用户信息
/// </summary>
public class User
{
    /// <summary>
    /// 用户的唯一标识符
    /// </summary>
    [PrimaryKey]
    public Guid ID { get; set; } = Guid.NewGuid();

    /// <summary>
    /// 用户的名称
    /// </summary>
    [NotNull]
    public required string Name { get; set; }

    /// <summary>
    /// 用户的电子邮箱
    /// </summary>
    [NotNull]
    public required string EMail { get; set; }

    /// <summary>
    /// 用户的密码（应该进行哈希处理）
    /// </summary>
    [NotNull]
    public required string Password { get; set; }

    /// <summary>
    /// 用户权限等级
    /// </summary>
    [NotNull]
    public required UserPermission Permission { get; set; }

    /// <summary>
    /// 绑定的实验板ID，如果未绑定则为空
    /// </summary>
    [Nullable]
    public Guid BoardID { get; set; }

    /// <summary>
    /// 用户绑定板子的过期时间
    /// </summary>
    [Nullable]
    public DateTime? BoardExpireTime { get; set; }
}

/// <summary>
/// FPGA 板子状态枚举
/// </summary>
public enum BoardStatus
{
    /// <summary>
    /// 未启用状态，无法被使用
    /// </summary>
    Disabled,

    /// <summary>
    /// 繁忙状态，正在被用户使用
    /// </summary>
    Busy,

    /// <summary>
    /// 可用状态，可以被分配给用户
    /// </summary>
    Available,
}

/// <summary>
/// FPGA 板子类，表示板子信息
/// </summary>
public class Board
{
    /// <summary>
    /// FPGA 板子的唯一标识符
    /// </summary>
    [PrimaryKey]
    public Guid ID { get; set; } = Guid.NewGuid();

    /// <summary>
    /// FPGA 板子的名称
    /// </summary>
    [NotNull]
    public required string BoardName { get; set; }

    /// <summary>
    /// FPGA 板子的IP地址
    /// </summary>
    [NotNull]
    public required string IpAddr { get; set; }

    /// <summary>
    /// FPGA 板子的MAC地址
    /// </summary>
    [NotNull]
    public required string MacAddr { get; set; }

    /// <summary>
    /// FPGA 板子的通信端口
    /// </summary>
    [NotNull]
    public int Port { get; set; } = 1234;

    /// <summary>
    /// FPGA 板子的当前状态
    /// </summary>
    [NotNull]
    public required BoardStatus Status { get; set; }

    /// <summary>
    /// 占用该板子的用户的唯一标识符
    /// </summary>
    [Nullable]
    public Guid OccupiedUserID { get; set; }

    /// <summary>
    /// 占用该板子的用户的用户名
    /// </summary>
    [Nullable]
    public string? OccupiedUserName { get; set; }

    /// <summary>
    /// FPGA 板子的固件版本号
    /// </summary>
    [NotNull]
    public string FirmVersion { get; set; } = "1.0.0";

}

/// <summary>
/// 实验类，表示实验信息
/// </summary>
public class Exam
{
    /// <summary>
    /// 实验的唯一标识符
    /// </summary>
    [PrimaryKey]
    public required string ID { get; set; }

    /// <summary>
    /// 实验名称
    /// </summary>
    [NotNull]
    public required string Name { get; set; }

    /// <summary>
    /// 实验描述
    /// </summary>
    [NotNull]
    public required string Description { get; set; }

    /// <summary>
    /// 实验创建时间
    /// </summary>
    [NotNull]
    public DateTime CreatedTime { get; set; } = DateTime.Now;

    /// <summary>
    /// 实验最后更新时间
    /// </summary>
    [NotNull]
    public DateTime UpdatedTime { get; set; } = DateTime.Now;

    /// <summary>
    /// 实验标签（以逗号分隔的字符串）
    /// </summary>
    [NotNull]
    public string Tags { get; set; } = "";

    /// <summary>
    /// 实验难度（1-5，1为最简单）
    /// </summary>
    [NotNull]
    public int Difficulty { get; set; } = 1;

    /// <summary>
    /// 普通用户是否可见
    /// </summary>
    [NotNull]
    public bool IsVisibleToUsers { get; set; } = true;

    /// <summary>
    /// 获取标签列表
    /// </summary>
    /// <returns>标签数组</returns>
    public string[] GetTagsList()
    {
        if (string.IsNullOrWhiteSpace(Tags))
            return Array.Empty<string>();

        return Tags.Split(',', StringSplitOptions.RemoveEmptyEntries)
                   .Select(tag => tag.Trim())
                   .Where(tag => !string.IsNullOrEmpty(tag))
                   .ToArray();
    }

    /// <summary>
    /// 设置标签列表
    /// </summary>
    /// <param name="tags">标签数组</param>
    public void SetTagsList(string[] tags)
    {
        Tags = string.Join(",", tags.Where(tag => !string.IsNullOrWhiteSpace(tag)).Select(tag => tag.Trim()));
    }
}

/// <summary>
/// 资源类型枚举
/// </summary>
public static class ResourceTypes
{
    /// <summary>
    /// 图片资源类型
    /// </summary>
    public const string Images = "images";

    /// <summary>
    /// Markdown文档资源类型
    /// </summary>
    public const string Markdown = "markdown";

    /// <summary>
    /// 比特流文件资源类型
    /// </summary>
    public const string Bitstream = "bitstream";

    /// <summary>
    /// 原理图资源类型
    /// </summary>
    public const string Diagram = "diagram";

    /// <summary>
    /// 项目文件资源类型
    /// </summary>
    public const string Project = "project";

    /// <summary>
    /// 压缩文件资源类型
    /// </summary>
    public const string Compression = "compression";
}

public enum ResourcePurpose : int
{
    /// <summary>
    /// 模板资源，通常由管理员上传，供用户参考
    /// </summary>
    Template,

    /// <summary>
    /// 用户上传的资源
    /// </summary>
    User,

    /// <summary>
    /// 用户提交的作业
    /// </summary>
    Homework
}

/// <summary>
/// 资源类，统一管理实验资源、用户比特流等各类资源
/// </summary>
public class Resource
{
    /// <summary>
    /// 资源的唯一标识符
    /// </summary>
    [PrimaryKey]
    public Guid ID { get; set; } = Guid.NewGuid();

    /// <summary>
    /// 上传资源的用户ID
    /// </summary>
    [NotNull]
    public required Guid UserID { get; set; }

    /// <summary>
    /// 所属实验ID（可选，如果不属于特定实验则为空）
    /// </summary>
    [Nullable]
    public string? ExamID { get; set; }

    /// <summary>
    /// 资源类型（images, markdown, bitstream, diagram, project等）
    /// </summary>
    [NotNull]
    public required string ResourceType { get; set; }

    /// <summary>
    /// 资源用途：template（模板）或 user（用户上传）
    /// </summary>
    [NotNull]
    public required ResourcePurpose Purpose { get; set; }

    /// <summary>
    /// 资源名称（包含文件扩展名）
    /// </summary>
    [NotNull]
    public required string ResourceName { get; set; }

    /// <summary>
    /// 资源路径（包含文件名和扩展名）
    /// </summary>
    [NotNull]
    public required string Path { get; set; }

    /// <summary>
    /// 资源SHA256哈希值
    /// </summary>
    [NotNull]
    public required string SHA256 { get; set; }

    /// <summary>
    /// 资源创建/上传时间
    /// </summary>
    [NotNull]
    public DateTime UploadTime { get; set; } = DateTime.Now;

    /// <summary>
    /// 资源的MIME类型
    /// </summary>
    [NotNull]
    public string MimeType { get; set; } = "application/octet-stream";

}
