using AsbCloudApp.Data;
using AsbCloudApp.Services;
using AsbCloudDb.Model;
using AsbCloudInfrastructure.Services.Cache;
using Mapster;
using System;
using System.Collections.Generic;
using System.Linq;

namespace AsbCloudInfrastructure.Services
{
    public class WellService : IWellService
    {
        private readonly IAsbCloudDbContext db;
        private readonly ITelemetryTracker telemetryTracker;
        private readonly CacheTable<RelationCompanyWell> cacheRelationCompaniesWells;

        public WellService(IAsbCloudDbContext db, ITelemetryTracker telemetryTracker, CacheDb cacheDb)
        {
            this.db = db;
            this.telemetryTracker = telemetryTracker;
            cacheRelationCompaniesWells = cacheDb.GetCachedTable<RelationCompanyWell>((AsbCloudDbContext)db);
        }

        public IEnumerable<WellDto> GetTransmittingWells(int idCompany)
        {
            var wells = new List<Well>();
            IEnumerable<string> activeTelemetriesUids = telemetryTracker.GetTransmittingTelemetryUids();
            if (activeTelemetriesUids.Any())
            {
                wells = db.GetWellsForCompany(idCompany)
                    .Where(w => activeTelemetriesUids.Contains(w.Telemetry.RemoteUid))
                    .ToList();
            }
            return wells.Select(w => From(w));
        }

        public IEnumerable<WellDto> GetWellsByCompany(int idCompany)
        {
            var wells = db.GetWellsForCompany(idCompany).ToList();
            return wells.Select(w => From(w));
        }

        public bool IsCompanyInvolvedInWell(int idCompany, int idWell)
         => cacheRelationCompaniesWells.Contains(r => r.IdWell == idWell && r.IdCompany == idCompany);
        
        public IEnumerable<WellSectionDto> GetSections(int idWell)
        {
            var entities = db
                .WellSections
                .Where(s => s.IdWell == idWell)
                .ToList();

            var dtos = entities.Adapt<WellSection, WellSectionDto>(
                (s, d) => { d.SectionType = s.WellSectionType.Caption;});
            
            return dtos;
        }

        public IEnumerable<WellOperationDto> GetOperations(int idWell)
        {
            var entities = db
                .WellOperations
                .Where(o => o.IdWell == idWell)
                .ToList();

            var dtos = entities.Adapt<WellOperationDto>();

            return dtos;
        }

        private static WellDto From(Well well)
        {
            var wellDto = new WellDto
            {
                Id = well.Id,
                Caption = well.Caption,
                Cluster = well.Cluster.Caption,
                Deposit = well.Cluster.Deposit.Caption,
            };

            return wellDto;
        }
    }
}