using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using Microsoft.EntityFrameworkCore;
using Siger.Middlelayer.AccRepository.Entities;
using Siger.Middlelayer.AccRepository.Repositories.Interface;
using Siger.Middlelayer.AccRepository.Response;
using Siger.Middlelayer.Common;
using Siger.Middlelayer.Common.Extensions;
using Siger.Middlelayer.Log;
using Siger.Middlelayer.Repository.Data.Acc;
using Siger.Middlelayer.Repository.Extensions;
using Siger.Middlelayer.Repository.Paged;
using Siger.Middlelayer.Utility.ImportEntities;

namespace Siger.Middlelayer.AccRepository.Repositories
{
    internal class AutomationFixtureToolsAssemblyRepository : AccRepositoryBase<siger_automation_fixture_tools_assembly>, IAutomationFixtureToolsAssemblyRepository
    {
        private ApiAccDbContext _context;
        public AutomationFixtureToolsAssemblyRepository(ApiAccDbContext context) : base(context)
        {
            _context = context;
        }

        public IPagedCollectionResult<ResponseAumationFixtureToolsAssemblys> GetPagedList(int category, string code, string name, string state, int projectid, int page, int pagesize, string toexcel = "")
        {
            var query = from q in _context.siger_automation_fixture_tools_assembly
                        join t1 in _context.siger_automation_fixture_tools on q.parent equals t1.guid into tt1
                        from t1 in tt1.DefaultIfEmpty()
                        join c1 in _context.siger_automation_fixture_tools_category on t1.category equals c1.guid into cc1
                        from c1 in cc1.DefaultIfEmpty()
                        join t2 in _context.siger_automation_fixture_tools on q.son equals t2.guid
                        join c2 in _context.siger_automation_fixture_tools_category on t2.category equals c2.guid
                        join u in _context.siger_project_user on q.updator equals u.mid into uu
                        from u in uu.DefaultIfEmpty()
                        join s in _context.siger_automation_fixture_tools_assembly on q.son equals s.parent into ss
                        from s in ss.DefaultIfEmpty()
                        join st2 in _context.siger_automation_fixture_tools on s.son equals st2.guid into stt2
                        from st2 in stt2.DefaultIfEmpty()
                        join sc2 in _context.siger_automation_fixture_tools_category on st2.category equals sc2.guid into scc2
                        from sc2 in scc2.DefaultIfEmpty()
                        where q.projectId == projectid && string.IsNullOrEmpty(q.parent)
                        select new ResponseAumationFixtureToolsAssemblys
                        {
                            id = q.id,
                            parentid = t1 == null ? 0 : t1.id,
                            parentname = t1.name ?? "",
                            fixturetoolid = t2.id,
                            name = t2.name,
                            code = t2.code,
                            partnumber = t2.partnumber,
                            specfication = t2.specification,
                            updator = u.name ?? "",
                            status = q.status,
                            fileurl = q.attachment,
                            filename = q.filename,
                            categoryid = c2.id,
                            category = c2.name,
                            updatetime = q.updatetime.HasValue && q.updatetime > DateTime.MinValue ? q.updatetime.Value.ToString(ParameterConstant.DateTimeFormat) : "",
                            cate_guid = c2.guid ?? "",
                            parentcate_guid = c1.guid ?? "",
                            parentguid = q.parent,
                            fixtureguid = q.son,
                            remark = q.remark,
                            parentcategoryid = c1 == null ? 0 : c1.id,
                            parentcategory = c1.name ?? "",
                            parentpartnumber = t1.partnumber ?? "",
                            parentspecfication = t1.specification ?? "",
                            parentcode = t1.code ?? "",
                            son_code = st2.code ?? "",
                            son_name = st2.name ?? "",
                            son_categoryid = sc2 == null ? 0 : sc2.id,
                            son_status = s == null ? -1 : s.status,
                        };
            Expression<Func<ResponseAumationFixtureToolsAssemblys, bool>> categoryExpression = f => true;
            if (category > 0)
            {
                categoryExpression = q => (q.categoryid == category || q.son_categoryid == category);
            }
            Expression<Func<ResponseAumationFixtureToolsAssemblys, bool>> codeExpression = f => true;
            if (!string.IsNullOrEmpty(code))
            {
                codeExpression = q => (q.code.Contains(code) || q.son_code.Contains(code));
            }
            Expression<Func<ResponseAumationFixtureToolsAssemblys, bool>> nameExpression = f => true;
            if (!string.IsNullOrEmpty(name))
            {
                nameExpression = q => (q.name.Contains(name) || q.son_name.Contains(name));
            }
            Expression<Func<ResponseAumationFixtureToolsAssemblys, bool>> stateExpression = f => true;
            if (!string.IsNullOrEmpty(state))
            {
                stateExpression = q => (q.status == state.ToInt() || q.son_status == state.ToInt());
            }
            var expression = categoryExpression.And(codeExpression).And(nameExpression).And(stateExpression);
            if (toexcel.ToInt() == 1)
            {
                var entities = query.Where(expression).GroupBy(q => q.fixtureguid).Select(q => q.FirstOrDefault()).OrderByDescending(q => q.id).AsNoTracking().ToList();
                return new PagedCollectionResult<ResponseAumationFixtureToolsAssemblys>(entities, entities.Count);
            }
            else
            {
                var entities = query.Where(expression).GroupBy(q=>q.fixtureguid).Select(q=>q.FirstOrDefault()).OrderByDescending(q => q.id).Skip((page - 1) * pagesize).Take(pagesize).AsNoTracking().ToList();
                var totalCount = query.Where(expression).GroupBy(q => q.fixtureguid).Select(q => q.FirstOrDefault()).Count();
                return new PagedCollectionResult<ResponseAumationFixtureToolsAssemblys>(entities, totalCount);
            }
        }

