using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using Microsoft.EntityFrameworkCore;
using Siger.Middlelayer.Common;
using Siger.Middlelayer.Common.Extensions;
using Siger.Middlelayer.Repository.Entities;
using Siger.Middlelayer.Repository.Extensions;
using Siger.Middlelayer.Repository.Paged;
using Siger.Middlelayer.Repository.Repositories.Interface;
using Siger.Middlelayer.Repository.Request;
using Siger.Middlelayer.Repository.Response;
using Siger.Middlelayer.Utility.ExcelImport;
using Siger.Middlelayer.Utility.ImportEntities;

namespace Siger.Middlelayer.Repository.Repositories
{
    internal class WorkingGroupRepository : ApiConfigRepositoryBase<siger_project_working_group>, IWorkingGroupRepository
    {
        private readonly ApiConfigDbContext _context;
        public WorkingGroupRepository(ApiConfigDbContext context) : base(context)
        {
            _context = context;
        }

        public IPagedCollectionResult<ResponseGetWorkingGroups> GetPagedCollectionResult(RequestGetWorkingGroups request, int projectId)
        {
            var queryList = from q in _context.siger_project_working_group
                join s in _context.siger_project_section on q.section_id equals s.id 
                join u in _context.siger_project_user on q.creator_mid equals u.mid into u1
                from uu in u1.DefaultIfEmpty()
                where q.project_id == projectId && q.status == (int) RowState.Valid
                select new ResponseGetWorkingGroups
                {
                    id = q.id,
                    create_time = q.create_time.ToString(ParameterConstant.DateTimeFormat),
                    start_date = q.start_date.ToString(ParameterConstant.DateFormat),
                    creator_name = uu != null ? uu.name : "",
                    sectionId = q.section_id,
                    sectionName = s.title,
                    shift_ids = q.shift_ids,
                    name = q.name,
                    user_mids = q.user_mids
                };
            Expression<Func<ResponseGetWorkingGroups, bool>> levelIdExpression = q => true;
            if (request.levelId > 0)
            {
                levelIdExpression = q => true;
            }
            Expression<Func<ResponseGetWorkingGroups, bool>> sectionIdExpression = q => true;
            if (request.sectionId > 0)
            {
                sectionIdExpression = q => q.sectionId == request.sectionId;
            }
            Expression<Func<ResponseGetWorkingGroups, bool>> shiftIdExpression = q => true;
            if (request.shiftId > 0)
            {
                shiftIdExpression = q => (q.shift_ids + "," ).Contains(request.shiftId + ",");
            }
            Expression<Func<ResponseGetWorkingGroups, bool>> groupIdExpression = q => true;
            if (request.workgroup_id > 0)
            {
                groupIdExpression = q => q.id == request.workgroup_id;
            }
            Expression<Func<ResponseGetWorkingGroups, bool>> userIdExpression = q => true;
            if (request.userId > 0)
            {
                userIdExpression = q => (q.user_mids + ",").Contains(request.userId + ",");
            }
            Expression<Func<ResponseGetWorkingGroups, bool>> timeExpression = q => true;
            if (!string.IsNullOrWhiteSpace(request.timerange))
            {
                var times = request.timerange.Split(new string[] { " - " }, StringSplitOptions.RemoveEmptyEntries);
                if (times.Length == 2)
                {
                    timeExpression = q =>
                        q.start_date.ToDateTime() >= times[0].ToDateTime() &&
                        q.start_date.ToDateTime() < times[1].ToDateTime().AddDays(1);
                }
            }

            var predicate = levelIdExpression.And(sectionIdExpression).And(groupIdExpression)
                .And(shiftIdExpression).And(userIdExpression).And(timeExpression);

            var totalCount = queryList.Count(predicate);
            var entities = queryList.Where(predicate).OrderBy(q => q.sectionName)
                .Skip((request.page - 1) * request.pagesize).Take(request.pagesize).AsNoTracking().ToList();

            return new PagedCollectionResult<ResponseGetWorkingGroups>(entities, totalCount);
        }

