using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using AsbCloudApp.Data.DailyReport;
using AsbCloudApp.Data.DailyReport.Blocks.Sign;
using AsbCloudApp.Data.DailyReport.Blocks.Subsystems;
using AsbCloudApp.Data.DailyReport.Blocks.TimeBalance;
using AsbCloudApp.Repositories;
using AsbCloudApp.Requests;
using AsbCloudDb;
using AsbCloudDb.Model;
using AsbCloudDb.Model.DailyReports;
using Mapster;
using Microsoft.EntityFrameworkCore;

namespace AsbCloudInfrastructure.Repository;

public class DailyReportRepository : CrudRepositoryBase<DailyReportDto, DailyReport>,
	IDailyReportRepository
{
	public DailyReportRepository(IAsbCloudDbContext dbContext)
		: base(dbContext)
	{
	}

	public async Task<IEnumerable<DailyReportDto>> GetAsync(int idWell, FileReportRequest request, CancellationToken cancellationToken)
	{
		var skip = request.Skip ?? 0;
		var take = request.Take ?? 10;

		var query = GetQuery().Where(d => d.IdWell == idWell);

		if (request.GeDate.HasValue)
			query = query.Where(d => d.Date >= request.GeDate.Value);
		
		if (request.LeDate.HasValue)
			query = query.Where(d => d.Date <= request.LeDate.Value);

		query = request.SortFields?.Any() == true ? 
			query.SortBy(request.SortFields) : 
			query.OrderBy(d => d.Date);

		var entities = await query
			.Skip(skip)
			.Take(take)
			.AsNoTracking()
			.ToArrayAsync(cancellationToken);

		var dtos = entities.Select(Convert);

		return dtos;
	}

	public async Task<DailyReportDto?> GetOrDefaultAsync(int idWell, DateOnly date, CancellationToken cancellationToken)
	{
		var entity = await GetQuery()
			.AsNoTracking()
			.SingleOrDefaultAsync(d => d.IdWell == idWell && d.Date == date, cancellationToken);

		return entity is null ? null : Convert(entity);
	}

	protected override DailyReportDto Convert(DailyReport src)
	{
		var dto = new DailyReportDto
		{
			Id = src.Id,
			IdWell = src.IdWell,
			DateLastUpdate = src.DateLastUpdate,
			Date = src.Date,
			SignBlock = src.SignBlock?.Adapt<SignBlockDto>(),
			TimeBalanceBlock = src.TimeBalanceBlock?.Adapt<TimeBalanceBlockDto>(),
			SubsystemBlock = src.SubsystemBlock?.Adapt<SubsystemBlockDto>()
		};
		
		return dto;
	}
}