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

namespace Ewide.Application.Service.HouseSafety.HouseInfo
{
    /// <summary>
    /// 房屋详细信息
    /// </summary>
    [ApiDescriptionSettings(Name = "HouseInfo", Order = 200)]
    public class HouseInfoService : IHouseInfoService, IDynamicApiController, ITransient
    {

        private readonly IRepository<BsHouseCode> _houseCodeRep;
        private readonly IRepository<BsHouseInfo> _houseInfoRep;
        private readonly IRepository<BsHouseTask> _houseTaskRep;
        private readonly IRepository<SysUser> _sysUserRep;
        private readonly IUserManager _userManager;
        private readonly IDapperRepository _dapperRepository;

        private readonly IHouseLogService _houseLogService;


        public HouseInfoService(
            IRepository<BsHouseCode> HouseCodeRep,
            IRepository<BsHouseInfo> HouseInfoRep, 
            IRepository<BsHouseTask> HouseTaskRep,
            IRepository<SysUser> sysUserRep,
            IUserManager userManager, IDapperRepository dapperRepository, IHouseLogService houseLogService)
        {
            _houseCodeRep = HouseCodeRep;
            _houseInfoRep = HouseInfoRep;
            _houseTaskRep = HouseTaskRep;
            _sysUserRep = sysUserRep;
            _userManager = userManager;
            _dapperRepository = dapperRepository;

            _houseLogService = houseLogService;
        }

        [HttpPost("/houseInfo/save")]
        [UnitOfWork]
        [AllowAnonymous]
        public async Task Save([FromBody] HouseInfoInputSave input)
        {
            await InputDataProcess(input,  DataStatus.Saved);
        }

        [HttpPost("/houseInfo/submitToCheck")]
        [UnitOfWork]
        [AllowAnonymous]
        public async Task SubmitToCheck([FromBody] HouseInfoInputSave input)
        {
            await InputDataProcess(input,DataStatus.Submited);
        }

        [HttpPost("/houseInfo/check")]
        [UnitOfWork]
        public async Task Check([FromBody] HouseInfoInputSave input)
        {
            await InputDataProcess(input, input.TaskCheckRecord.PassOrBackDataStatus );
        }

        [HttpGet("/houseInfo/getByTaskId")]
        [UnitOfWork]
        public async Task<HouseInfoOutputForDetailPage> GetByTaskId([Required] string taskId)
        {
            //获取任务实体
            var houseTask = await _houseTaskRep.DetachedEntities.FirstOrDefaultAsync(t=>t.Id == taskId);
            if(houseTask == null) throw Oops.Oh("任务不存在");

            //获取房屋编码信息
            var houseCodeOutputAsync = await _dapperRepository.QueryAsync<HouseCodeOutput>(
                @"SELECT 
HC.Id,HC.Address,HC.ProjectId,HC.ZoneId,HC.Type,AA.Name AreaName,RA.Name RoadName,CA.Name CommName,O.Name ZoneName,Proj.Note ProjectNote,CONCAT(Proj.`Name`, IFNULL(CONCAT('(',Proj.Note,')'), '')) FullProjName,HC.HouseCode,HC.Lng,HC.Lat,HC.No 
FROM bs_house_code HC
LEFT JOIN bs_house_projectinfo Proj ON Proj.Id=HC.ProjectId
LEFT JOIN sys_org O ON HC.ZoneId = O.Id
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)
WHERE HC.Id=@HouseCodeId", new { houseTask.HouseCodeId }
                );
            var houseCodeOutput= houseCodeOutputAsync.SingleOrDefault();
            if (houseCodeOutput == null) throw Oops.Oh("任务已失效：房屋编码不存在，请重新加载任务列表");
            
            //获取当前登录账号
            var currentUser = await _userManager.CheckUserAsync();

            //查询房屋详细信息是否存在
            var houseInfo = await _houseInfoRep.DetachedEntities.FirstOrDefaultAsync(h => h.HouseCodeId == houseTask.HouseCodeId);
            var houseInfoOutputForDetailPage = new HouseInfoOutputForDetailPage
            {
                HouseCode = houseCodeOutput
            };

            var taskOutput = houseTask.Adapt<HouseTaskOutput>();
            taskOutput.PatrolDate = houseTask.PatrolDate.GetValueOrDefault(DateTime.Now);
            taskOutput.PatrolUser = String.IsNullOrEmpty(houseTask.PatrolUser) ? currentUser.Name : houseTask.PatrolUser;
            houseInfoOutputForDetailPage.PatrolInfo = taskOutput;

            if (houseInfo == null || houseInfo.State <= (int)DataStatus.Submited)
            {
                // 未建档或者当前数据未提交时打开,标记为已读
                await _houseLogService.Read(houseCodeOutput.Id);
            }

