using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.AspNetCore.Mvc;
using Siger.ApiCommon.Result;
using Siger.ApiCommon.Utilities;
using Siger.Middlelayer.Common;
using Siger.Middlelayer.Common.AppSettings;
using Siger.Middlelayer.Common.Extensions;
using Siger.Middlelayer.Common.Helpers;
using Siger.Middlelayer.Log;
using Siger.Middlelayer.Repository;
using Siger.Middlelayer.Repository.Data;
using Siger.Middlelayer.Repository.Entities;
using Siger.Middlelayer.Repository.Repositories.Interface;
using Siger.Middlelayer.Repository.Request;
using Siger.Middlelayer.Repository.Response;
using Siger.Middlelayer.Utility.Helpers;
using Siger.Middlelayer.Utility.ImportEntities;
using UnixTimeHelper = Siger.Middlelayer.Common.Helpers.UnixTimeHelper;

namespace Siger.ApiConfig.Controller
{
    public class UserController : BaseController
    {
        private readonly IUnitOfWork _unitOfWork;
        private readonly ISigerUserRepository _userRepository;
        private readonly ISigerUserPowerRepository _powerRepository;
        public UserController(IUnitOfWork unitOfWork, ISigerUserRepository userRepository, ISigerUserPowerRepository powerRepository)
        {
            _unitOfWork = unitOfWork;
            _userRepository = userRepository;
            _powerRepository = powerRepository;
        }

        [HttpGet]
        public IActionResult GetRootMenu()
        {
            var user = _userRepository.Get(UserId);
            if (user.type == (int) UserType.SuperAdmin)
            {
                var powers = _powerRepository.GetList(q => q.parent == "0" && q.status == (int) RowState.Valid && q.type == (int)PowerType.Web).OrderBy(q => q.sorting);
                return new ObjectResult(powers.Select(m => m.value.ToLower()));
            }
            var powsers = _userRepository.GetUserPowers(UserId, ProjectId).ToList();
            if (powsers.Any())
            {
                var parentPowers = powsers.Where(q => q.parent == "0" && q.type == (int)PowerType.Web).OrderBy(m => m.sorting).Select(m => m.value.ToLower());
                return new ObjectResult(parentPowers);
            }
            return new ObjectResult(new List<string>());
        }

        [HttpGet]
        public IActionResult GetRootModules()
        {
            var user = _userRepository.Get(UserId);
            if (user.type == (int)UserType.SuperAdmin)
            {
                var powers = _powerRepository.GetList(q => q.parent == "0" && q.status == (int)RowState.Valid && q.type == (int)PowerType.Web).OrderBy(q => q.sorting);
                return new ObjectResult(powers.Select(m => new ResponseNameCode
                {
                    name = m.name,
                    code = m.value
                }));
            }
            var powsers = _userRepository.GetUserPowers(UserId, ProjectId).ToList();
            if (powsers.Any())
            {
                var parentPowers = powsers.Where(q => q.parent == "0" && q.type == (int)PowerType.Web).OrderBy(m => m.sorting);
                return new ObjectResult(parentPowers.Select(m => new ResponseNameCode
                {
                    name = m.name,
                    code = m.value
                }));
            }
            return new ObjectResult(new List<string>());
        }

        [HttpGet]
        public IActionResult GetAppMenu()
        {
            var response = new List<ResponseGetAppMenu>();
            var powers = _userRepository.GetAppPowers(UserId, ProjectId);

            var parentPowers = powers.Where(q => q.parent == "0");
            foreach (var power in parentPowers)
            {
                var childPowers = powers.Where(q => q.parent == power.id.ToString());
                if (childPowers.Any())
                {
                    var entity = new ResponseGetAppMenu
                    {
                        name = power.name,
                        description = power.description,
                        sort = power.sorting,
                        permission = power.value
                    };
                    foreach (var childPower in childPowers)
                    {
                        entity.menus.Add(new ResponseGetAppMenu
                        {
                            name = childPower.name,
                            description = childPower.description,
                            sort = childPower.sorting,
                            permission = childPower.value
                        });
                    }
                    response.Add(entity);
                }
            }

            return new ObjectResult(response);
        }