        public IEnumerable<ResponseAumationFixtureToolsAssembly> GetDetailList(string parent, int category, string code, string name, string state, int projectid)
        {
            var query = from q in _context.siger_automation_fixture_tools_assembly
                        join t1 in _context.siger_automation_fixture_tools on q.parent equals t1.guid into tt1
                        from t1 in tt1.DefaultIfEmpty()
                        join c1 in _context.siger_automation_fixture_tools_category on t1.category equals c1.guid
                        join t2 in _context.siger_automation_fixture_tools on q.son equals t2.guid
                        join c2 in _context.siger_automation_fixture_tools_category on t2.category equals c2.guid
                        join u in _context.siger_project_user on q.updator equals u.mid into uu
                        from u in uu.DefaultIfEmpty()
                        where q.projectId == projectid && q.parent == parent
                        select new ResponseAumationFixtureToolsAssembly
                        {
                            id = q.id,
                            parentid = t1 == null ? 0 : t1.id,
                            parentname = t1.name ?? "",
                            fixturetoolid = t2.id,
                            name = t2.name,
                            code = t2.code,
                            partnumber = t2.partnumber,
                            specfication = t2.specification,
                            updator = u.name ?? "",
                            status = q.status,
                            fileurl = q.attachment,
                            filename = q.filename,
                            categoryid = c2.id,
                            category = c2.name,
                            updatetime = q.updatetime.HasValue && q.updatetime > DateTime.MinValue ? q.updatetime.Value.ToString(ParameterConstant.DateTimeFormat) : "",
                            cate_guid = c2.guid ?? "",
                            parentcate_guid = c1.guid ?? "",
                            parentguid = q.parent,
                            fixtureguid = q.son,
                            remark = q.remark,
                            parentcategoryid = c1 == null ? 0 : c1.id,
                            parentcategory = c1.name ?? "",
                            parentpartnumber = t1.partnumber ?? "",
                            parentspecfication = t1.specification ?? "",
                            parentcode = t1.code ?? ""
                        };
            Expression<Func<ResponseAumationFixtureToolsAssembly, bool>> categoryExpression = f => true;
            if (category > 0)
            {
                categoryExpression = q => q.categoryid == category;
            }
            Expression<Func<ResponseAumationFixtureToolsAssembly, bool>> codeExpression = f => true;
            if (!string.IsNullOrEmpty(code))
            {
                codeExpression = q => q.code.Contains(code);
            }
            Expression<Func<ResponseAumationFixtureToolsAssembly, bool>> nameExpression = f => true;
            if (!string.IsNullOrEmpty(name))
            {
                nameExpression = q => q.name.Contains(name);
            }
            Expression<Func<ResponseAumationFixtureToolsAssembly, bool>> stateExpression = f => true;
            if (!string.IsNullOrEmpty(state))
            {
                stateExpression = q => q.status == state.ToInt();
            }
            var expression = categoryExpression.And(codeExpression).And(nameExpression).And(stateExpression);
            var entities = query.Where(expression).OrderByDescending(q => q.id).AsNoTracking().ToList();
            return entities;
        }


