using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Mvc;
using Siger.ApiCommon.Exceptions;
using Siger.ApiCommon.Result;
using Siger.ApiTPM.Utilities;
using Siger.Middlelayer.Common;
using Siger.Middlelayer.Common.Extensions;
using Siger.Middlelayer.Common.Helpers;
using Siger.Middlelayer.Common.ModuleEnum;
using Siger.Middlelayer.Log;
using Siger.Middlelayer.Repository;
using Siger.Middlelayer.TpmRepository.Entities;
using Siger.Middlelayer.TpmRepository.Repositories.Interface;
using Siger.Middlelayer.TpmRepository.Request;
using Siger.Middlelayer.TpmRepository.Response;
using Siger.ApiCommon.Filters;
using Siger.Middlelayer.Repository.Repositories.Interface;

namespace Siger.ApiTPM.Controllers
{
    public class PartsProcurementController : BaseController
    {
        private readonly IUnitOfWork _unitOfWork;
        private readonly ISigerProjectProcurementProcessRepository _procurementProcessRepository;
        private readonly ISparepartRepository _sparepartRepository;
        private readonly ISigerProjectSparepartOrder _sparepartOrder;
        private readonly ISigerProjectSparepartOrderDetail _sparepartOrderDetail;
        private readonly ISigerProjectUserRepository _projectUserRepository;
        private readonly ISigerProjectEmailConfig _projectEmailConfig;
        private readonly ISigerSystemConfigRepository _systemConfigRepository;
        private readonly ISparepartOrderApprovalRepository _approvalRepository;

