using SameBeat.Domain.Wyjatki;
namespace SameBeat.Domain.Encje;
///
/// Lekka tozsamosc czatu (ETAP 6) -- NIE to samo co UczestnikOczekujacy z poczekalni. Czat jest
/// dostepny dla kazdego widza, nie tylko dla ludzi z kamera na scenie, wiec potrzebuje wlasnego,
/// prostszego mechanizmu "kim jest ta przegladarka": bez sekretu sesji, bez tozsamosci LiveKit, bez
/// statusu w poczekalni. Tworzona przy pierwszym wejsciu na czat (POST /api/chat/dolacz).
///
public class UczestnikCzatu
{
public const int MaksymalnaDlugoscNicku = 40;
public Guid Id { get; private set; }
public Guid WydarzenieId { get; private set; }
public string Nick { get; private set; } = string.Empty;
public DateTime DolaczylUtc { get; private set; }
public bool Wyciszony { get; private set; }
public bool Zbanowany { get; private set; }
// Prywatny konstruktor bez parametrow -- wymagany przez EF Core do materializacji encji z bazy.
private UczestnikCzatu()
{
}
private UczestnikCzatu(Guid id, Guid wydarzenieId, string nick, DateTime dolaczylUtc)
{
Id = id;
WydarzenieId = wydarzenieId;
Nick = nick;
DolaczylUtc = dolaczylUtc;
}
///
/// Tworzy nowa tozsamosc czatu. Walidacja nicku tutaj chroni przed powstaniem encji w niepoprawnym
/// stanie niezaleznie od tego, ktory serwis aplikacji jej uzyje -- ten sam wzorzec i te same reguly
/// co UczestnikOczekujacy.Dolacz z ETAPU 2 (niepusty, limit dlugosci, bez '<'/'>').
///
public static UczestnikCzatu Dolacz(Guid wydarzenieId, string nick)
{
if (wydarzenieId == Guid.Empty)
{
throw new NieprawidlowyStanEncjiWyjatek("Uczestnik czatu musi byc powiazany z konkretnym wydarzeniem.");
}
var nickOczyszczony = OczyscNick(nick);
return new UczestnikCzatu(Guid.NewGuid(), wydarzenieId, nickOczyszczony, DateTime.UtcNow);
}
private static string OczyscNick(string nick)
{
if (string.IsNullOrWhiteSpace(nick))
{
throw new NieprawidlowyStanEncjiWyjatek("Nick jest wymagany.");
}
var przycietyNick = nick.Trim();
if (przycietyNick.Length > MaksymalnaDlugoscNicku)
{
throw new NieprawidlowyStanEncjiWyjatek($"Nick moze miec maksymalnie {MaksymalnaDlugoscNicku} znakow.");
}
// Podstawowa sanityzacja przed wstrzyknieciem HTML -- ten sam nick idzie pozniej do wiadomosci
// czatu, wiec odrzucamy znaki, ktorymi dalo by sie otworzyc znacznik, juz przy wejsciu do systemu.
if (przycietyNick.Contains('<') || przycietyNick.Contains('>'))
{
throw new NieprawidlowyStanEncjiWyjatek("Nick nie moze zawierac znakow '<' ani '>'.");
}
return przycietyNick;
}
/// Host wyciszyl te tozsamosc -- dalsze wiadomosci beda odrzucane przez SerwisCzatu, dopoki nie zostanie odciszona.
public void Wycisz() => Wyciszony = true;
public void Odcisz() => Wyciszony = false;
///
/// Ban tozsamosci czatu -- CELOWO osobny mechanizm od Zbanuj() w UczestnikOczekujacy (ETAP 2):
/// tamten dotyczy prawa do kamery/mikrofonu w poczekalni, ten wylacznie prawa do pisania na czacie.
/// Ta sama przegladarka moze w teorii miec obie tozsamosci niezaleznie od siebie.
///
public void Zbanuj() => Zbanowany = true;
}