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

namespace Siger.Middlelayer.TpmRepository.Repositories
{
    /// <summary>
	/// SigerAndonExpectionType
	/// </summary>
    internal class SigerAndonExpectionTypeRepository : TpmRepositoryBase<siger_andon_expection_type>, ISigerAndonExpectionTypeRepository
    {
        private readonly ApiTpmDbContext _context;
        public SigerAndonExpectionTypeRepository(ApiTpmDbContext context) : base(context)
        {
            _context = context;
        }

        public IPagedCollectionResult<ResponseAndonExpection> GetData(string name, int ProjectId, int page, int pagesize)
        {
            Expression<Func<ResponseAndonExpection, bool>> funName = f => true;
            if (!string.IsNullOrEmpty(name))
            {
                funName = f => f.title.Contains(name);
            }
            var query = from type in _context.siger_andon_expection_type
                        join ad in _context.siger_andon_process on type.process_code equals ad.code into temp
                        from ad in temp.DefaultIfEmpty()
                        join gp in _context.siger_project_usergroup on type.usergroup equals gp.id into gr
                        from gp in gr.DefaultIfEmpty()
                        join gps in _context.siger_project_usergroup on type.second_usergroup equals gps.id into grs
                        from gps in grs.DefaultIfEmpty()
                        where type.status == (int)RowState.Valid && type.projectid.Equals(ProjectId)
                        select new ResponseAndonExpection
                        {
                            title = type.name,
                            level = type.level,
                            parent = type.parent,
                            process_code = type.process_code,
                            usergroup = type.usergroup,
                            process_name = ad.name,
                            usergroup_name = gp.title,
                            second_usergroup = gps == null ? 0 : gps.id,
                            secondusergroup_name = gps == null ? "" : gps.title,
                            errorlevel = type.errorlevel,
                            errorlevelname = "L" + type.errorlevel,
                            id = type.id,
                            is_caloee = type.is_caloee,
                            is_passprocess = type.is_passprocess
                        };
            var predicate = funName;
            var count = query.Count(predicate);
            var entities = query.Where(predicate).Skip((page - 1) * pagesize).Take(pagesize).AsNoTracking().ToList();
            return new PagedCollectionResult<ResponseAndonExpection>(entities, count);
        }

        public List<ResponseAndonExpection> GetTreeData(string name, int ProjectId)
        {
            var model = GetData(name, ProjectId, 1, 9999).Data.ToList();
            var data = GetTree(0, model);
            return data;
        }

        private List<ResponseAndonExpection> GetTree(int parent, List<ResponseAndonExpection> model)
        {
            var ret = new List<ResponseAndonExpection>();
            var query = model.Where(f => f.parent.Equals(parent));
            if (query != null && query.Any())
            {
                foreach (var item in query)
                {
                    item.children = GetTree(item.id, model);
                    item.value = item.id;
                    item.label = item.title;
                    ret.Add(item);
                }
            }
            return ret;
        }

        /// <summary>
        /// 查询所有相关安灯异常
        /// </summary>
        /// <param name="id">起始id</param>
        /// <param name="projectid"></param>
        /// <returns></returns>
        public List<int> GetAllExpectionlevel(int id, int projectid)
        {
            var ret = new List<int>();
            ret.Add(id);
            var condition = new List<int>();
            condition.Add(id);
            while (true)
            {
                var query = GetSonExpection(condition, projectid);
                if (!query.Any())
                {
                    break;
                }
                condition = query.Select(s => s.id).ToList();
                ret.AddRange(condition);
            }
            return ret;
        }
        private List<siger_andon_expection_type> GetSonExpection(List<int> parent, int projectid)
        {
            return _context.siger_andon_expection_type.Where(f => f.projectid == projectid && f.status != 0 && parent.Contains(f.parent)).ToList();
        }

