using Avalonia.Collections;

using InkForge.Data;

using Microsoft.EntityFrameworkCore;

namespace InkForge.Desktop.Models;

public class NoteStore(IDbContextFactory<NoteDbContext> dbContextFactory)
{
	public AvaloniaDictionary<int, Note> Notes { get; } = [];

	public async ValueTask Load()
	{
		await using var dbContext = await dbContextFactory.CreateDbContextAsync().ConfigureAwait(false);
		Notes.Clear();
		await foreach (var note in dbContext.Notes.AsAsyncEnumerable().ConfigureAwait(false))
		{
			Notes.Add(note.Id, Map(note));
		}
	}

	public void AddNote(Note note)
	{
		using var dbContext = dbContextFactory.CreateDbContext();
		var entity = Map(note);
		var entry = dbContext.Notes.Add(entity);

		dbContext.SaveChanges();
	}

	public Note? GetById(int id)
	{
		if (!Notes.TryGetValue(id, out var note))
		{
			using var dbContext = dbContextFactory.CreateDbContext();
			if (dbContext.Notes.Find(id) is not { } dbNote)
			{
				return null;
			}

			Notes.Add(id, note = Map(dbNote));
		}

		return note;
	}

	private NoteEntity Map(Note note)
	{
		return new()
		{
			Id = note.Id,
			Value = new()
			{
				Name = note.Name,
				Created = note.CreatedTime,
				Updated = note.UpdatedTime,
			},
			Parent = note.ParentId switch
			{
				{ } parentId => new()
				{
					Id = parentId
				},
				_ => null
			},
		};
	}

	private Note Map(NoteEntity entity)
	{
		return new()
		{
			Id = entity.Id,
			Name = entity.Value.Name,
			CreatedTime = entity.Value.Created,
			UpdatedTime = entity.Value.Updated,
			ParentId = entity.Parent?.Id
		};
	}
}