            if (houseInfo == null)
            {
                houseInfoOutputForDetailPage.HouseInfo = new HouseInfoOutput();
                return houseInfoOutputForDetailPage;
            }

            var houseInfoOutput = (await _houseInfoRep.DetachedEntities.FirstOrDefaultAsync(p => p.HouseCodeId == houseTask.HouseCodeId)).Adapt<HouseInfoOutput>();
            houseInfoOutputForDetailPage.HouseInfo = houseInfoOutput;

            return houseInfoOutputForDetailPage;
        }

        [NonAction]
        [UnitOfWork]
        public async Task InputDataProcess(HouseInfoInputSave input,DataStatus dataStatus = DataStatus.Init)
        {
            //房屋编码地址/坐标单独更新
            var houseCode = input.houseCode.Adapt<BsHouseCode>();
            await houseCode.UpdateIncludeAsync(new[] { nameof(BsHouseCode.Address), nameof(BsHouseCode.Lng), nameof(BsHouseCode.Lat) }, true);

            //获取房屋详情实体，判断是新增还是更新
            var houseEntity = await _houseInfoRep.DetachedEntities.FirstOrDefaultAsync(h => h.HouseCodeId == input.houseCode.Id);

            //建档审核通过的房屋数据修改时，对应的建档任务Task不处理
            var houseTask = await _houseTaskRep.DetachedEntities.FirstOrDefaultAsync(p => p.Id == input.PatrolInfo.Id);
            if (houseEntity == null || houseEntity.State != 6)
            {
                var _houseTask = input.PatrolInfo.Adapt<BsHouseTask>();
                _houseTask.HouseCodeId = input.houseCode.Id;
                //任务没有暂存状态，其他状态与HouseInfo的State一致
                _houseTask.Status = dataStatus == DataStatus.TempSaved ? (int)DataStatus.Saved : (int)dataStatus;
                await _houseTask.UpdateExcludeAsync(new string[] { nameof(BsHouseTask.TaskType) }, ignoreNullValues: true);
            }
            //判断房屋建档状态
            //dataStatus == DataStatus.Saved 若是保存操作   则判断是新增/更新
            //判断是新增/更新 根据传入参数dataStatus确定
            input.houseInfo.State = dataStatus == DataStatus.Saved ? (houseEntity == null ? (int)DataStatus.Saved : houseEntity.State) : (int)dataStatus;
            var houseInfo = input.houseInfo.Adapt<BsHouseInfo>();
            houseInfo.HouseCodeId = input.houseCode.Id;
            
            if (houseEntity == null)
            {
                houseInfo.Id = Guid.NewGuid().ToString();
                await houseInfo.InsertAsync();
            }
            else
            {
                houseInfo.Id = houseEntity.Id;
                await houseInfo.UpdateExcludeAsync(new[] { nameof(BsHouseInfo.HouseGrade) }, true);
            }

            int? logSort = null;

            if (dataStatus == DataStatus.Submited)
            {
                await _houseLogService.Done(input.houseCode.Id);

                var org = await _userManager.GetUserOrgInfo();

                var _sysEmpRep = Db.GetRepository<SysEmp>();
                var _sysUserRoleRep = Db.GetRepository<SysUserRole>();
                var _sysRoleRep = Db.GetRepository<SysRole>();
                var zoneManagerList = await (from u in _sysUserRep.DetachedEntities
                                             join e in _sysEmpRep.DetachedEntities on u.Id equals e.Id
                                             join ur in _sysUserRoleRep.DetachedEntities on u.Id equals ur.SysUserId
                                             join r in _sysRoleRep.DetachedEntities on ur.SysRoleId equals r.Id
                                             where e.OrgId == org.Id && r.Code == Enum.GetName(HouseManagerRole.ZoneManager).ToUnderScoreCase()
                                             select u).ToListAsync();

                logSort = await _houseLogService.Add(input.houseCode.Id, zoneManagerList, HouseLogType.Check);
            }
            //审核操作则新增一条审核记录
            if (dataStatus == DataStatus.Back || dataStatus == DataStatus.Passed)
            {
                var checkRecord = input.TaskCheckRecord.Adapt<BsHouseTaskCheckRecord>();
                await checkRecord.InsertAsync();
                await _houseLogService.Done(input.houseCode.Id);
                logSort = await _houseLogService.AddThenDone(input.houseCode.Id, _userManager.User, dataStatus == DataStatus.Passed ? HouseLogType.Agree : HouseLogType.Disagree, remark: checkRecord.Content, sort: logSort);
                if (dataStatus == DataStatus.Back)
                {
                    var user = await _sysUserRep.DetachedEntities.FirstOrDefaultAsync(p => p.Id.Equals(houseTask.UserID));
                    logSort = await _houseLogService.Add(input.houseCode.Id, user, HouseLogType.CreateInfo, sort: logSort);
                }
            }
        }
    }
}
