using AsbCloudApp.Data;
using AsbCloudApp.Services;
using AsbCloudDb.Model;
using AsbCloudInfrastructure.Services.Cache;
using AutoMapper;

namespace AsbCloudInfrastructure.Services
{
    public class TelemetryService : ITelemetryService
    {
        private readonly IMapper mapper;
        private readonly CacheTable<Telemetry> cacheTelemetry;
        private readonly CacheTable<Well> cacheWells;

        public TelemetryService(IAsbCloudDbContext db, CacheDb cacheDb, MapperConfiguration mapperConfiguration)
        {
            mapper = mapperConfiguration.CreateMapper();
            cacheTelemetry = cacheDb.GetCachedTable<Telemetry>((AsbCloudDbContext)db);
            cacheWells = cacheDb.GetCachedTable<Well>((AsbCloudDbContext)db);
        }

        public int GetOrCreateTemetryIdByUid(string uid)
            => GetOrCreateTelemetryByUid(uid).Id;

        public int? GetWellIdByTelemetryUid(string uid)
            => GetWellByTelemetryUid(uid)?.Id;

        public double GetTimezoneOffsetByTelemetryId(int idTelemetry) =>
            cacheTelemetry.FirstOrDefault(t => t.Id == idTelemetry).Info.TimeZoneOffsetTotalHours;

        public void UpdateInfo(string uid, TelemetryInfoDto info)
        {
            var telemetry = GetOrCreateTelemetryByUid(uid);
            telemetry.Info = mapper.Map<TelemetryInfo>(info);
            cacheTelemetry.Upsert(telemetry);
        }

        public Telemetry GetTelemetryByWellId(int wellId)
        {
            var well = cacheWells.FirstOrDefault(w => w.Id == wellId);
            if (well is null)
                return null;

            var telemetry = cacheTelemetry.FirstOrDefault(t => t.Id == well.Id);
            if (telemetry is null)
                return null;

            return telemetry;
        }

        private Well GetWellByTelemetryUid(string uid)
        {
            var tele = cacheTelemetry.FirstOrDefault(t => t.RemoteUid == uid, RefreshMode.IfResultEmpty);
            if (tele is null)
                return null;

            return cacheWells.FirstOrDefault(w => w?.IdTelemetry == tele.Id);
        }

        private Telemetry GetOrCreateTelemetryByUid(string uid)
            => cacheTelemetry.FirstOrDefault(t => t.RemoteUid == uid, RefreshMode.IfResultEmpty)
                ?? cacheTelemetry.Insert(new Telemetry { RemoteUid = uid, });

    }
}