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

namespace Ewide.Application.Service
{
    /// <summary>
    /// 房屋流转日志
    /// </summary>
    [ApiDescriptionSettings(Name = "HouseLog", Order = 210)]
    public class HouseLogService : IHouseLogService, IDynamicApiController, ITransient
    {
        private readonly IDapperRepository _dapperRep;

        private readonly IUserManager _userManager;

        private readonly IRepository<BsHouseLog> _bsHouseLogRep;

        public HouseLogService(IDapperRepository dapperRep, IUserManager userManager, IRepository<BsHouseLog> bsHouseLogRep)
        {
            _dapperRep = dapperRep;
            _userManager = userManager;
            _bsHouseLogRep = bsHouseLogRep;
        }

        [NonAction]
        [UnitOfWork]
        public async Task<int> Add(string houseCodeId, SysUser targetUser, HouseLogType type, string remark = null, int? sort = null)
        {
            return await Add(houseCodeId, new List<SysUser> { targetUser }, type, remark, sort);
        }

        [NonAction]
        [UnitOfWork]
        public async Task<int> Add(string houseCodeId, List<SysUser> targetUsers, HouseLogType type, string remark = null, int? sort = null)
        {
            if (!sort.HasValue)
            {
                sort = await _bsHouseLogRep.DetachedEntities.Where(p => p.HouseCodeId.Equals(houseCodeId)).MaxAsync(p => p.Sort);
            }
            var _sort = sort.GetValueOrDefault(1) + 1;
            await new BsHouseLog
            {
                Id = Guid.NewGuid().ToString(),
                HouseCodeId = houseCodeId,
                TargetUserIds = String.Join(",", targetUsers.Select(p => p.Id)),
                Type = type,
                Status = HouseLogStatus.Handle,
                Remark = remark,
                Sort = _sort
            }.InsertAsync();

            return _sort;
        }

        [NonAction]
        [UnitOfWork]
        public async Task Read(string houseCodeId)
        {
            var log = await _bsHouseLogRep
                .Where(p => p.HouseCodeId.Equals(houseCodeId) && p.Status.Equals(HouseLogStatus.Handle))
                .OrderByDescending(p => p.CreatedTime)
                .FirstOrDefaultAsync();
            if (log != null)
            {
                log.Status = HouseLogStatus.Handling;
                await log.UpdateAsync();
            }
        }

        [NonAction]
        [UnitOfWork]
        public async Task Done(string houseCodeId)
        {
            var log = await _bsHouseLogRep
                .Where(p => p.HouseCodeId.Equals(houseCodeId) && !p.Status.Equals(HouseLogStatus.Handled))
                .OrderByDescending(p => p.CreatedTime)
                .FirstOrDefaultAsync();
            if (log != null)
            {
                log.Status = HouseLogStatus.Handled;
                log.FinishedTime = DateTime.Now;
                log.FinishedUserId = _userManager.UserId;
                log.FinishedUserName = _userManager.User.Account;
                await log.UpdateAsync();
            }
        }

        [NonAction]
        [UnitOfWork]
        public async Task<int> AddThenRead(string houseCodeId, SysUser targetUser, HouseLogType type, string remark = null, int? sort = null)
        {
            return await AddThenRead(houseCodeId, new List<SysUser> { targetUser }, type, remark, sort);
        }

        [NonAction]
        [UnitOfWork]
        public async Task<int> AddThenRead(string houseCodeId, List<SysUser> targetUsers, HouseLogType type, string remark = null, int? sort = null)
        {
            if (!sort.HasValue)
            {
                sort = await _bsHouseLogRep.DetachedEntities.Where(p => p.HouseCodeId.Equals(houseCodeId)).MaxAsync(p => p.Sort);
            }
            var _sort = sort.GetValueOrDefault(1) + 1;
            await new BsHouseLog
            {
                Id = Guid.NewGuid().ToString(),
                HouseCodeId = houseCodeId,
                TargetUserIds = String.Join(",", targetUsers.Select(p => p.Id)),
                Type = type,
                Status = HouseLogStatus.Handling,
                Remark = remark,
                Sort = _sort
            }.InsertAsync();

            return _sort;
        }

        [NonAction]
        [UnitOfWork]
        public async Task<int> AddThenDone(string houseCodeId, SysUser targetUser, HouseLogType type, string remark = null, int? sort = null)
        {
            return await AddThenDone(houseCodeId, new List<SysUser> { targetUser }, type, remark, sort);
        }

        [NonAction]
        [UnitOfWork]
        public async Task<int> AddThenDone(string houseCodeId, List<SysUser> targetUsers, HouseLogType type, string remark = null, int? sort = null)
        {
            if (!sort.HasValue)
            {
                sort = await _bsHouseLogRep.DetachedEntities.Where(p => p.HouseCodeId.Equals(houseCodeId)).MaxAsync(p => p.Sort);
            }
            var _sort = sort.GetValueOrDefault(1) + 1;
            await new BsHouseLog
            {
                Id = Guid.NewGuid().ToString(),
                HouseCodeId = houseCodeId,
                TargetUserIds = String.Join(",", targetUsers.Select(p => p.Id)),
                Type = type,
                Status = HouseLogStatus.Handled,
                Remark = remark,
                FinishedTime = DateTime.Now,
                FinishedUserId = _userManager.UserId,
                FinishedUserName = _userManager.User.Account,
                Sort = _sort
            }.InsertAsync();

            return _sort;
        }

        [HttpGet("/houseLog/list")]
        public async Task<dynamic> List([FromQuery] HouseLogInput input)
        {
            var sql = @"SELECT
	HL.Id,
	HL.Type,
	HL.`Status`,
    HL.Remark,
	HL.FinishedTime,
	HL.FinishedUserId,
	IFNULL(NickName, `Name`) FinishedUserName,
(SELECT GROUP_CONCAT(IFNULL(NickName,`Name`)) FROM sys_user
	WHERE Id IN (
		SELECT DISTINCT SUBSTRING_INDEX(SUBSTRING_INDEX(_HL.TargetUserIds,',',HT.help_topic_id + 1),',',-1)
		FROM bs_house_log _HL
		JOIN mysql.help_topic HT ON HT.help_topic_id < (LENGTH(_HL.TargetUserIds) - LENGTH(REPLACE(_HL.TargetUserIds,',','')) + 1)
		WHERE _HL.Id = HL.Id
	)
) TargetUserNames
FROM bs_house_log HL
LEFT JOIN sys_user SU ON HL.FinishedUserId = SU.Id
WHERE HouseCodeId = @HouseCodeId
ORDER BY Sort DESC";

            return await _dapperRep.QueryAsync<HouseLogOutput>(sql, new { houseCodeId = input.Id });
        }

        [HttpGet("/houseLog/listByInfoId")]
        public async Task<dynamic> ListByInfoId([FromQuery] HouseLogInput input)
        {
            var info = await Db.GetRepository<BsHouseInfo>().DetachedEntities.FirstOrDefaultAsync(p => p.Id.Equals(input.Id));
            return await List(new HouseLogInput
            {
                Id = info.HouseCodeId
            });
        }

        [HttpGet("/houseLog/listByTaskId")]
        public async Task<dynamic> ListByTaskId([FromQuery] HouseLogInput input)
        {
            var task = await Db.GetRepository<BsHouseTask>().DetachedEntities.FirstOrDefaultAsync(p => p.Id.Equals(input.Id));
            return await List(new HouseLogInput
            {
                Id = task.HouseCodeId
            });
        }
    }
}
