using Microsoft.EntityFrameworkCore;
using ZB.MOM.WW.ScadaBridge.Commons.Entities.Schemas;
using ZB.MOM.WW.ScadaBridge.Commons.Interfaces.Repositories;

namespace ZB.MOM.WW.ScadaBridge.ConfigurationDatabase.Repositories;

/// <summary>
/// EF Core implementation of <see cref="ISharedSchemaRepository"/> over the central
/// <c>SharedSchemas</c> JSON-Schema library table. Plain tracked EF
/// reads/writes against the shared <see cref="ScadaBridgeDbContext"/>, saving on each
/// mutating call — mirrors the <c>SecuredWriteRepository</c> data-access shape.
/// </summary>
public class SharedSchemaRepository : ISharedSchemaRepository
{
    private readonly ScadaBridgeDbContext _context;

    /// <summary>
    /// Initializes a new instance of the <see cref="SharedSchemaRepository"/> class.
    /// </summary>
    /// <param name="context">The EF Core database context.</param>
    public SharedSchemaRepository(ScadaBridgeDbContext context)
    {
        _context = context ?? throw new ArgumentNullException(nameof(context));
    }

    /// <inheritdoc />
    public async Task<int> AddAsync(SharedSchema schema, CancellationToken ct = default)
    {
        ArgumentNullException.ThrowIfNull(schema);

        await _context.Set<SharedSchema>().AddAsync(schema, ct);
        await _context.SaveChangesAsync(ct);
        return schema.Id;
    }

    /// <inheritdoc />
    public async Task<SharedSchema?> GetByIdAsync(int id, CancellationToken ct = default)
    {
        return await _context.Set<SharedSchema>().FindAsync([id], ct);
    }

    /// <inheritdoc />
    public async Task<SharedSchema?> GetByNameAsync(string name, CancellationToken ct = default)
    {
        return await _context.Set<SharedSchema>()
            .AsNoTracking()
            .FirstOrDefaultAsync(s => s.Name == name, ct);
    }

    /// <inheritdoc />
    public async Task<IReadOnlyList<SharedSchema>> ListAsync(CancellationToken ct = default)
    {
        return await _context.Set<SharedSchema>()
            .AsNoTracking()
            .OrderBy(s => s.Name)
            .ToListAsync(ct);
    }

    /// <inheritdoc />
    public async Task UpdateAsync(SharedSchema schema, CancellationToken ct = default)
    {
        ArgumentNullException.ThrowIfNull(schema);

        _context.Set<SharedSchema>().Update(schema);
        await _context.SaveChangesAsync(ct);
    }

    /// <inheritdoc />
    public async Task DeleteAsync(int id, CancellationToken ct = default)
    {
        var entity = await _context.Set<SharedSchema>().FindAsync([id], ct);
        if (entity is null)
        {
            return;
        }

        _context.Set<SharedSchema>().Remove(entity);
        await _context.SaveChangesAsync(ct);
    }
}
