using AutoMapper;
using Microsoft.EntityFrameworkCore.Internal;
using Performance.DtoModels;
using Performance.EntityModels;
using Performance.Repository;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Performance.Services.AllotCompute
{
    public class QueryDataService : IAutoInjection
    {
        private readonly LogManageService logManageService;
        private readonly PerforPersheetRepository persheetRepository;
        private readonly PerforImemployeeRepository imemployeeRepository;
        private readonly PerforImemployeeclinicRepository imemployeeclinicRepository;
        private readonly PerforImaccountbasicRepository imaccountbasicRepository;
        private readonly PerforImspecialunitRepository imspecialunitRepository;
        private readonly PerforImdataRepository imdataRepository;
        private readonly PerforImheaderRepository imheaderRepository;

        public QueryDataService(LogManageService logManageService,
            PerforPersheetRepository persheetRepository,
            PerforImemployeeRepository imemployeeRepository,
            PerforImemployeeclinicRepository imemployeeclinicRepository,
            PerforImaccountbasicRepository imaccountbasicRepository,
            PerforImspecialunitRepository imspecialunitRepository,
            PerforImdataRepository imdataRepository,
            PerforImheaderRepository imheaderRepository)
        {
            this.logManageService = logManageService;
            this.persheetRepository = persheetRepository;
            this.imemployeeRepository = imemployeeRepository;
            this.imemployeeclinicRepository = imemployeeclinicRepository;
            this.imaccountbasicRepository = imaccountbasicRepository;
            this.imspecialunitRepository = imspecialunitRepository;
            this.imdataRepository = imdataRepository;
            this.imheaderRepository = imheaderRepository;
        }

        public PerExcel QueryDataAndHeader(per_allot allot)
        {
            var sheetTypes = new List<int>
            {
                (int)SheetType.Employee,
                (int)SheetType.Income,
                (int)SheetType.OtherIncome,
                (int)SheetType.Expend,
                (int)SheetType.Overtime,
                (int)SheetType.Workload,
                (int)SheetType.SpecialUnit,
                (int)SheetType.AccountBasic,
                (int)SheetType.ClinicEmployee,
            };
            var sheets = persheetRepository.GetEntities(t => t.AllotID == allot.ID && sheetTypes.Contains(t.SheetType.Value));
            return Query(sheets, allot.ID);
        }

        private PerExcel Query(List<per_sheet> sheets, int allotId)
        {
            if (sheets == null || !sheets.Any())
                throw new Exception("未查询到数据");

            var allheader = imheaderRepository.GetEntities(t => sheets.Select(s => s.ID).Contains(t.SheetID.Value));
            if (allheader == null || !allheader.Any())
                throw new Exception("未获取到列");


            var perExcel = new PerExcel
            {
                PerSheet = new List<PerSheet>()
            };

            sheets.ForEach(t =>
            {
                perExcel.PerSheet.Add(new PerSheet
                {
                    SheetName = t.SheetName,
                    SheetType = (SheetType)t.SheetType,
                    PerData = new List<IPerData>(),
                    PerHeader = new List<PerHeader>()
                }); ;
            });

            foreach (var sheet in perExcel.PerSheet)
            {
                var imSheet = sheets.FirstOrDefault(t => t.SheetName == sheet.SheetName && t.SheetType == (int)sheet.SheetType);
                logManageService.WriteMsg("获取基础数据", $"开始查询数据 -- {sheet.SheetName}", 1, allotId, "ReceiveMessage", true);
                if (sheet.SheetType == SheetType.Employee)
                {
                    QueryHeader(allotId, imSheet.ID, allheader, sheet);
                    QueryEmployee(allotId, imSheet.ID, sheet);
                }
                else if (sheet.SheetType == SheetType.ClinicEmployee)
                {
                    QueryHeader(allotId, imSheet.ID, allheader, sheet);
                    QueryClinicEmployee(allotId, imSheet.ID, sheet);
                }
                else if (sheet.SheetType == SheetType.AccountBasic)
                {
                    QueryHeader(allotId, imSheet.ID, allheader, sheet);
                    QueryAccountBasic(allotId, imSheet.ID, sheet);
                }
                else if (sheet.SheetType == SheetType.SpecialUnit)
                {
                    QueryHeader(allotId, imSheet.ID, allheader, sheet);
                    QuerySpecialUnit(allotId, imSheet.ID, sheet);
                }
                else
                {
                    QueryHeader(allotId, imSheet.ID, allheader, sheet);
                    QueryCommon(allotId, imSheet.ID, sheet);
                }
            }
            logManageService.WriteMsg("保存基础数据", $"基础数据保存完成!", 1, allotId, "ReceiveMessage", true);
            return perExcel;
        }

        private void QueryEmployee(int allotId, int sheetId, PerSheet sheet)
        {
            var data = imemployeeRepository.GetEntities(t => t.AllotID == allotId && t.SheetID == sheetId);
            var sheetData = Mapper.Map<List<PerDataEmployee>>(data);
            if (sheetData != null && sheetData.Any())
                sheet.PerData.AddRange(sheetData);
        }

        private void QueryClinicEmployee(int allotId, int sheetId, PerSheet sheet)
        {
            var data = imemployeeclinicRepository.GetEntities(t => t.AllotID == allotId && t.SheetID == sheetId);
            var sheetData = Mapper.Map<List<PerDataClinicEmployee>>(data);
            if (sheetData != null && sheetData.Any())
                sheet.PerData.AddRange(sheetData);
        }

        private void QueryAccountBasic(int allotId, int sheetId, PerSheet sheet)
        {
            var data = imaccountbasicRepository.GetEntities(t => t.AllotID == allotId && t.SheetID == sheetId);
            var sheetData = Mapper.Map<List<PerDataAccountBaisc>>(data);
            if (sheetData != null && sheetData.Any())
                sheet.PerData.AddRange(sheetData);
        }

        private void QuerySpecialUnit(int allotId, int sheetId, PerSheet sheet)
        {
            var data = imspecialunitRepository.GetEntities(t => t.AllotID == allotId && t.SheetID == sheetId);
            var sheetData = Mapper.Map<List<PerDataSpecialUnit>>(data);
            if (sheetData != null && sheetData.Any())
                sheet.PerData.AddRange(sheetData);
        }

        private void QueryCommon(int allotId, int sheetId, PerSheet sheet)
        {
            var data = imdataRepository.GetEntities(t => t.AllotID == allotId && t.SheetID == sheetId);
            var sheetData = Mapper.Map<List<PerData>>(data);
            if (sheetData != null && sheetData.Any())
                sheet.PerData.AddRange(sheetData);
        }

        private void QueryHeader(int allotId, int sheetId, List<im_header> allheader, PerSheet sheet)
        {
            var perHeaders = new List<PerHeader>();
            var headers = allheader.Where(t => (t.ParentID ?? 0) == 0 && t.SheetID == sheetId).ToList();
            sheet.PerHeader = GetHeaderAndChild(headers, allheader, perHeaders);
        }

        private List<PerHeader> GetHeaderAndChild(List<im_header> headers, List<im_header> allheaders, List<PerHeader> perHeaders)
        {
            foreach (var header in headers)
            {
                var perHeader = Mapper.Map<PerHeader>(header);
                var children = allheaders.Where(t => t.ParentID == header.ID);
                if (children != null && children.Any())
                {
                    perHeader.Children = GetHeaderAndChild(children.ToList(), allheaders, perHeaders);
                }
                perHeaders.Add(perHeader);
            }

            return perHeaders;
        }
    }
}
