using AutoMapper;
using DamageAssesment.Api.Locations.Db;
using DamageAssesment.Api.Locations.Interfaces;
using Microsoft.EntityFrameworkCore;

namespace DamageAssesment.Api.Locations.Providers
{
    public class RegionsProvider : IRegionsProvider
    {
        private LocationDbContext locationDbContext;
        private ILogger<RegionsProvider> logger;
        private IMapper mapper;

        public RegionsProvider(LocationDbContext regionDbContext, ILogger<RegionsProvider> logger, IMapper mapper)
        {
            this.locationDbContext = regionDbContext;
            this.logger = logger;
            this.mapper = mapper;
          //  SeedData();
        }

        public async Task<(bool IsSuccess, Models.Region Region, string ErrorMessage)> GetRegionByIdAsync(int Id)
        {
            try
            {
                logger?.LogInformation("Get Regions from DB");
                var region = await locationDbContext.Regions.AsNoTracking().FirstOrDefaultAsync(s => s.Id == Id);

                if (region != null)
                {
                    logger?.LogInformation($"RegionId: {region.Id} Items found");
                    var result = mapper.Map<Db.Region, Models.Region>(region);
                    return (true, result, null);
                }
                return (false, null, "Not found");
            }
            catch (Exception ex)
            {
                logger?.LogError(ex.ToString());
                return (false, null, ex.Message);
            }
        }

        public async Task<(bool IsSuccess, IEnumerable<Models.Region> Regions, string ErrorMessage)> GetRegionsAsync()
        {
            try
            {
                logger?.LogInformation("Get all Regions from DB");
                var regions = await locationDbContext.Regions.AsNoTracking().ToListAsync();

                if (regions != null)
                {
                    logger?.LogInformation($"{regions.Count} Items(s) found");
                    var result = mapper.Map<IEnumerable<Db.Region>, IEnumerable<Models.Region>>(regions);
                    return (true, result, null);
                }
                return (false, null, "Not found");
            }
            catch (Exception ex)
            {
                logger?.LogError(ex.ToString());
                return (false, null, ex.Message);
            }
        }

        public async Task<(bool IsSuccess, Models.Region Region, string ErrorMessage)> PostRegionAsync(Models.Region region)
        {
            try
            {
                if (region != null)
                {
                    var _region = mapper.Map<Models.Region, Db.Region>(region);
                    locationDbContext.Regions.Add(_region);
                    await locationDbContext.SaveChangesAsync();
                    region.Id = _region.Id;
                    logger?.LogInformation($"{region} added successfuly");
                    return (true, region, "Successful");
                }
                else
                {
                    logger?.LogInformation($"{region} cannot be added");
                    return (false, null, "Region cannot be added");
                }
            }
            catch (Exception ex)
            {
                logger?.LogError(ex.ToString());
                return (false, null, ex.Message);
            }
        }

        public async Task<(bool IsSuccess, Models.Region Region, string ErrorMessage)> PutRegionAsync(int Id, Models.Region region)
        {
            try
            {
                if (region != null)
                {
                    var _region = await locationDbContext.Regions.AsNoTracking().Where(s => s.Id == Id).FirstOrDefaultAsync();

                    if (_region != null)
                    {
                        if (RegionExists(region.Id))
                        {
                            locationDbContext.Regions.Update(mapper.Map<Models.Region, Db.Region>(region));
                            locationDbContext.SaveChanges();
                            return (true, region, "Region updated Successfuly");
                        }
                        else
                        {
                            logger?.LogInformation($"RegionID: {Id} Not exists");
                            return (false, null, "Region not exists");
                        }
                    }
                    else
                    {
                        logger?.LogInformation($"RegionID: {Id} Not found");
                        return (false, null, "Not Found");
                    }

                }
                else
                {
                    logger?.LogInformation($"RegionID: {Id} Bad Request");
                    return (false, null, "Bad request");
                }
            }
            catch (Exception ex)
            {
                logger?.LogError(ex.ToString());
                return (false, null, ex.Message);
            }
        }

        public async Task<(bool IsSuccess, Models.Region Region, string ErrorMessage)> DeleteRegionAsync(int Id)
        {
            try
            {
                var region = await locationDbContext.Regions.AsNoTracking().Where(x => x.Id == Id).FirstOrDefaultAsync();

                if (region != null)
                {
                    locationDbContext.Regions.Remove(region);
                    locationDbContext.SaveChanges();
                    return (true, mapper.Map<Db.Region, Models.Region>(region), $"RegionId {Id} deleted Successfuly");
                }
                else
                {
                    logger?.LogInformation($"RegionID: {Id} Not found");
                    return (false, null, "Not Found");
                }
            }
            catch (Exception ex)
            {
                logger?.LogError(ex.ToString());
                return (false, null, ex.Message);
            }
        }

        private bool RegionExists(int id)
        {
            return locationDbContext.Regions.AsNoTracking().Count(e => e.Id == id) > 0;
        }

        public void SeedData()
        {
            if (!locationDbContext.Regions.Any())
            {
                locationDbContext.Regions.Add(new Db.Region() { Name = "North", Abbreviation = "N" });
                locationDbContext.Regions.Add(new Db.Region() { Name = "Central", Abbreviation = "C" });
                locationDbContext.Regions.Add(new Db.Region() { Name = "South", Abbreviation = "S" });
                locationDbContext.Regions.Add(new Db.Region() { Name = "Charter Schools", Abbreviation = "CS" });
                locationDbContext.Regions.Add(new Db.Region() { Name = "Alternate and Special Centers", Abbreviation = "AC" });
                locationDbContext.SaveChanges();
            }
        }
    }
}