        [HttpGet]
        public IActionResult GetModuleMenu(string moduleName)
        {
            var response = new List<ResponseGetUserPowers>();
            var parentPower = _powerRepository.Get(q => q.value == moduleName && q.status == (int) RowState.Valid && q.type == (int)PowerType.Web);
            if (parentPower == null)
            {
                return new ObjectResult(response);
            }

            var modules = License.ModuleStatuses;
            var module = modules?.FirstOrDefault(q => q.ModuleName.ToLower().Equals(parentPower.value));
            if (module?.IsValid == false)
            {
                throw new BadRequestException(CommonEnum.LicenseHasExpired);
            }
            var powsers = _userRepository.GetModulePowers(UserId, ProjectId, parentPower.id.ToString()).Where(q => q.type == (int)PowerType.Web).ToList();
            if (powsers.Any())
            {
                var parentPowers = powsers.Where(q => q.parent == parentPower.id.ToString());
                foreach (var sigerUserPower in parentPowers)
                {
                    var responsePower = new ResponseGetUserPowers
                    {
                        name = sigerUserPower.name,
                        permission = sigerUserPower.value,
                        icon = sigerUserPower.icon
                    };
                    var childPowers = powsers.Where(q => q.parent == sigerUserPower.id.ToString());
                    var menus = new List<ResponseGetUserPowers>();
                    foreach (var childPower in childPowers)
                    {
                        var child = new ResponseGetUserPowers
                        {
                            name = childPower.name,
                            permission = childPower.value,
                            target = childPower.value,
                            href = childPower.value,
                            icon = childPower.icon
                        };
                        menus.Add(child);
                    }

                    responsePower.menus = menus;
                    response.Add(responsePower);
                }
            }
            return new ObjectResult(response);
        }

        [HttpGet]
        public IActionResult GetMenu()
        {
            var response = new List<ResponseGetUserPowers>();

            var powsers = _userRepository.GetUserPowers(UserId, ProjectId).Where(q => q.type == (int)PowerType.Web).ToList();
            if (powsers.Any())
            {
                var parentPowers = powsers.Where(q => q.parent == "0");
                foreach (var sigerUserPower in parentPowers)
                {
                    var responsePower = new ResponseGetUserPowers
                    {
                        name = sigerUserPower.name,
                        permission = sigerUserPower.value
                    };
                    var childPowers = powsers.Where(q => q.parent == sigerUserPower.id.ToString());
                    var menus = new List<ResponseGetUserPowers>();
                    foreach (var childPower in childPowers)
                    {
                        var child = new ResponseGetUserPowers
                        {
                            name = childPower.name,
                            permission = childPower.value,
                            target = sigerUserPower.value,
                            href = childPower.value,
                        };

                        var childChildPowers = powsers.Where(q => q.parent == childPower.id.ToString());
                        foreach (var childChildPower in childChildPowers)
                        {
                            var childchild = new ResponseGetUserPowers
                            {
                                name = childChildPower.name,
                                permission = childChildPower.value,
                                target = sigerUserPower.value,
                                href = childChildPower.value,
                            };

                            child.menus.Add(childchild);
                        }

                        menus.Add(child);
                    }

                    responsePower.menus = menus;
                    response.Add(responsePower);
                }
            }
            return new ObjectResult(response);
        }