        public CommonImportResult ImportGroups(IEnumerable<WorkingGroupList> data, int projectId, int userId)
        {
            var errors = new List<string>();
            var entities = new List<siger_project_working_group>();
            var rowIndex = 1;
            var dataList = data.OrderBy(q => q.SectionName).ThenBy(q => q.GroupName).ToList();

            foreach (var item in dataList)
            {
                var workgroup = new siger_project_working_group();
                rowIndex++;
                //检查工号
                var user = _context.siger_project_user.FirstOrDefault(q => q.work_code == item.Code && q.projectid == projectId && q.status == (int) RowState.Valid);
                if (user == null)
                {
                    errors.Add($"{rowIndex},{Convert.ToString((int)RequestEnum.UserNotFound)}");
                }
                //检查部门
                var section = _context.siger_project_section.FirstOrDefault(q => q.title == item.SectionName && q.projectid == projectId && q.status == (int)RowState.Valid);
                if (section == null)
                {
                    errors.Add($"{rowIndex},{Convert.ToString((int)RequestEnum.SectionNotFound)}");
                }
                //检查班组是否存在
                var group = _context.siger_project_working_group.FirstOrDefault(q => q.name == item.GroupName && q.project_id == projectId && q.status == (int)RowState.Valid);
                if (group != null)
                {
                    errors.Add($"{rowIndex},{Convert.ToString((int)RequestEnum.WorkingGroupIsExist)}");
                }

                //相同班组名称下，排班必须相同
                var workgroups = data.Where(q => q.GroupName == item.GroupName && q.SectionName == item.SectionName);
                foreach (var groupList in workgroups)
                {
                    if (groupList.DateList.SequenceEqual(item.DateList) == false)
                    {
                        errors.Add($"{rowIndex},{Convert.ToString((int)RequestEnum.WorkingGroupIsInvalid)}");
                        break;
                    }
                }

                if (item.StartDate.ToDateTime() == DateTime.MinValue)
                {
                    errors.Add($"{rowIndex},{Convert.ToString((int)ImportEnum.DateTimeIsInValid)}");
                }

                var shiftids = string.Empty;
                //班次是否存在
                foreach (var shift in item.DateList)
                {
                    var entity = _context.siger_project_shift.FirstOrDefault(q =>
                        q.title == shift && q.projectid == projectId && q.status == (int) RowState.Valid);
                    if (entity == null)
                    {
                        errors.Add($"{rowIndex},{Convert.ToString((int)RequestEnum.ShiftNotFound)}");
                    }
                    else
                    {
                        shiftids += entity.id + ",";
                    }
                }

                if (errors.Any())
                {
                    return new CommonImportResult(0, string.Join(";", errors));
                }

                workgroup.name = item.GroupName;
                workgroup.interval = item.DateList.Count;
                workgroup.section_id = section.id;
                workgroup.user_mids = user.mid.ToString();
                workgroup.shift_ids = shiftids.TrimEnd(',');
                workgroup.start_date = item.StartDate.ToDateTime();

                entities.Add(workgroup);
            }

            //按照班组把人员分组
            var names = entities.Select(m => m.name).Distinct().ToList();
            foreach (var name in names)
            {
                var groups = entities.Where(q => q.name == name);
                if (!groups.Any())
                {
                    continue;
                }

                var group = groups.First();
                var entity = new siger_project_working_group
                {
                    project_id = projectId,
                    create_time = DateTime.Now,
                    creator_mid = userId,
                    interval = group.interval,
                    name = name,
                    section_id = group.section_id,
                    shift_ids = group.shift_ids,
                    user_mids = string.Join(",",groups.Select(m => m.user_mids).ToList()),
                    start_date = group.start_date
                };
                _context.siger_project_working_group.Add(entity);
            }
            try
            {
                _context.SaveChanges();
                return new CommonImportResult(1, "1");
            }
            catch
            {
                throw;
            }
        }
    }
}