        public PartsProcurementController(IUnitOfWork unitOfWork, ISigerProjectProcurementProcessRepository procurementProcessRepository, ISparepartRepository sparepartRepository,
            ISigerProjectSparepartOrder sparepartOrder, ISigerProjectSparepartOrderDetail sparepartOrderDetail, ISigerProjectUserRepository projectUserRepository, ISigerProjectEmailConfig projectEmailConfig
            , ISigerSystemConfigRepository systemConfigRepository, ISparepartOrderApprovalRepository approvalRepository)
        {
            _unitOfWork = unitOfWork;
            _procurementProcessRepository = procurementProcessRepository;
            _sparepartRepository = sparepartRepository;
            _sparepartOrder = sparepartOrder;
            _sparepartOrderDetail = sparepartOrderDetail;
            _projectUserRepository = projectUserRepository;
            _projectEmailConfig = projectEmailConfig;
            _systemConfigRepository = systemConfigRepository;
            _approvalRepository = approvalRepository;
        }
        [HttpGet]
        public IActionResult GetApprovalProcessTitle()
        {
            var ret = _procurementProcessRepository.GetList(f => f.projectid.Equals(ProjectId) && f.status == (int)RowState.Valid).Select(s => s.title).Distinct().ToList();
            return new ObjectResult(ret);
        }
        [HttpGet]
        public IActionResult GetApprovalProcess(string title, int page, int pagesize)
        {
            var ret = _procurementProcessRepository.GetPagedList(page, pagesize, f => f.projectid.Equals(ProjectId) && f.status == (int)RowState.Valid && f.title.Equals(title), "id");
            return new PagedObjectResult(ret.Data, ret.Total, page, pagesize);
        }
        [HttpGet]
        public IActionResult SetApprovalProcessCycle(int cycle)
        {
            var ret = _procurementProcessRepository.GetList(f => f.projectid.Equals(ProjectId) && f.status == (int)RowState.Valid, "id");
            foreach (var item in ret)
            {
                item.cycle = cycle;
                _procurementProcessRepository.Update(item);
            }
            if (_unitOfWork.Commit() > 0)
            {
                return new ObjectResult(CommonEnum.Succefull);
            }
            throw new BadRequestException(CommonEnum.Fail);
        }
        [HttpGet]
        public IActionResult DeleteApprovalProcess(int id)
        {
            var model = _procurementProcessRepository.Get(f => f.projectid.Equals(ProjectId) && f.status == (int)RowState.Valid && f.id.Equals(id));
            if (model != null)
            {
                model.status = (int)RowState.Invalid;
            }
            if (_unitOfWork.Commit() > 0)
            {
                return new ObjectResult(CommonEnum.Succefull);
            }
            throw new BadRequestException(CommonEnum.Fail);
        }
        [HttpPost]
        public IActionResult AddApprovalProcess([FromBody]RequestApprovalProcess req)
        {
            var data = _procurementProcessRepository.Get(f => f.projectid.Equals(ProjectId) && f.status == (int)RowState.Valid && f.title.Equals(req.title) && f.approval_user.Equals(req.approval_user));
            if (data != null)
            {
                throw new BadRequestException(CommonEnum.RecordExits);
            }

            var maxseq = 0;
            var existData = _procurementProcessRepository.GetList(f => f.projectid.Equals(ProjectId) && f.status == (int)RowState.Valid && f.title.Equals(req.title));
            if (existData.Any())
            {
                maxseq = existData.Max(m => m.seq) + 1;
            }
            var model = Mapper<RequestApprovalProcess, siger_project_procurement_process>.Map(req);
            model.projectid = ProjectId;
            model.seq = maxseq;
            _procurementProcessRepository.Insert(model);

            if (_unitOfWork.Commit() > 0)
            {
                return new ObjectResult(CommonEnum.Succefull);
            }
            throw new BadRequestException(CommonEnum.Fail);
        }
        [HttpPost]
        public IActionResult ModifyApprovalProcess([FromBody]RequestApprovalProcess req)
        {
            var model = _procurementProcessRepository.Get(f => f.projectid.Equals(ProjectId) && f.status == (int)RowState.Valid && f.id.Equals(req.id));
            if (model == null)
            {
                throw new BadRequestException(CommonEnum.NoData);
            }
            if (model.approval_user == req.approval_user && model.mail == req.mail)
            {
                return new ObjectResult(CommonEnum.Succefull);
            }
            model.approval_user = req.approval_user;
            model.mail = req.mail;
            if (_unitOfWork.Commit() == 0)
            {
                throw new BadRequestException(CommonEnum.Fail);
            }
            return new ObjectResult(CommonEnum.Succefull);
        }
        [HttpPost]
        public IActionResult SparepartInfo([FromBody]RequestSparepartInfo req)
        {
            var ret = _sparepartRepository.GetSparepartListInfo(req, ProjectId);
            return new PagedObjectResult(ret.Data, ret.Total, req.page, req.pagesize);
        }
        [HttpPost]
        public IActionResult SparepartPush([FromBody]RequestSparepartPush req)
        {
            var data = req.list;
            var now = UnixTimeHelper.GetNow();
            if (!data.Any())
            {
                throw new BadRequestException(CommonEnum.NoData);
            }
            var approve = (int)ApproveStatus.Pass;
            var order = (int)OrderStatus.Purchasing;
            var type = (int)OrderType.Normal;
            var approve_node = "";
            if (req.type == (int)OrderType.Urgent)
            {
                type = (int)OrderType.Urgent;
                approve = (int)ApproveStatus.WaitAudit;
                order = (int)OrderStatus.NotSubmitted;
                approve_node = "等待审核";
            }
            var code = _sparepartOrder.GengrateCode(ProjectId);
            decimal cost = 0;

            foreach (var item in data)
            {
                var model = _sparepartRepository.Get(f => f.code.Equals(item.code) && f.projectid.Equals(ProjectId) && f.status == (int)RowState.Valid);
                if (model == null)
                {
                    throw new BadRequestException(CommonEnum.Fail);
                }
                cost += item.count * Convert.ToDecimal(model.price);
                _sparepartOrderDetail.Insert(new siger_project_sparepart_order_detail
                {
                    count = item.count,
                    order_code = code,
                    sparepart_code = item.code,
                    projectid = ProjectId,
                    edit_time = now
                });
            }
            _sparepartOrder.Insert(new siger_project_sparepart_order
            {
                order_code = code,
                mid = UserId,
                projectid = ProjectId,
                process_name = req.name ?? "",
                order_type = type,
                approve_status = approve,
                order_status = order,
                cost = cost,
                approve_node = approve_node,
                edit_time = now,
                remark = req.remark.ToStr()
            });
            if (_unitOfWork.Commit() > 0)
            {
                //保存成功后发送信息
                if (req.type == (int)OrderType.Urgent)
                {
                    var process = _procurementProcessRepository.Get(f => f.status == (int)RowState.Valid && f.projectid == ProjectId && f.title.Equals(req.name) && f.seq == 0);
                    if (process != null)
                    {
                        SendAlarmMail(process.id, ProjectId, req.remark.ToStr(), code);
                    }
                    //var str = "尊敬的XXX您好，\r\n您所负责的备件：\r\n";
                    //var details = _sparepartOrderDetail.GetList(f => f.projectid.Equals(ProjectId) && f.status == (int)RowState.Valid && f.order_code.Equals(code));
                    //foreach (var detail in details)
                    //{
                    //    var sparepart = _sparepartRepository.Get(f => f.projectid.Equals(ProjectId) && f.status == (int)RowState.Valid && f.code.Equals(detail.sparepart_code));
                    //    if (sparepart != null)
                    //    {
                    //        str += $"备件{sparepart.code} {sparepart.title}";
                    //    }
                    //}
                    //str += "库存已超过预警值，请及时进行在系统进行采购";
                    //var users = _sparepartRepository.GetSparepartListInfo(new RequestSparepartInfo { code = code, page = 1, pagesize = 9999 }, ProjectId).Data.Select(s => s.mid).Distinct();
                    //foreach (var user in users)
                    //{
                    //    SendAlarmMail(user, str, "库存已超过预警值");
                    //}

                }
                return new ObjectResult(CommonEnum.Succefull);
            }
            throw new BadRequestException(CommonEnum.Fail);
        }
        /// <summary>
        /// 备件采购订单查询
        /// </summary>
        [HttpPost]
        public IActionResult SparepartOrderInfo([FromBody]RequestSparepartOrder req)
        {
            var data = _sparepartOrder.GetSparepartOrderInfo(req, ProjectId);
            return new PagedObjectResult(data.Data, data.Total, req.page, req.pagesize);
        }
        /// <summary>
        /// 备件确认收货
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult SparepartOrderConfirm(int id)
        {
            var now = UnixTimeHelper.GetNow();
            var data = _sparepartOrder.Get(f => f.projectid.Equals(ProjectId) && f.status == (int)RowState.Valid && f.id.Equals(id));
            if (data == null)
            {
                throw new BadRequestException(CommonEnum.NoData);
            }
            if (data.order_status == (int)OrderStatus.Completed)
            {
                throw new BadRequestException(TpmEnum.OrderConfirmed);

            }
            if (data.order_type == (int)OrderType.Urgent)
            {
                if (data.approve_status != (int)ApproveStatus.Pass)
                {
                    throw new BadRequestException(TpmEnum.OrderCanNotConfirm);
                }
            }
            data.order_status = (int)OrderStatus.Completed;
            data.editor = UserId;
            data.edit_time = now;
            _sparepartOrder.Update(data);
            var details = _sparepartOrderDetail.GetList(f => f.order_code.Equals(data.order_code) && f.projectid.Equals(ProjectId) && f.status == (int)RowState.Valid).ToList();
            foreach (var detail in details)
            {
                var model = _sparepartRepository.Get(f => f.code.Equals(detail.sparepart_code));
                if (model != null)
                {
                    model.sku += detail.count;
                    model.order_time = now;
                    _sparepartRepository.Update(model);
                }
                detail.edit_time = now;
                detail.status = (int)OrderStatus.Completed;
                _sparepartOrderDetail.Update(detail);
            }
            if (_unitOfWork.Commit() > 0)
            {
                return new ObjectResult(CommonEnum.Succefull);
            }
            throw new BadRequestException(CommonEnum.Fail);
        }
        /// <summary>
        /// 备件详情
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public IActionResult SparepartOrderDetail(string ordercode, int page, int pagesize)
        {
            var data = _sparepartOrderDetail.GetDetailInfo(ordercode, ProjectId, page, pagesize);
            return new PagedObjectResult(data.Data, data.Total, page, pagesize);
        }
        /// <summary>
        /// 修改订单数量
        /// </summary>
        /// <param name="req"></param>
        /// <returns></returns>
        [HttpPost]
        public IActionResult SparepartModifyOrderDetail([FromBody]RequestSparepartOrderDetail req)
        {
            decimal cost = 0;
            var now = UnixTimeHelper.GetNow();
            var order = string.Empty;//订单号
            if (req.data.Any())
            {
                foreach (var item in req.data)
                {
                    var detail = _sparepartOrderDetail.Get(f => f.id.Equals(item.id) && f.projectid.Equals(ProjectId) && f.status == (int)RowState.Valid);
                    if (detail != null)
                    {
                        order = detail.order_code;
                        var sparepart = _sparepartRepository.Get(f => f.code.Equals(detail.sparepart_code) && f.projectid.Equals(ProjectId))?.price ?? 0;
                        cost += item.count * Convert.ToDecimal(sparepart);
                        detail.count = item.count;
                        detail.edit_time = now;
                        _sparepartOrderDetail.Update(detail);
                    }
                }
                var model = _sparepartOrder.Get(f => f.order_code.Equals(order) && f.projectid.Equals(ProjectId) && f.status == (int)RowState.Valid);
                if (model != null)
                {
                    model.cost = cost;
                    model.editor = UserId;
                    model.edit_time = now;
                    model.approve_status = (int)ApproveStatus.WaitAudit;
                    model.approve_node = string.Empty;
                    _sparepartOrder.Update(model);
                }
                if (_unitOfWork.Commit() > 0)
                {
                    if (model != null)
                    {
                        var process = _procurementProcessRepository.Get(f => f.status == (int)RowState.Valid && f.projectid == ProjectId && f.title.Equals(model.process_name) && f.seq == 0);
                        if (process != null)
                        {
                            SendAlarmMail(process.id, ProjectId, model.remark, model.order_code);
                        }
                    }
                    return new ObjectResult(CommonEnum.Succefull);
                }
            }
            throw new BadRequestException(CommonEnum.Fail);
        }