        [HttpGet]
        public IActionResult GetAppModules()
        {
            var user = _userRepository.Get(UserId);
            var modules = new List<siger_user_power>();
            if (user.type == (int)UserType.SuperAdmin)
            {
                modules = _powerRepository.GetList(q => q.parent == "0" && q.status == (int)RowState.Valid).ToList();
            }
            var powsers = _userRepository.GetUserPowers(UserId, ProjectId).ToList();
            if (powsers.Any())
            {
                modules = powsers.Where(q => q.parent == "0").ToList();
            }

            var responses = new List<ResponseGetAppModule>();
            if (modules.Any())
            {
                foreach (var power in modules)
                {
                    var response = new ResponseGetAppModule
                    {
                        module = power.value,
                    };

                    var subMudules = modules.Where(q => q.parent == power.id.ToString()
                                                                    && q.status == (int)RowState.Valid
                                                                    && q.type == (int)PowerType.App)
                        .OrderBy(m => m.sorting).ToList();
                    foreach (var subMudule in subMudules)
                    {
                        response.submod.Add(new ResponseGetSubAppModule
                        {
                            submodule = subMudule.name,
                            description = subMudule.description,
                            icon = subMudule.icon,
                            url = subMudule.value
                        });
                    }
                    responses.Add(response);
                }
            }

            return new ObjectResult(responses);
        }

        [HttpGet]
        public IActionResult ListUserInfo(int type)
        {
            var response = new List<ResponseGetUser>();

            var users = _userRepository.GetList(q => q.type == type && q.status == (int) RowState.Valid);

            foreach (var sigerUser in users)
            {
                var user = Mapper<siger_user, ResponseGetUser>.Map(sigerUser);
                if (string.IsNullOrEmpty(user.realname))
                {
                    user.realname = user.nickname;
                }
                response.Add(user);
            }

            return new ObjectResult(response);
        }

        [HttpGet]
        public IActionResult ListUserInfo3()
        {
            var response = new List<ResponseGetAdminsForDorpdown>();

            var list = _userRepository.GetList(q => q.status == (int)RowState.Valid && (q.type == (int)UserType.Admin || q.type == (int)UserType.SuperAdmin));
            foreach (var adminUser in list)
            {
                var user = Mapper<siger_user, ResponseGetAdminsForDorpdown>.Map(adminUser);
                if (string.IsNullOrEmpty(user.realname))
                {
                    user.realname = user.nickname;
                }
                response.Add(user);
            }

            return new ObjectResult(response);
        }

        [HttpGet]
        public IActionResult ListUserInfo4()
        {
            var response = new List<ResponseGetUser>();

            var users = _userRepository.GetList(q => q.status == (int)RowState.Valid && q.roleid != 4 && q.realname != "");

            foreach (var sigerUser in users)
            {
                var user = Mapper<siger_user, ResponseGetUser>.Map(sigerUser);
                if (string.IsNullOrEmpty(user.realname))
                {
                    user.realname = user.nickname;
                }
                response.Add(user);
            }

            return new ObjectResult(response);
        }

        [HttpGet]
        public IActionResult GetUsers(string sectionid, string usergroupid, string name, string sex, string work_code, int page = 1, int pagesize = PageSize)
        {
            var response = new List<ResponseGetProjectUser>();

            var section = sectionid.ToInt();
            var userGroup = usergroupid.ToInt();
            var gender = sex.ToInt();

            var list = _userRepository.GetPagedUsers(section, userGroup, name, gender, work_code, ProjectId,
                page, pagesize);

            foreach (var commonUser in list.Data)
            {
                response.Add(Mapper<ProjectUser, ResponseGetProjectUser>.Map(commonUser));
            }

            return new PagedObjectResult(response, list.Total, page, pagesize);
        }

        [HttpGet]
        public IActionResult GetUserList(int page = 1, int pagesize = PageSize)
        {
            var response = new List<ResponseGetAdmins>();

            var list = _userRepository.GetAdmins((int)UserType.Admin, page, pagesize);
            foreach (var adminUser in list.Data)
            {
                response.Add(Mapper<AdminUser, ResponseGetAdmins>.Map(adminUser));
            }

            return new PagedObjectResult(response, list.Total, page, pagesize);
        }