        public CommonImportResult ImportAndonExpection(IEnumerable<ImportAndonExpection> types, int projectId)
        {
            var errors = new List<string>();
            var rowIndex = 0;
            //same level
            if (!types.Any())
            {
                errors.Add($"{rowIndex++},{(int)CommonEnum.NoDataForExport}");
                return new CommonImportResult(0, string.Join(";", errors));
            }
            if (types.Select(s => s.level).Distinct().ToList().Count > 1)
            {
                errors.Add($"{rowIndex++},{(int)RequestEnum.AndonExpectionLevelNotSame}");
                return new CommonImportResult(0, string.Join(";", errors));
            }
            var level = types.First().level;
            if (level < 0 || level > 3)
            {
                errors.Add($"{rowIndex++},{(int)RequestEnum.AndonExpectionLevelError}");
                return new CommonImportResult(0, string.Join(";", errors));
            }
            var usergroupList = _context.siger_project_usergroup.Where(f => f.projectid == projectId && f.status != 0).ToList();
            var expectionList = _context.siger_andon_expection_type.Where(f => f.projectid == projectId && f.status != 0 && f.level <= level).ToList();
            var processList = _context.siger_andon_process.Where(f => f.projectid == projectId && f.status != 0).ToList();
            foreach (var item in types)
            {
                rowIndex++;
                if (expectionList.Any(f => f.name.Equals(item.name)))
                {
                    errors.Add($"{rowIndex},{(int)RequestEnum.AndonExpectionExist}");
                    continue;
                }
                if (!string.IsNullOrEmpty(item.parent_name) && !expectionList.Any(f => f.name.Equals(item.parent_name)))
                {
                    errors.Add($"{rowIndex},{(int)RequestEnum.AndonParentExpectionNotExist}");
                    continue;
                }
                if (level > 1)
                {
                    var parent = expectionList.FirstOrDefault(f => f.name.Equals(item.parent_name));
                    if (parent == null)
                    {
                        errors.Add($"{rowIndex++},{(int)RequestEnum.AndonParentExpectionNotExist}");
                        continue;
                    }
                    if (parent.level + 1 != item.level)
                    {
                        errors.Add($"{rowIndex},{(int)RequestEnum.ErrorExpectionLevel}");
                        continue;
                    }
                    if (!string.IsNullOrEmpty(item.process) && !processList.Any(f => f.name.Equals(item.process)))
                    {
                        errors.Add($"{rowIndex},{(int)RequestEnum.AndonExpectionProcessNotExist}");
                        continue;
                    }
                    if (!string.IsNullOrEmpty(item.usergroup_name) && !usergroupList.Any(f => f.title.Equals(item.usergroup_name)))
                    {
                        errors.Add($"{rowIndex},{(int)RequestEnum.AndonExpectionUserGroupNotExist}");
                        continue;
                    }
                    if (!string.IsNullOrEmpty(item.second_usergroup_name) && !usergroupList.Any(f => f.title.Equals(item.second_usergroup_name)))
                    {
                        errors.Add($"{rowIndex},{(int)RequestEnum.AndonExpectionUserGroupNotExist}");
                        continue;
                    }
                }
                if (types.Count(a => a.name == item.name) > 1)
                {
                    errors.Add($"{rowIndex},{(int)CommonEnum.RecordExits}");
                    continue;
                }
            }

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

            //insert
            foreach (var item in types)
            {
                var parent = 0;
                var process = string.Empty;
                var usergroup = 0;
                var secondusergroup = 0;
                if (!string.IsNullOrEmpty(item.parent_name))
                {
                    parent = expectionList.First(f => f.name.Equals(item.parent_name)).id;
                }
                if (!string.IsNullOrEmpty(item.process) && level > 1)
                {
                    process = processList.First(f => f.name.Equals(item.process)).code;
                }
                if (!string.IsNullOrEmpty(item.usergroup_name) && level > 1)
                {
                    usergroup = usergroupList.First(f => f.title.Equals(item.usergroup_name)).id;
                }
                if (!string.IsNullOrEmpty(item.second_usergroup_name) && level > 1)
                {
                    secondusergroup = usergroupList.First(f => f.title.Equals(item.second_usergroup_name)).id;
                }
                var model = new siger_andon_expection_type
                {
                    parent = parent,
                    errorlevel = item.errorlevel,
                    is_caloee = 1,
                    is_passprocess = 0,
                    name = item.name,
                    level = item.level,
                    process_code = process,
                    usergroup = usergroup,
                    second_usergroup = secondusergroup,
                    projectid = projectId,
                    status = (int)RowState.Valid
                };
                _context.siger_andon_expection_type.Add(model);
            }
            if (_context.SaveChanges() <= 0)
            {
                return new CommonImportResult(0, CommonEnum.Fail.ToString());
            }
            return new CommonImportResult(1, "1");
        }

    }
}