        public CommonImportResult ImportData(IEnumerable<FixtureToolsAssmeblyTemplate> list, int projectid, int userid)
        { 
            var errors = new List<string>();
            var rowIndex = 1;
            foreach (var item in list)
            {
                rowIndex++;

                var entities = new List<siger_automation_fixture_tools_assembly>();

                if (string.IsNullOrEmpty(item.FixtureTool) || string.IsNullOrEmpty(item.ParentFixtureTool))
                {
                    errors.Add($"{rowIndex},{(int)RequestEnum.ParameterMiss}");
                }
                if (item.ParentFixtureTool == item.FixtureTool)
                {
                    errors.Add($"{rowIndex},{(int)RequestEnum.ParentSonSame}");
                }
                var parent = _context.siger_automation_fixture_tools.FirstOrDefault(q => q.code == item.ParentFixtureTool && q.projectId == projectid);
                if (parent == null)
                {
                    errors.Add($"{rowIndex},{(int)RequestEnum.FixtureToolNotFound}");
                }
                var son = _context.siger_automation_fixture_tools.FirstOrDefault(q => q.code == item.FixtureTool && q.projectId == projectid);
                if (son == null)
                {
                    errors.Add($"{rowIndex},{(int)RequestEnum.FixtureToolNotFound}");
                }
                var parentGuid = parent.guid;
                var exsit = _context.siger_automation_fixture_tools_assembly.FirstOrDefault(q => q.projectId == projectid && q.son == son.guid && q.parent == parentGuid);
                if (exsit != null)
                {
                    errors.Add($"{rowIndex},{(int)RequestEnum.DataExist}");
                }
                if (list.Count(q => q.FixtureTool == item.FixtureTool && q.ParentFixtureTool == item.ParentFixtureTool) > 1)
                {
                    errors.Add($"{rowIndex},{(int)RequestEnum.DataExist}");
                }
                var parentExsit = _context.siger_automation_fixture_tools_assembly.FirstOrDefault(q => q.projectId == projectid && q.son == parentGuid);
                if (parentExsit != null && !string.IsNullOrEmpty(parentExsit.parent))
                {
                    errors.Add($"{rowIndex},{(int)RequestEnum.LevelCountError}");
                }

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

                if (_context.siger_automation_fixture_tools_assembly.FirstOrDefault(q => q.projectId == projectid && q.son == parentGuid) == null)
                {
                    var parentEntity = new siger_automation_fixture_tools_assembly
                    {
                        guid = Guid.NewGuid().ToString(),
                        parent = "",
                        son = parent.guid,
                        creator = userid,
                        createtime = DateTime.Now,
                        attachment = "",
                        filename = "",
                        projectId = projectid,
                        updatetime = DateTime.Now,
                        updator = userid,
                        status = item.Status == "可用" ? (int)RowState.Valid : (int)RowState.Invalid,
                        remark = item.Remark
                    };
                    _context.siger_automation_fixture_tools_assembly.Add(parentEntity);
                }

                var entity = new siger_automation_fixture_tools_assembly
                {
                    guid = Guid.NewGuid().ToString(),
                    parent = parentGuid,
                    son = son.guid,
                    creator = userid,
                    createtime = DateTime.Now,
                    attachment = "",
                    filename = "",
                    projectId = projectid,
                    updatetime = DateTime.Now,
                    updator = userid,
                    status = item.Status == "可用" ? (int)RowState.Valid : (int)RowState.Invalid,
                    remark = item.Remark
                };
                entities.Add(entity);

                try
                {
                    _context.siger_automation_fixture_tools_assembly.AddRange(entities);
                    _context.SaveChanges();                    
                }
                catch (Exception e)
                {
                    Logger.WriteLineError(e.Message);
                    throw;
                }
            }

            return new CommonImportResult(1, "1");
        }
    }
}
