using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Datory;
using GxPress.Common.AppOptions;
using GxPress.Common.Tools;
using GxPress.Entity.WorkCar;
using GxPress.Repository.Interface.WorkCar;
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Options;

namespace GxPress.Repository.Implement.WorkCar
{
    public class CarOrderRepository : ICarOrderRepository
    {
        private readonly Repository<CarOrder> _repository;

        public CarOrderRepository(IOptionsMonitor<DatabaseOptions> dbOptionsAccessor, IDistributedCache cache)
        {
            var databaseType = StringUtils.ToEnum<DatabaseType>(dbOptionsAccessor.CurrentValue.DatabaseType, DatabaseType.MySql);
            var database = new Database(databaseType, dbOptionsAccessor.CurrentValue.ConnectionString);
            _repository = new Repository<CarOrder>(database, cache);
        }

        public IDatabase Database => _repository.Database;
        public string TableName => _repository.TableName;
        public List<TableColumn> TableColumns => _repository.TableColumns;

        public async Task<int> InsertAsync(CarOrder item)
        {
            return await _repository.InsertAsync(item);
        }

        public async Task<IEnumerable<CarOrder>> GetListAsync(int carId)
        {
            return await _repository.GetAllAsync(Q.Where(nameof(CarOrder.CarId), carId));
        }

        public async Task<IEnumerable<int>> GetOrderedCarIds(int typeId, DateTime startDate, DateTime endDate)
        {
            var orders = await _repository.GetAllAsync(Q
                .Where(nameof(CarOrder.TypeId), typeId)
                .Where(nameof(CarOrder.EndDate), ">", endDate)
            );
            var carIds = new List<int>();
            foreach (var order in orders)
            {
                if (!CheckDate(startDate, endDate, order.StartDate, order.EndDate))
                {
                    carIds.Add(order.CarId);
                }
            }

            return carIds;
        }

        private bool CheckDate(DateTime a, DateTime b, DateTime x, DateTime y)
        {
            //讨论取a[B,E]与b1[B,E]不重叠部分：
            //2.a)当 (a.E<=b1.B)||(b1.E<=a.B) 时，无重叠，保留原先的a
            //时间无重叠                 
            if ((b < x) || (y < a))
            {
                return false;
            }
            //2.b)否则有重叠，去掉原先的a；
            //当 (a.B<b1.B)&&(b1.B<=a.E) 时，留下左边非重复段 a1[a.B,b1.B]
            //当 (a.B<=b1.E)&&(b1.E<a.E) 时，留下右边非重复段 a2[b1.E,a.E]
            //重叠
            if ((a < x) && (x <= b))
            {
                return true;
            }
            if ((a <= y) && (y < b))
            {
                return true;
            }
            if ((a < y) && (b == x))
            {
                return true;
            }
            return false;
        }


        public async Task<bool> DeleteAsync(int orderId)
        {
            return await _repository.DeleteAsync(orderId);
        }

        public async Task DeleteByCarIdAsync(int carId)
        {
            await _repository.DeleteAsync(Q.Where(nameof(CarOrder.CarId), carId));
        }
    }
}