        [HttpPost]
        public IActionResult AddUser2([FromBody] RequestAddAdmin request)
        {
            var isExist = _userRepository.IsExist(q => q.mobile == request.mobile && q.status == (int)RowState.Valid);
            if (isExist)
            {
                throw new BadRequestException(RequestEnum.MobileHasExist);
            }
            var user = new siger_user();
            user.email = request.email;
            user.mobile = request.mobile;
            user.nickname = request.nickname;
            user.roleid = request.roleid;
            user.password = request.password;
            user.type = (int) UserType.Admin;
            user.power = request.power ?? string.Empty;
            user.graduate = request.graduate ?? string.Empty;

            _userRepository.Insert(user);
            if (_unitOfWork.Commit() > 0)
            {
                return new ObjectResult(CommonEnum.Succefull);
            }

            throw new BadRequestException(CommonEnum.SystemExcetion);
        }

        [HttpGet]
        public IActionResult GetUser2(int id)
        {
            var user = _userRepository.Get(id);
            if (user == null || user.status != (int)RowState.Valid)
            {
                throw new BadRequestException(RequestEnum.UserNotFound);
            }
            return new ObjectResult(user);
        }

        [HttpPost]
        public IActionResult EditUser2([FromBody] RequestUpdateAdmin request)
        {
            var user = _userRepository.Get(request.userid);
            if (user == null || user.status != (int)RowState.Valid)
            {
                throw new BadRequestException(RequestEnum.UserNotFound);
            }
            var isExist = _userRepository.IsExist(q => q.mobile == request.mobile && q.id != user.id && q.status == (int)RowState.Valid);
            if (isExist)
            {
                throw new BadRequestException(RequestEnum.MobileHasExist);
            }
            user.mobile = request.mobile;
            user.nickname = request.nickname;
            user.roleid = request.roleid;

            _userRepository.Update(user);
            if (_unitOfWork.Commit() > 0)
            {
                return new ObjectResult(CommonEnum.Succefull);
            }

            throw new BadRequestException(CommonEnum.SystemExcetion);
        }

        [HttpGet]
        public IActionResult ExportUsers(string sectionid, string usergroupid, string name, string sex, string work_code)
        {           
            var rootDir = FileSystemHelper.GetPhysicalFolders(FileSystemHelper.CommonFileSetting.PhysicalFolder, FileSystemHelper.ExportFileName);

            var section = sectionid.ToInt();
            var userGroup = usergroupid.ToInt();
            var gender = sex.ToInt();
            var users = _userRepository.ExportUsers(section, userGroup, name, gender, work_code, ProjectId);
            if (!users.Any())
            {
                throw new BadRequestException(RequestEnum.UserNotFound);
            }
            var temporaryFileName = $"userlist_{DateTime.Now:yyyyMMddHHmmss}.xlsx";
            var fileName = Path.Combine(rootDir, temporaryFileName);

            var helper = new EpPlusExcelHelper<UserList>(_userRepository.GetProjectLanguage(ProjectId));
            try
            {
                var userList = new List<UserList>();
                var index = 1;
                foreach (var projectUser in users)
                {
                    var user = new UserList
                    {
                        Work_code = projectUser.work_code,
                        Email = projectUser.work_email,
                        Fixed_line = projectUser.fixed_line,
                        Mobile = projectUser.mobile,
                        Name = projectUser.name,
                        Section = projectUser.sectiontitle,
                        Usergroup = projectUser.usergrouptitle,
                        Sex = projectUser.sex,
                        Create_time = projectUser.create_time == "0" 
                            ? ""
                            : UnixTimeHelper.ConvertStringDateTime(projectUser.create_time).ToString(ParameterConstant.DateFormat),
                        Rank = projectUser.rank,
                        No = index
                    };
                    userList.Add(user);

                    index++;
                }

                helper.GenerateExcel(userList, fileName);
                return new ObjectResult($"{FileSystemHelper.CommonFileSetting.RequestPath}/{FileSystemHelper.ExportFileName}/{temporaryFileName}");
            }
            catch (Exception e)
            {
                Logger.WriteLineError("ExportUsers failed, error: " + e.Message);
                throw new BadRequestException(RequestEnum.ExportFailed);
            }
            finally
            {
                helper.Dispose();
            }
        }
    }
}