        /// <summary>
        /// 获取备件采购信息NoToken
        /// </summary>
        /// <param name="req"></param>
        /// <returns></returns>
        [NoTokenValidateFilter]
        [HttpPost]
        public IActionResult SparepartOrderInfoNoToken([FromBody]RequestSparepartOrder req)
        {
            var mid = 0;
            var orders = new List<string>();
            var pid = 0;
            if (CheckToken(req.token, ref mid, ref orders, ref pid))
            {
                req.orders = orders;
                req.order_type = (int)OrderType.Urgent;//限制订单类型为紧急采购
                var data = _sparepartOrder.GetSparepartOrderInfo(req, pid);
                return new PagedObjectResult(data.Data, data.Total, req.page, req.pagesize);
            }
            throw new BadRequestException(TpmEnum.TokenVaild);
        }
        /// <summary>
        /// 获取备件采购信息详情NoToken
        /// </summary>
        /// <param name="req"></param>
        /// <returns></returns>
        [NoTokenValidateFilter]
        [HttpPost]
        public IActionResult SparepartOrderDetailNoToken([FromBody]RequestSparepartOrder req)
        {
            var mid = 0;
            var orders = new List<string>();
            var pid = 0;
            if (CheckToken(req.token, ref mid, ref orders, ref pid))
            {
                var data = _sparepartOrderDetail.GetDetailInfo(req.order_code, pid, req.page, req.pagesize);
                return new PagedObjectResult(data.Data, data.Total, req.page, req.pagesize);
            }
            throw new BadRequestException(TpmEnum.TokenVaild);
        }
        /// <summary>
        /// 审核NoToken
        /// </summary>
        /// <param name="req"></param>
        /// <returns></returns>
        [NoTokenValidateFilter]
        [HttpPost]
        public IActionResult AuditOrders([FromBody]RequestSparepartOrder req)
        {
            var mid = 0;
            var orders = new List<string>();
            var pid = 0;
            var approvenode = "";
            var approvestatus = 0;
            var nextmid = 0;
            var orderstatus = (int)OrderStatus.Purchasing;

            if (!CheckToken(req.token, ref mid, ref orders, ref pid))
            {
                throw new BadRequestException(TpmEnum.TokenVaild);
            }
            var userdata = _procurementProcessRepository.Get(f => f.id.Equals(mid));
            //init order status
            switch ((ApproveStatus)req.approve_status)
            {
                case ApproveStatus.Pass:
                    approvenode = $"{userdata?.approval_user ?? ""}审核完成";
                    approvestatus = (int)ApproveStatus.Pass;
                    var user = _procurementProcessRepository.Get(f => f.title.Equals(userdata.title) && f.status == (int)RowState.Valid && f.projectid == pid && f.seq == userdata.seq + 1);
                    if (user != null)
                    {
                        approvestatus = (int)ApproveStatus.Audit;
                        nextmid = user.id;
                    }
                    break;
                case ApproveStatus.NotPass:
                    approvenode = $"{ userdata?.approval_user ?? ""}审核不通过";
                    approvestatus = (int)ApproveStatus.NotPass;
                    break;
                default:
                    throw new BadRequestException(CommonEnum.Fail);
            }
            if (req.orders.Any())
            {
                orders = req.orders;//待操作的订单号
                var orderModels = _sparepartOrder.GetList(f => f.projectid == pid && f.status == (int)RowState.Valid && orders.Contains(f.order_code)).ToList();
                if (!orderModels.Any())
                {
                    throw new BadRequestException(CommonEnum.RecordNotFound);
                }
                foreach (var orderdata in orderModels)
                {
                    var model = _sparepartOrder.Get(f => f.id == orderdata.id);
                    //存在下级审核继续发邮件
                    if (approvestatus == (int)ApproveStatus.Audit)
                    {
                        orderstatus = (int)OrderStatus.NotSubmitted;
                        SendAlarmMail(nextmid, pid, orderdata.remark, orderdata.order_code);
                    }
                    model.approve_status = approvestatus;
                    model.approve_node = approvenode;
                    model.order_status = orderstatus;
                    _sparepartOrder.Update(model);

                    var approvalHistory = new siger_project_sparepart_order_approval
                    {
                        order_id = orderdata.id,
                        approval_time = DateTime.Now,
                        approval_user = userdata?.approval_user ?? "",
                        approval_result = req.approve_status,
                        project_id = pid,
                        remark = ""
                    };
                    _approvalRepository.Insert(approvalHistory);
                }

                if (_unitOfWork.Commit() > 0)
                {
                    return new ObjectResult(CommonEnum.Succefull);
                }
            }
            throw new BadRequestException(CommonEnum.RecordNotFound);
        }
        /// <summary>
        /// token生成接口
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [NoTokenValidateFilter]
        [HttpGet]
        public IActionResult GenerateToken(int id)
        {
            try
            {
                var orders = _sparepartOrder.GetList().Select(f => f.order_code).Distinct().ToList();
                var data = new RequestSparepartToken()
                {
                    //expirationtime = UnixTimeHelper.GetNow() + 3600 * 24 * 30,
                    mid = id,
                    orders = orders
                };
                var model = JsonHelper.SerializerToJsonString(data);
                var token = CryptoJSHelper.Encrypt(model);
                return new ObjectResult(token);
            }
            catch (Exception ex)
            {
                return new ObjectResult(ex.Message);
            }
        }

