using System.Linq.Dynamic.Core;

using CSharpFunctionalExtensions;

using Microsoft.EntityFrameworkCore;

using Monitoring.Core.Domain.AssetManagement;
using Monitoring.Core.Domain.ServiceOrganizationManagement;
using Monitoring.Core.Domain.UserPrimitives;
using Monitoring.Features.Assets;
using Monitoring.Infrastructure.Data;

namespace Monitoring.Repositories;

public class AssetRepository(
	DataContext dataContext
)
{
	public Task<AssetModel?> Get(AssetId id, UserId? userId, CancellationToken cancellationToken)
	{
		var query = dataContext.Assets
			.Where(x => x.Id == id);

		if (userId is not null)
		{
			query = query.Where(x => x.Organization.Members.Any(member => member.UserId == userId));
		}

		return query
			.Select(AssetModel.FromEntity)
			.FirstOrDefaultAsync(cancellationToken);
	}

	internal async Task<Result<Asset>> Add(
		Asset asset,
		CancellationToken cancellationToken)
	{
		try
		{
			var existingAsset = await dataContext.Assets
				.FirstOrDefaultAsync(
					x => x.Id == asset.Id
						|| (x.Name == asset.Name &&
							x.OrganizationId == asset.OrganizationId),
					cancellationToken);
			if (existingAsset is not null)
			{
				return Result.Failure<Asset>("Asset already exists");
			}

			await dataContext.Assets.AddAsync(asset, cancellationToken);
			await dataContext.SaveChangesAsync(cancellationToken);

			return Result.Success(asset);
		}
		catch (Exception e)
		{
			return Result.Failure<Asset>(e.Message);
		}
	}

	internal async Task Update(
		Asset asset,
		byte[] rowVersion,
		CancellationToken cancellationToken)
	{
		dataContext.Assets.Update(asset);
		dataContext.Entry(asset).OriginalValues["RowVersion"] = rowVersion;

		await dataContext.SaveChangesAsync(cancellationToken);

	}

	public async Task<List<Asset>> GetAssetsByServiceOrganizationIdAsync(Guid serviceOrganizationId, CancellationToken cancellationToken)
{
    var sid = new ServiceOrganizationId(serviceOrganizationId);
    return await dataContext.Assets
      .Where(x => x.ServiceOrganizationId != null && x.ServiceOrganizationId == sid)
      .ToListAsync(cancellationToken);
}
}