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

namespace Siger.Middlelayer.EsopRepository.Repositories
{
    internal class EsopProcessRepository : EsopRepositoryBase<siger_project_esop_process>, IEsopProcessRepository
    {
        private readonly ApiEsopDbContext _context;

        public EsopProcessRepository(ApiEsopDbContext context) : base(context)
        {
            _context = context;
        }

        public IPagedCollectionResult<ResponseGetEsopProcess> GetPagedList(int projectId, int page, int pagesize)
        {
            var querylist = from q in _context.siger_project_esop_process
                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
                where q.project_id == projectId && q.status == (int)RowState.Valid orderby q.create_time descending
                select new ResponseGetEsopProcess
                {
                    id = q.id,
                    create_time = q.create_time.ToString("yyyy-MM-dd"),
                    creator_name = u.name,
                    description = q.description,
                    name = q.name,
                    section_name = s.title,
                    status = q.isvalid
                };

            var totalCount = querylist.Count();
            var entities = querylist.Skip((page - 1) * pagesize).Take(pagesize).AsNoTracking().ToList();
            return new PagedCollectionResult<ResponseGetEsopProcess>(entities, totalCount);
        }

        public bool AddProcess(RequestAddProcess request, int userId, int projectId)
        {
            var entity = new siger_project_esop_process
            {
                name = request.name,
                description = request.description,
                section_id = request.section_id,
                create_time = DateTime.Now,
                creator_mid = userId,
                project_id = projectId
            };

            _context.siger_project_esop_process.Add(entity);
            if (_context.SaveChanges() > 0)
            {
                var index = 1;
                foreach (var userGroup in request.groups)
                {
                    var group = new siger_project_esop_process_set
                    {
                        approval_type = userGroup.approval_type,
                        approval_usergroupid = userGroup.approval_usergroupid,
                        approval_usertype = userGroup.approval_usertype,
                        process_id = entity.id,
                        step_number = index
                    };
                    _context.siger_project_esop_process_set.Add(group);
                    index++;
                }
            }
            return _context.SaveChanges() > 0;
        }

        public IEnumerable<siger_project_esop_process_set> GetEsopProcessSets(int processId)
        {
            return _context.siger_project_esop_process_set.Where(q => q.process_id == processId).AsEnumerable();
        }

        public IQueryable<siger_project_esop_process_set> GetAllEsopProcessSets()
        {
            return _context.siger_project_esop_process_set.Where(q => q.status != 0);
        }

        public void UpdateEsopProcessSets(int processId, IEnumerable<ApprovalUserGroup> groups)
        {
            var sets = _context.siger_project_esop_process_set.Where(q => q.process_id == processId).ToList();
            foreach (var processSet in sets)
            {
                _context.siger_project_esop_process_set.Remove(processSet);
            }

            var index = 1;
            foreach (var userGroup in groups)
            {
                var group = new siger_project_esop_process_set
                {
                    approval_type = userGroup.approval_type,
                    approval_usergroupid = userGroup.approval_usergroupid,
                    approval_usertype = userGroup.approval_usertype,
                    process_id = processId,
                    step_number = index
                };
                _context.siger_project_esop_process_set.Add(group);
                index ++;
            }

            _context.SaveChanges();
        }

        public IEnumerable<ResponseGetProcessFlow> GetProcessFlows(int process_id)
        {
            var sets = _context.siger_project_esop_process_set.Where(q => q.status == (int)RowState.Valid && q.process_id == process_id)
                .OrderBy(m => m.id).ToList();
            var responses = new List<ResponseGetProcessFlow>();
            if (!sets.Any())
            {
                return responses;
            }

            foreach (var set in sets)
            {
                var response = new ResponseGetProcessFlow
                {
                    process_id = set.process_id,
                    approval_type = set.approval_type,
                    approval_usergroupid = set.approval_usergroupid,
                    approval_usertype = set.approval_usertype,
                    step_number = set.step_number
                };
                var names = string.Empty;
                var ids = set.approval_usergroupid.Split(',');
                if (ids.Length > 0)
                {
                    foreach (var id in ids)
                    {
                        if (set.approval_usertype == 1) //岗位
                        {
                            var group = _context.siger_project_usergroup.FirstOrDefault(q => q.id == id.ToInt() && q.status == (int) RowState.Valid);
                            if (group != null)
                            {
                                names += group.title + ",";
                            }
                        }
                        else //人员
                        {
                            var user = _context.siger_project_user.FirstOrDefault(q => q.mid == id.ToInt() && q.status == (int)RowState.Valid);
                            if (user != null)
                            {
                                names += user.name + ",";
                            }
                        }
                    }
                }

                response.approval_usergroupnames = names.TrimEnd(',');
                responses.Add(response);
            }
            return responses;
        }

        public IEnumerable<ResponseApprovalHistory> GetResponseApprovalHistories(int document_id, int process_id)
        {
            var responses = new List<ResponseApprovalHistory>();
            var histories = _context.siger_project_esop_document_approval.Where(q =>
                q.document_id == document_id && q.status == (int) RowState.Valid).OrderBy(m => m.step_number).ToList();

            var flows = GetProcessFlows(process_id).ToList();
            if (!flows.Any())
            {
                return responses;
            }

            var approvalUsers = _context.siger_project_user.Where(q => histories.Select(m => m.creator_mid).Contains(q.mid) && q.status == (int) RowState.Valid);
            foreach (var flow in flows)
            {
                var response = new ResponseApprovalHistory { title = flow.approval_usergroupnames };
                
                var stepFlow = flows.FirstOrDefault(q => q.step_number == flow.step_number);
                if (stepFlow == null)
                {
                    continue;
                }
                var stepNumberHistories = histories.Where(q => q.step_number == flow.step_number).ToList();
                if (stepNumberHistories.Any())
                {
                    foreach (var numberHistory in stepNumberHistories)
                    {
                        var user = approvalUsers.FirstOrDefault(q => q.mid == numberHistory.creator_mid);
                        if (user == null)
                        {
                            continue;
                        }
                        response.ApprovalHistories.Add(new ApprovalHistory
                        {
                            audit_time = numberHistory.create_time.ToString("yyyy-MM-dd HH:mm:ss"),
                            status = numberHistory.approval_result,
                            info = user.name
                        });
                    }
                }
                responses.Add(response);
            }

            return responses;
        }
    }
}
