using Omika.Diagnostics.Tasks;
namespace Omika.Diagnostics.Tests.Fakes;
///
/// Fake en mémoire de pour les tests sans
/// PostgreSQL. Reproduit la sémantique du repository Npgsql : unicité par signature
/// (group_url_identifier), statut normalisé, date de résolution dérivée du statut.
///
public sealed class FakeDiagnosticTaskRepository : IDiagnosticTaskRepository
{
private readonly List _tasks = [];
private long _nextId = 1;
public IReadOnlyList Seed(params DiagnosticTaskRecord[] tasks)
{
foreach (DiagnosticTaskRecord t in tasks)
{
if (t.Id == 0)
{
t.Id = _nextId++;
}
else
{
_nextId = Math.Max(_nextId, t.Id + 1);
}
_tasks.Add(t);
}
return _tasks;
}
public Task> ListAsync(
CancellationToken cancellationToken = default)
{
IReadOnlyList ordered = _tasks
.OrderByDescending(t => t.UpdatedAtUtc)
.ThenByDescending(t => t.Id)
.ToList();
return Task.FromResult(ordered);
}
public Task GetByIdAsync(
long id,
CancellationToken cancellationToken = default) =>
Task.FromResult(_tasks.FirstOrDefault(t => t.Id == id));
public Task GetByGroupAsync(
string groupUrlIdentifier,
CancellationToken cancellationToken = default) =>
Task.FromResult(_tasks.FirstOrDefault(t => t.GroupUrlIdentifier == groupUrlIdentifier));
public Task CreateAsync(
string groupUrlIdentifier,
string title,
string? description,
string? cause,
string status,
string createdByUsername,
string? assigneeUsername,
CancellationToken cancellationToken = default)
{
string? group = Normalize(groupUrlIdentifier);
string? normalizedTitle = Normalize(title);
if (group is null || normalizedTitle is null)
{
return Task.FromResult(null);
}
if (_tasks.Any(t => t.GroupUrlIdentifier == group))
{
return Task.FromResult(null); // doublon.
}
string normalizedStatus = DiagnosticTaskStatuses.Normalize(status);
DateTimeOffset now = DateTimeOffset.UtcNow;
var record = new DiagnosticTaskRecord
{
Id = _nextId++,
GroupUrlIdentifier = group,
Title = normalizedTitle,
Description = Normalize(description),
Cause = Normalize(cause),
Status = normalizedStatus,
CreatedByUsername = createdByUsername,
AssigneeUsername = Normalize(assigneeUsername),
CreatedAtUtc = now,
UpdatedAtUtc = now,
ResolvedAtUtc = DiagnosticTaskStatuses.IsTerminal(normalizedStatus) ? now : null
};
_tasks.Add(record);
return Task.FromResult(record);
}
public Task UpdateAsync(
long id,
string title,
string? description,
string? cause,
string status,
string? assigneeUsername,
CancellationToken cancellationToken = default)
{
DiagnosticTaskRecord? task = _tasks.FirstOrDefault(t => t.Id == id);
string? normalizedTitle = Normalize(title);
if (task is null || normalizedTitle is null)
{
return Task.FromResult(false);
}
string normalizedStatus = DiagnosticTaskStatuses.Normalize(status);
task.Title = normalizedTitle;
task.Description = Normalize(description);
task.Cause = Normalize(cause);
task.Status = normalizedStatus;
task.AssigneeUsername = Normalize(assigneeUsername);
task.UpdatedAtUtc = DateTimeOffset.UtcNow;
task.ResolvedAtUtc = DiagnosticTaskStatuses.IsTerminal(normalizedStatus)
? task.ResolvedAtUtc ?? DateTimeOffset.UtcNow
: null;
return Task.FromResult(true);
}
public Task DeleteAsync(
long id,
CancellationToken cancellationToken = default)
{
int removed = _tasks.RemoveAll(t => t.Id == id);
return Task.FromResult(removed > 0);
}
private static string? Normalize(string? value) =>
string.IsNullOrWhiteSpace(value) ? null : value.Trim();
}