        private string GenerateTokenByCode(int id, string code)
        {
            try
            {
                var data = new RequestSparepartToken()
                {
                    //expirationtime = UnixTimeHelper.GetNow() + 3600 * 24 * 30,
                    mid = id,
                    orders = new List<string> { code }
                };
                var model = JsonHelper.SerializerToJsonString(data);
                var token = CryptoJSHelper.Encrypt(model);
                return token;
            }
            catch (Exception)
            {
                return "";
            }
        }
        private bool CheckToken(string token, ref int mid, ref List<string> orders, ref int pid)
        {
            try
            {
                if (string.IsNullOrEmpty(token))
                {
                    return false;
                }
                token = CryptoJSHelper.Decrypt(token);
                var model = JsonHelper.DeserializerJsonResult<RequestSparepartToken>(token);
                mid = model.mid;
                var user = _procurementProcessRepository.Get(f => f.id.Equals(model.mid) && f.status == (int)RowState.Valid);
                if (user == null)
                {
                    return false;
                }
                pid = user.projectid;
                orders = model.orders;
                //if (model.expirationtime <= UnixTimeHelper.GetNow())
                //{
                //    return false;
                //}
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }

        private void SendAlarmMail(int mid, int pid, string remark, string order)
        {
            var Cfg = _projectEmailConfig.Get(f => f.project == pid && f.status == (int)RowState.Valid);
            if (Cfg == null)
            {
               // Logger.WriteLineInfo("你没有维护邮箱！");
                return;
            }
            var user = _procurementProcessRepository.Get(f => f.id.Equals(mid) && f.status == (int)RowState.Valid && f.projectid == pid);
            if (user == null || string.IsNullOrEmpty(user.mail))
            {
               // Logger.WriteLineInfo($"{mid}该用户没有邮箱！");
                return;
            }
            if (string.IsNullOrEmpty(user.mail))
            {
                return;
            }
            var orderData = _sparepartOrder.Get(f => f.projectid == pid && f.order_code.Equals(order) && f.status == (int)RowState.Valid);
            if (orderData == null)
            {
                Logger.WriteLineInfo($"{order}备件采购订单未找到！");
                return;
            }
            var creater = _projectUserRepository.Get(f => f.mid.Equals(orderData.mid));
            var content = $"尊敬的{user.approval_user}您好，<br />";
            content += $"由{creater?.name ?? ""}提交的备件紧急采购申请已提交<br />";
            var details = _sparepartOrderDetail.GetList(f => f.projectid.Equals(pid) && f.status == (int)RowState.Valid && f.order_code.Equals(order)).ToList();
            foreach (var detail in details)
            {
                var sparepart = _sparepartRepository.Get(f => f.projectid.Equals(pid) && f.status == (int)RowState.Valid && f.code.Equals(detail.sparepart_code));
                if (sparepart != null)
                {
                    content += $"备件{sparepart.code} {sparepart.title}<br />";
                }
            }

            if (!string.IsNullOrWhiteSpace(remark))
            {
                content += "<br /><br />";
                content += $"申请备注: {remark}<br />";
            }
            
            var server = _systemConfigRepository.Get(f => f.key == "serverip");
            var str = server?.value ?? "";
            str += @"/#/audit/?token=";
            str += GenerateTokenByCode(mid, order);
            content += $"请您尽快审批{str}";
            MailHelper.SendMail(Cfg.server, true, Cfg.send, Cfg.code, "Tpm Notice",
                   Cfg.send, user.mail, "备件紧急采购申请", content, new List<string>());
        }
    }
}