using System.Text.Json.Serialization;
using RelayShared.Rtc;
using SurrealDb.Net.Models;

#region Resharper Stuff
// ReSharper disable ClassNeverInstantiated.Global
// ReSharper disable PropertyCanBeMadeInitOnly.Global
// ReSharper disable InconsistentNaming
#endregion

namespace RelayShared.Rtc;

public enum SignalType
{
    Offer,
    Answer,
    Candidate,
    OfferUpdated,
    AnswerUpdated,
    CandidateAdded,
    CallLeft,
    ChannelList,
    ServerPublicKey,
    EncryptedSignal,
    EncryptedChat,
    ClientEncryptedChat
}

public enum ChannelType
{
    Text, //Default channel type, handles text, links, files*, all in a linear live chat format
    Voice, //Used for general voice and video calls, utilizes WebRTC in its intended use
    File, //File browser for connected text channels, used for browsing files rather than scrolling through text channel
    Forum, //Specific forum posts, meant to keep conversations grouped and on topic while keeping all in an easy to find place
    Stage //Used for announcements and presentations, voice/video call utilizing a modified WebRTC protocol through server
}
public sealed class RtcSignalMessage
{
    [JsonPropertyName("type")]
    public SignalType Type { get; set; }

    [JsonPropertyName("from")]
    public string From { get; set; } = string.Empty;

    [JsonPropertyName("to")]
    public string To { get; set; } = string.Empty;

    [JsonPropertyName("channelId")]
    public string ChannelId { get; set; } = string.Empty;

    [JsonPropertyName("sdp")]
    public string? Sdp { get; set; }

    [JsonPropertyName("candidate")]
    public string? Candidate { get; set; }

    [JsonPropertyName("sdpMid")]
    public string? SdpMid { get; set; }

    [JsonPropertyName("sdpMLineIndex")]
    public int? SdpMLineIndex { get; set; }
    
    [JsonPropertyName("isInitiator")]
    public bool IsInitiator { get; set; }
}

public sealed class RtcNotificationMessage
{
    public SignalType? Type { get; set; }
    public string? ChannelId { get; set; }
    public string? Username { get; set; }
    public string? Direction { get; set; }
}

public sealed class ServerPublicKeyMessage
{
    public SignalType Type { get; set; } = SignalType.ServerPublicKey;
    public string PublicKey { get; set; } = string.Empty;
}

public sealed class SocketRtcSignalMessage
{
    public SignalType Type { get; set; }
    public string SenderUsername { get; set; } = string.Empty;
    public string ChannelId { get; set; } = string.Empty;
    public string CipherText { get; set; } = string.Empty;
    public string Nonce { get; set; } = string.Empty;
    public string Tag { get; set; } = string.Empty;
    public string EncryptedKey { get; set; } = string.Empty;
}

public sealed class SocketEncryptedMessage
{
    public SignalType Type { get; set; } = SignalType.EncryptedChat;
    public string SenderUsername { get; set; } = string.Empty;
    public string RecipientUsername { get; set; } = string.Empty;
    public string ChannelId { get; set; } = string.Empty;
    public string CipherText { get; set; } = string.Empty;
    public string Nonce { get; set; } = string.Empty;
    public string Tag { get; set; } = string.Empty;
    public string EncryptedKey { get; set; } = string.Empty;
}

public sealed class ChannelItem
{
    public string ChannelId { get; set; } = string.Empty;
    public string Name { get; set; } = string.Empty;
    
    public ChannelType Type { get; set; }
    
    public string Group { get; set; } = string.Empty;
    public DateTime CreatedAt { get; set; }
}

public sealed class SocketChannelList
{
    public SignalType Type { get; set; } = SignalType.ChannelList;
    public List<ChannelItem> Channels { get; set; } = [];
}

public sealed class RtcJoinRequest
{
    public string ChannelId { get; set; } = string.Empty;
    public string Username { get; set; } = string.Empty;
}

public sealed class RtcJoinResponse
{
    public string ChannelId { get; set; } = string.Empty;
    public bool HasActiveCall { get; set; }
    public bool IsOfferer { get; set; }
    public string? OfferUser { get; set; }
    public RtcSessionDescription? OfferSdp { get; set; }
}

public sealed class RtcLeaveRequest
{
    public string ChannelId { get; set; } = string.Empty;
    public string Username { get; set; } = string.Empty;
}

public sealed class RtcSessionDescription
{
    public string Type { get; set; } = string.Empty;
    public string Sdp { get; set; } = string.Empty;
}

public sealed class RtcOffer
{
    public string ChannelId { get; set; } = string.Empty;
    public string Username { get; set; } = string.Empty;
    public RtcSessionDescription SessionDescription { get; set; } = new();
}

public sealed class RtcAnswer
{
    public string ChannelId { get; set; } = string.Empty;
    public string Username { get; set; } = string.Empty;
    public RtcSessionDescription SessionDescription { get; set; } = new();
}

public class DBIceCandidate : Record
{
    public required string ChannelId { get; set; }
    public required string Username { get; set; }
    public required string Candidate { get; set; }
    public string? SdpMid { get; set; }
    public int? SdpMLineIndex { get; set; }
    // public required string Direction { get; set; } // "offer" or "answer"
    public DateTime CreatedAt { get; set; }
}

public class RtcIceCandidate
{
    public required string ChannelId { get; set; }
    public required string Username { get; set; }
    public required IceCandidate Candidate { get; set; }
}

public class IceCandidate
{
    public required string candidate { get; set; }
    public required string sdpMid { get; set; }
    public required int sdpMLineIndex { get; set; }
    public required string usernameFragment { get; set; }
    
}

public sealed class DBActiveCall : Record
{
    public string ChannelId { get; set; } = string.Empty;
    public string? OfferUser { get; set; }
    public RtcSessionDescription? Offer { get; set; }
    public RtcSessionDescription? Answer { get; set; }
    public DateTime CreatedAt { get; set; }
    public DateTime UpdatedAt { get; set; }
    public bool IsActive { get; set; }
}