using System.Collections.Generic;
using System.Linq;
using Microsoft.EntityFrameworkCore;
using Siger.Middlelayer.Common;
using Siger.Middlelayer.Repository.Data;
using Siger.Middlelayer.Repository.Entities;
using Siger.Middlelayer.Repository.Paged;
using Siger.Middlelayer.Repository.Repositories.Interface;
using Siger.Middlelayer.Repository.Request;
using Siger.Middlelayer.Repository.Response;

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

        public IPagedCollectionResult<UserGroupItem> GetUserGroupItems(int id, int projectid, int page, int pagesize)
        {
            var query = _context.siger_project_usergroup.Where(q =>
                q.status == (int) RowState.Valid && q.projectid == projectid
                                                 && q.sectionid == id);
            var querylist = from q in query
                join se in _context.siger_project_section on q.sectionid equals se.id
                where se.status == (int) RowState.Valid
                join p in _context.siger_project_usergroup on q.parentid equals p.id into par
                from p in par.DefaultIfEmpty()
                select new UserGroupItem
                {
                    id = q.id,
                    projectid = projectid,
                    sectionid = q.sectionid,
                    title = q.title,
                    nickname = q.nickname,
                    description = q.description,
                    create_mid = q.create_mid,
                    time = q.time,
                    create_ip = q.create_ip,
                    parentid = q.parentid,
                    status = q.status,
                    role_id = q.role_id ?? 0,
                    fatherUserGroupTitle = p != null ? p.title : "",
                    sectionname = se.title,
                    create_time = q.time
                };

            foreach (var userGroupItem in querylist)
            {
                userGroupItem.number = _context.siger_project_user
                    .Count(q => q.usergroupid == userGroupItem.id.ToString() && q.status == (int) RowState.Valid);
            }

            var totalCount = querylist.Count();
            var entities = querylist.OrderBy(q => q.parentid).Skip((page - 1) * pagesize).Take(pagesize).AsNoTracking()
                .ToList();

            var list = new List<UserGroupItem>();
            foreach (var userGroupItem in entities)
            {
                userGroupItem.number = _context.siger_project_user
                    .Count(q => q.usergroupid == userGroupItem.id.ToString() && q.status == (int)RowState.Valid);

                list.Add(userGroupItem);
            }
            return new PagedCollectionResult<UserGroupItem>(list, totalCount);
        }

        public UserGroupItem GetUserGroupItem(int id, int projectid)
        {
            var query = _context.siger_project_usergroup.Where(q =>
                q.status == (int)RowState.Valid && q.id == id);
            var querylist = from q in query
                            join se in _context.siger_project_section on q.sectionid equals se.id
                            where se.status == (int)RowState.Valid
                            join p in _context.siger_project_usergroup on q.parentid equals p.id into par
                            from p in par.DefaultIfEmpty()
                            select new UserGroupItem
                            {
                                id = q.id,
                                projectid = projectid,
                                sectionid = q.sectionid,
                                title = q.title,
                                nickname = q.nickname,
                                description = q.description,
                                create_mid = q.create_mid,
                                time = q.time,
                                create_ip = q.create_ip,
                                parentid = q.parentid,
                                status = q.status,
                                role_id = q.role_id ?? 0,
                                fatherUserGroupTitle = p != null ? p.title : "",
                                sectionname = se.title,
                                create_time = q.time
                            };
            var entity = querylist.FirstOrDefault();
            if (entity != null)
            {
                entity.number = _context.siger_project_user
                    .Count(q => q.usergroupid == entity.id.ToString() && q.status == (int)RowState.Valid);
            }

            return entity;
        }

        public AddUserGroupKeysEnum AddUserGroupKeys(int usergroupid, int projectid, IList<UserGroupKeys> userGroupKeys)
        {
            var keys = userGroupKeys.Select(q => q.fieldname);
            var isExist =
                _context.siger_project_user_info_key.Count(q =>
                    q.status == (int) RowState.Valid && keys.Contains(q.title) && q.projectid == projectid);
            if (isExist > 0)
            {
                return AddUserGroupKeysEnum.KeyHasExist;
            }
            var list = new List<siger_project_user_info_key>();
            foreach (var userGroupKey in userGroupKeys)
            {
                if (!string.IsNullOrWhiteSpace(userGroupKey.fieldname))
                {
                    var entity = new siger_project_user_info_key
                    {
                        status = (int) RowState.Valid,
                        title = userGroupKey.fieldname,
                        description = userGroupKey.fielddescription,
                        projectid = projectid,
                        unit = userGroupKey.fieldunit,
                        usergroupid = usergroupid
                    };
                    list.Add(entity);
                }
            }

            if (list.Count > 0)
            {
                _context.siger_project_user_info_key.AddRange(list);
                if (_context.SaveChanges() > 0)
                {
                    return AddUserGroupKeysEnum.Successful;
                }
            }

            return AddUserGroupKeysEnum.Failed;
        }

        public IEnumerable<UserGroupTree> GetProjectUserTreeBySectionId(int sectionid, int projectid)
        {
            var groups = new List<UserGroupTree>();
            var userGroups = _context.siger_project_usergroup.Where(q => q.sectionid == sectionid
                                                                        && q.projectid == projectid
                                                                        && q.status == (int) RowState.Valid);
            var maxUser = _context.siger_project_user.Max(t => t.id);
            var i = maxUser > 0 ? maxUser + 2 : 2;
            var pid = i - 1;
            foreach (var usergroup in userGroups)
            {
                var group = new UserGroupTree
                {
                    name = usergroup.title,
                    title = usergroup.title,
                    open = true,
                    id = i,
                    pid = pid,
                    spread = true
                };

                var users = _context.siger_project_user.Where(q => q.usergroupid == usergroup.id.ToString()
                                                                   && q.projectid == projectid
                                                                   && q.status == (int) RowState.Valid).ToList();
                var userList = new List<UserGroupTree>();
                foreach (var sigerProjectUser in users)
                {
                    userList.Add(new UserGroupTree
                    {
                        id = sigerProjectUser.id,
                        pid = i,
                        mid = sigerProjectUser.mid,
                        name = sigerProjectUser.name,
                        title = sigerProjectUser.name,
                        spread = true,
                        open = true
                    });
                }

                group.children = userList;

                groups.Add(group);
                i++;
            }

            return groups;
        }

        public IEnumerable<UserGroupTitle> GetGroupsUsers(int groupid)
        {
            var query = _context.siger_project_user_group.Where(q => q.groupid == groupid);

            var querylist = from a in query
                join b in _context.siger_project_user on a.mid equals b.mid
                where b.status == (int) RowState.Valid
                join c in _context.siger_project_usergroup on b.usergroupid equals c.id.ToString()
                where c.status == (int) RowState.Valid
                select new UserGroupTitle
                {
                    id = c.id,
                    name = b.name,
                    usergrouptitle = c.title
                };
            return querylist.ToList();
        }

        public IEnumerable<siger_project_user_group> GetUser_GroupsByMid(int mid)
        {
            return _context.siger_project_user_group.Where(q => q.mid == mid).ToList();
        }

        public IEnumerable<siger_project_user_group> GetUser_GroupsByGroupId(int groupid)
        {
            return _context.siger_project_user_group.Where(q => q.groupid == groupid).ToList();
        }

        public int AddUser_Group(IEnumerable<int> mids, int groupid)
        {
            var entities = new List<siger_project_user_group>();
            foreach (var mid in mids)
            {
                var entity = _context.siger_project_user_group.FirstOrDefault(q => q.mid == mid && q.groupid == groupid);
                if (entity == null)
                {
                    var group = new siger_project_user_group
                    {
                        groupid = groupid,
                        mid = mid
                    };
                    entities.Add(group);                    
                }
            }

            if (entities.Any())
            {
                _context.siger_project_user_group.AddRange(entities);
                return _context.SaveChanges();
            }

            return 0;
        }

        public int DeleteUser_Group(int mid, int groupid)
        {
            var entity = _context.siger_project_user_group.FirstOrDefault(q => q.mid == mid && q.groupid == groupid);
            if (entity != null)
            {
                _context.siger_project_user_group.Remove(entity);
                return _context.SaveChanges();
            }

            return 0;
        }

        public int DeleteUser_GroupByGroupId(int groupId)
        {
            var entities = _context.siger_project_user_group.Where(q => q.groupid == groupId);
            if (entities.Any())
            {
                _context.siger_project_user_group.RemoveRange(entities);
                return _context.SaveChanges();
            }

            return 0;
        }

        public IEnumerable<UserGroupSectionInfo> GetGroupSectionInfos(int projectId)
        {
            var query = from q in _context.siger_project_usergroup
                join s in _context.siger_project_section on q.sectionid equals s.id
                where q.status == (int) RowState.Valid && q.projectid == projectId
                select new UserGroupSectionInfo
                {
                    groupID = q.id,
                    groupTitle = q.title,
                    sectionID = q.sectionid,
                    sectionTitle = s.title
                };
            return query.AsEnumerable();
        }

        public IEnumerable<int> GetGroupSectionIds(int userId, int projectId)
        {
            var query = from q in _context.siger_project_station
                join g in _context.siger_project_user_group on q.groupid equals g.groupid
                join u in _context.siger_project_user on g.mid equals u.mid
                where q.status == (int) RowState.Valid && u.status == (int) RowState.Valid && u.projectid == projectId && g.mid == userId
                select q.sectionid;
            return query.AsEnumerable();
        }
    }
}
