using Dapper;
using Ewide.Core;
using Ewide.Core.Extension;
using Furion.DatabaseAccessor;
using Furion.DatabaseAccessor.Extensions;
using Furion.DependencyInjection;
using Furion.DynamicApiController;
using Furion.FriendlyException;
using Mapster;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Ewide.Application.Service
{
    /// <summary>
    /// 选房相关
    /// </summary>
    [ApiDescriptionSettings(Name = "HouseSelector", Order = 180)]
    public class HouseSelectorService : IHouseSelectorService, IDynamicApiController, ITransient
    {
        private readonly IUserManager _userManager;
        private readonly IDapperRepository _dapperRep;

        private readonly IRepository<BsHouseMemberRelation> _bsHouseMemberRelationRep;
        private readonly IRepository<BsHouseCode> _bsHouseCodeRep;
        private readonly IRepository<BsHouseTask> _bsHouseTaskRep;
        private readonly IRepository<SysUser> _sysUserRep;
        private readonly IHouseZoneService _houseZoneService;

        private readonly IHouseLogService _houseLogService;

        public HouseSelectorService(
            IUserManager userManager,
            IDapperRepository dapperRep,
            IRepository<BsHouseMemberRelation> bsHouseMemberRelationRep,
            IRepository<BsHouseCode> bsHouseCodeRep,
            IRepository<BsHouseTask> bsHouseTaskRep,
            IRepository<SysUser> sysUserRep,
            IHouseZoneService houseZoneService,
            IHouseLogService houseLogService
        )
        {
            _userManager = userManager;

            _dapperRep = dapperRep;
            _bsHouseMemberRelationRep = bsHouseMemberRelationRep;
            _bsHouseCodeRep = bsHouseCodeRep;
            _bsHouseTaskRep = bsHouseTaskRep;
            _sysUserRep = sysUserRep;
            _houseZoneService = houseZoneService;

            _houseLogService = houseLogService;
        }

        /// <summary>
        /// 获取人员允许绑定的房屋编码列表
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("/houseSelector/selectorPage")]
        public async Task<dynamic> HouseSelectorList([FromBody] QueryHouseSelectorInput input)
        {
            var sql = @"SELECT 
	HC.*,AA.Name AreaName,RA.Name RoadName,CA.Name CommName,Proj.AreaCode,Proj.Note,CONCAT(Proj.`Name`, IFNULL(CONCAT('(',Proj.Note,')'), '')) FullProjName 
FROM bs_house_code HC
LEFT JOIN bs_house_projectinfo Proj ON Proj.Id=HC.ProjectId
LEFT JOIN sys_area_code CA ON CA.Code = Proj.AreaCode
LEFT JOIN sys_area_code RA ON RA.AdCode = SUBSTR(CA.AdCode,1,9)
LEFT JOIN sys_area_code AA ON AA.AdCode = SUBSTR(CA.AdCode,1,6) 
LEFT JOIN bs_house_member_relation HM ON HC.Id = HM.HouseCodeId
INNER JOIN (SELECT * FROM sys_emp WHERE Id = @UserId) E ON HC.ZoneId = E.OrgId
WHERE HM.Id IS NULL";
            return await _dapperRep.QueryPageDataDynamic(sql, input, param: new
            {
                input.UserId
            }, filterFields: new[] { 
                nameof(BsHouseCode.Address) ,
                nameof(BsHouseCode.CreatedTime)
            });
        }

        /// <summary>
        /// 获取人员已经绑定的房屋编码列表
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("/houseSelector/selectedPage")]
        public async Task<dynamic> HouseSelectedList([FromBody] QueryHouseSelectorInput input)
        {
            var sql = @"SELECT 
	HC.*,AA.Name AreaName,RA.Name RoadName,CA.Name CommName,Proj.AreaCode,Proj.Note,CONCAT(Proj.`Name`, IFNULL(CONCAT('(',Proj.Note,')'), '')) FullProjName 
FROM bs_house_code HC
LEFT JOIN bs_house_projectinfo Proj ON Proj.Id=HC.ProjectId
LEFT JOIN sys_area_code CA ON CA.Code = Proj.AreaCode
LEFT JOIN sys_area_code RA ON RA.AdCode = SUBSTR(CA.AdCode,1,9)
LEFT JOIN sys_area_code AA ON AA.AdCode = SUBSTR(CA.AdCode,1,6) 
INNER JOIN (SELECT * FROM bs_house_member_relation WHERE SysUserId = @UserId) HM ON HC.Id = HM.HouseCodeId";
            return await _dapperRep.QueryPageDataDynamic(sql, input, param: new
            {
                input.UserId
            }, filterFields: new[] {
                nameof(BsHouseCode.Address) ,
                nameof(BsHouseCode.CreatedTime)
            });
        }

        /// <summary>
        /// 从人员选择房屋
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("/houseSelector/select")]
        [UnitOfWork]
        public async Task Select([FromBody] HouseSelectInput input)
        {
            #region 验证房屋是否在当前用户可选范围内

            var ids = input.Ids.Distinct().ToList();
            if (ids.Count == 0) throw Oops.Oh("没有选中任何房屋");

            // 验证当前用户是否安全员 **须补充

            // 已经被选中的房屋,从ids中剔除
            var houseSelected = await _bsHouseMemberRelationRep.DetachedEntities
                .Where(p => ids.Contains(p.HouseCodeId))
                .Select(p => p.HouseCodeId)
                .ToListAsync();
            if (houseSelected.Count > 0)
            {
                houseSelected.ForEach(p =>
                {
                    var index = ids.IndexOf(p);
                    if (index > -1)
                    {
                        ids.RemoveAt(index);
                    }
                });
            }

            if (ids.Count == 0) throw Oops.Oh("当前房屋在此之前已经全部被选中，请确认");

            var selectedUser = await _sysUserRep.DetachedEntities.FirstOrDefaultAsync(p => p.Id.Equals(input.UserId));

            // 从用户所在片区中过滤房屋
            var zoneId = await _houseZoneService.GetZoneByUser(selectedUser.Id);
            var house = await _bsHouseCodeRep.DetachedEntities.Where(p => ids.Contains(p.Id) && p.ZoneId == zoneId).Select(p => p.Id).ToListAsync();

            if (house.Count == 0) throw Oops.Oh("选中的房屋错误");

            #endregion

            // 选定房屋
            house.ForEach(async p =>
            {
                var originalTask = _bsHouseTaskRep.DetachedEntities.FirstOrDefault(t => t.HouseCodeId == p && t.TaskType == 0 && t.IsEnabled);
                if (originalTask == null)
                {
                    new BsHouseTask
                    {
                        Id = System.Guid.NewGuid().ToString(),
                        HouseCodeId = p,
                        UserID = selectedUser.Id,
                        EndTime = System.DateTime.Now.AddMonths(1),
                        Status = 0,
                        TaskType = 0
                    }.Insert();

                    await _houseLogService.Done(p);
                    await _houseLogService.Add(p, selectedUser, HouseLogType.CreateInfo);
                }
                else
                {
                    var sort = await _houseLogService.AddThenDone(p, _userManager.User, HouseLogType.SelectMember);
                    if (originalTask.Status != 6)//建档未完成，生成新建档任务分配给新的人员；原建档任务数据保留，有效性设置为false，取消巡查关系
                    {
                        var newTask = originalTask.Adapt<BsHouseTask>();
                        newTask.Id = System.Guid.NewGuid().ToString();
                        newTask.UserID = input.UserId;
                        newTask.EndTime = System.DateTime.Now.AddMonths(1);
                        newTask.Insert();

                        originalTask.IsEnabled = false;
                        originalTask.Update();

                        sort = await _houseLogService.Add(p, selectedUser, HouseLogType.CreateInfo, sort: sort);
                    }//已建档完成，不再分配建档任务，仅更换巡查关系
                    else
                    {
                        var originalRelation = _bsHouseMemberRelationRep.DetachedEntities.FirstOrDefault(r => r.HouseCodeId == p && r.SysUserId == originalTask.UserID);
                        originalRelation.Delete();
                    }
                }

                new BsHouseMemberRelation
                {
                    SysUserId = selectedUser.Id,
                    HouseCodeId = p
                }.Insert();
            });
        }

        [HttpPost("/houseSelector/revoke")]
        [UnitOfWork]
        public async Task Revoke([FromBody] HouseSelectInput input)
        {
            var ids = input.Ids.Distinct().ToList();
            if (ids.Count == 0) throw Oops.Oh("没有选中任何房屋");

            var selected = await _bsHouseMemberRelationRep.Where(p => ids.Contains(p.HouseCodeId) && p.SysUserId == input.UserId).ToListAsync();

            selected.ForEach(p =>
            {
                p.Delete();
            });
        }

        public async Task SelectMember()
        {

        }
    }
}
