using AlibabaCloud.SDK.Dingtalkdatacenter_1_0.Models;
using AspectCore.DynamicProxy;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Distributed;
using NPOI.SS.Formula.Functions;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using XYY.Authentication.Standard;
using XYY.Common.Standard;
using XYY.Core.Standard.ExcelHelper.MSExcelHelper;
using XYY.Core.Standard.Mvc;
using XYY.Data.Standard.Finance;
using XYY.Model.Standard.Dto.Finance;
using XYY.Model.Standard.Enums;
using XYY.Model.Standard.Finance;
using XYY.Service.Standard.Finance;
using XYY.TaskTrack.Standard;
using XYY.TaskTrack.Standard.TaskModel;

namespace XYY.Api.Finance.Controllers
{
    [Route("api/[controller]/[action]")]
    [ApiController]
    public class FinanceQuotationController : ApiControllerBase
    {
        XYY.Core.Standard.AliYun.IAliYunPostFileSerivce _aliYunPostFileSerivce;
        private IQuotationService _quotationService;
        private IQuotationApproveService _quotationApproveService;
        private IMQManager _MQManager;
        private XYY.Data.Standard.IUserCustomerRepository _userCustomerRepository;
        private IDingDingBaseService _dingDingBaseService;
        IDistributedCache _cache;
        private ILogistics_ExpressSettlementAdjustmentRepository _expressSettlementAdjustmentRepository;

        private IFinance_ServiceSurchargeService _serviceSurchargeService;
        public FinanceQuotationController(IQuotationService quotationService, IQuotationApproveService quotationApproveService, IMQManager MQManager, Data.Standard.IUserCustomerRepository userCustomerRepository, IDingDingBaseService dingDingBaseService, IDistributedCache cache, Core.Standard.AliYun.IAliYunPostFileSerivce aliYunPostFileSerivce, ILogistics_ExpressSettlementAdjustmentRepository expressSettlementAdjustmentRepository, IFinance_ServiceSurchargeService serviceSurchargeService)
        {
            _quotationService = quotationService;
            _quotationApproveService = quotationApproveService;
            _MQManager = MQManager;
            _userCustomerRepository = userCustomerRepository;
            _dingDingBaseService = dingDingBaseService;
            _cache = cache;
            _aliYunPostFileSerivce = aliYunPostFileSerivce;
            _expressSettlementAdjustmentRepository = expressSettlementAdjustmentRepository;
            _serviceSurchargeService = serviceSurchargeService;
        }

        public async Task<IActionResult> QueryPublic(QueryModel queryModel)
        {
            var user = User.GetUserContent();
            if (user.Roles.Any(x => x == "销售"))
            {
                if (queryModel.QueryParamer == null)
                    queryModel.QueryParamer = new List<QueryParamer>();

                queryModel.QueryParamer.Add(new QueryParamer
                {
                    Method = "Eq",
                    Filed = "SalesmanUserId",
                    Value = user.Id.ToString()
                });


            }
            var data = await _quotationService.QueryData(queryModel);
            return Ok(data);
        }

        public async Task<IActionResult> Query(QueryModel queryModel)
        {
            var user = User.GetUserContent();
            if (user.Roles.Any(x => x == "销售"))
            {
                if (queryModel.QueryParamer == null)
                    queryModel.QueryParamer = new List<QueryParamer>();



                queryModel.QueryParamer.Add(new QueryParamer
                {
                    Method = "Eq",
                    Filed = "SalesmanUserId",
                    Value = user.Id.ToString()
                });


            }
            var data = await _quotationService.QueryData(queryModel);
            return Ok(data);
        }

        public async Task<IActionResult> GetChinaPostPublic(int channelId)
        {
            //邮政公开价
            var data = await _quotationService.QueryChinaPostPublicData(channelId);
            return Ok(data);
        }


        [HttpPost]
        [HttpGet]
        public async Task<IActionResult> GetChinaPostPublicDiscount(QueryModel queryMdoel)
        {
            var data = await _quotationService.QueryChinaPostPublicDiscount(queryMdoel);
            return Ok(data);
        }


        [HttpGet]
        public async Task<IActionResult> GetSettlementAdjustmentMode()
        {
            var r = new object[]
           {
                new {
                    Key = "每票元",
                    Value=1
                },
                new {
                    Key = "每500G元",
                    Value=2
                },
                new {
                    Key = "比例(%)",
                    Value=3
                }
           };
            return Ok(r);
        }


        [HttpPost]
        [HttpGet]
        public async Task<IActionResult> InputChinaPostData(string url, string sheetName)
        {
            System.Net.WebClient client = new System.Net.WebClient();
            var data = client.DownloadData(url);
            var json = _quotationService.ImportExcelToChinaPostPublicJson(data, sheetName);
            return Ok(json);

        }


        public async Task<IActionResult> GetExpressFeeAsAdjustment(Logistics_ExpressSettlementAdjustmentDto adjustmentDto)
        {
            QueryModel query = new QueryModel()
            {
                QueryParamer = new List<QueryParamer> {
                    new QueryParamer{
                        Filed = "SealId",
                        Value="True"
                    } ,
                    new QueryParamer{
                        Filed = "customerids",
                        Method="In",
                        Value =  String.Join(',', adjustmentDto.CustomerId)
                    },
                    new QueryParamer{
                        Filed ="ExpressId",
                        Value = adjustmentDto.ExpressId.ToString()
                    }
                }
            };
            adjustmentDto.Details.ForEach(x => x.IsAll = x.Zone.Split(",").Contains("全部"));
            var detail = await _quotationService.QueryViewExpressSettlement(query);
            var all = adjustmentDto.Details.Where(x => x.IsAll);
            //冲突调整判断
            var notAll = adjustmentDto.Details.Where(x => !x.IsAll).ToList();
            //数据校验处理
            var verify = AdjustmentDtoVerify(notAll);
            //全部调整  
            if (all.Count() > 1)
            {
                throw new Exception("全部调整时，仅允许单种策略");
            }
            else if (!verify.Item1) { throw new Exception(verify.Item2); }
            else if (all.Count() == 1 && verify.Item1)
            {
                var a = all.First();
                var df = detail.First() as object;
                Type type = typeof(object);
                var ps = type.GetProperties();
                //int wi = 1;
                List<string> singleZone = notAll.SelectMany(x => x.Zone.Split(",")).ToList();
                foreach (var d in detail.Where(x => !singleZone.Contains(x.操作费)))//排除单个调整项
                {
                    double f = double.Parse(d.运费);
                    switch (a.Mode)
                    {
                        case SettlementAdjustmentMode.比例:
                            f += Math.Round(f * (a.Value / 100), 3);
                            break;
                        case SettlementAdjustmentMode.每票元:
                            f += a.Value;
                            break;
                        case SettlementAdjustmentMode.每500G元:
                            f += Convert.ToDouble(d.结束重量) / 0.5 * a.Value;// f + a.Value * wi;
                            break;
                    }
                    d.运费 = f.ToString();
                }
                //wi++;
            }
            //单独调整
            if (notAll != null && notAll.Count > 0)
            {
                foreach (var item in notAll)
                {
                    foreach (var d in detail.Where(x => item.Zone.Split(",").Contains(x.操作费)))
                    {
                        double f = double.Parse(d.运费);
                        switch (item.Mode)
                        {
                            case SettlementAdjustmentMode.比例:
                                f += Math.Round(f * (item.Value / 100), 3);
                                break;
                            case SettlementAdjustmentMode.每票元:
                                f += item.Value;
                                break;
                            case SettlementAdjustmentMode.每500G元:
                                f += Convert.ToDouble(d.结束重量) / 0.5 * item.Value;// f + a.Value * wi;
                                break;
                        }
                        d.运费 = f.ToString();
                    }
                }
            }
            var json = _quotationService.ConvertSettlementView(detail.ToList());
            return Ok(new { json, detail });
        }
        /// <summary>
        /// 数据校验处理
        /// </summary>
        /// <returns></returns>
        private Tuple<bool, string> AdjustmentDtoVerify(List<Logistics_ExpressSettlementAdjustmentDetail> notAll)
        {
            bool result = true; string msg = string.Empty;
            if (notAll == null || notAll.Count == 0) { return Tuple.Create(result, msg); }
            //同一个分区不能出现两次
            List<string> zones = notAll.SelectMany(x => x.Zone.Split(",")).Distinct().ToList();
            foreach (var item in zones)
            {
                var temp = notAll.Where(x => x.Zone.Split(",").Contains(item)).ToList();
                if (temp.Count > 1) { result = false; msg += $"分区【{item}】\r\n"; }
            }
            if (!string.IsNullOrEmpty(msg)) { msg += "，存在多个调整！"; }
            return Tuple.Create(result, msg);
        }

        [HttpPost]
        /// <summary>
        /// 生成文件
        /// 并记录调整逻辑
        /// </summary>
        /// <param name="adjustmentDto"></param>
        /// <param name="detail"></param>
        /// <returns></returns>
        public async Task<IActionResult> GenerateExpressFeeFile(GenerateExpressFeeFileDto dto)
        {
            List<Tuple<string, string>> msgs = await _expressSettlementAdjustmentRepository.ExpressSettlementAdjustmentLog(dto.adjustmentDto);
            //生成计费文件
            string file = GetExpressFeeFile(msgs, dto.detail);
            if (string.IsNullOrEmpty(file)) { throw new Exception("生成调整文件失败，请联系技术部！"); }
            return Ok(file);

        }
        private string GetExpressFeeFile(List<Tuple<string, string>> msgs, IEnumerable<View_Quotation> detail)
        {
            string fileUrl = string.Empty;
            #region 基础数据整理
            var weights = detail.GroupBy(x => x.结束重量).ToList();
            List<string> headName = new List<string> { "公斤/分区" };
            var temp = weights[0].Select(x => x.操作费).Distinct().ToList();
            headName.AddRange(temp);
            headName.Add("备注");
            #endregion
            //考虑文件表头会变动 48和50共用
            XSSFWorkbook excelBook = new XSSFWorkbook();
            #region 样式处理
            //表头字体设置
            NPOI.SS.UserModel.IFont headFont = excelBook.CreateFont();
            headFont.FontHeightInPoints = 14;
            headFont.IsBold = true;

            NPOI.SS.UserModel.IFont sheetTable1Font = excelBook.CreateFont();
            sheetTable1Font.FontHeightInPoints = 11;
            sheetTable1Font.IsBold = true;

            //sheet 1表头
            ICellStyle headStyle = excelBook.CreateCellStyle();
            headStyle.WrapText = true;//设置换行这个要先设置
            headStyle.Alignment = HorizontalAlignment.Center;
            headStyle.BorderBottom = BorderStyle.Thin;
            headStyle.BorderTop = BorderStyle.Thin;
            headStyle.BorderLeft = BorderStyle.Thin;
            headStyle.BorderRight = BorderStyle.Thin;
            headStyle.SetFont(headFont);
            //单元格通用样式
            ICellStyle styleCommonCenter = excelBook.CreateCellStyle();
            styleCommonCenter.Alignment = HorizontalAlignment.Center;
            styleCommonCenter.WrapText = true;
            styleCommonCenter.VerticalAlignment = VerticalAlignment.Center;
            styleCommonCenter.BorderBottom = BorderStyle.Thin;
            styleCommonCenter.BorderTop = BorderStyle.Thin;
            styleCommonCenter.BorderLeft = BorderStyle.Thin;
            styleCommonCenter.BorderRight = BorderStyle.Thin;
            #endregion
            ISheet sheet = excelBook.CreateSheet("Sheet1");
            IRow row = sheet.CreateRow(0);
            row.Height = 200 * 3;
            for (int i = 0; i < headName.Count; i++)
            {
                sheet.SetColumnWidth(i, 20 * 256);
                ICell cell = row.CreateCell(i);
                cell.CellStyle = headStyle;
                cell.SetCellValue(headName[i]);
                //批注处理 不使用批注 全部设置不好对应
                //var tempZone = msgs.Where(x => x.Item1 == headName[i]).FirstOrDefault();
                //if (temp != null)
                //{
                //    IDrawing drawing = sheet.CreateDrawingPatriarch();
                //    IComment comment = drawing.CreateCellComment(new XSSFClientAnchor(0, 0, 0, 0, 0, 0, 0, 0));
                //    comment.String =new XSSFRichTextString(tempZone.Item2);
                //    comment.Author = "zkl";
                //    cell.CellComment = comment;
                //}

            }
            //处理数据行写入
            for (int i = 0; i < weights.Count; i++)
            {
                IRow dataRow = sheet.CreateRow(i + 1);
                for (int j = 0; j < headName.Count; j++)
                {
                    ICell cell = dataRow.CreateCell(j);
                    cell.CellStyle = styleCommonCenter;
                    if (j == 0) { cell.SetCellValue(weights[i].Key); }
                    else if (headName[j] == "备注") { if (i < msgs.Count) { cell.SetCellValue(msgs[i].Item2); } else { cell.SetCellValue(""); } }
                    else { cell.SetCellValue(weights[i].Where(x => x.操作费 == headName[j]).FirstOrDefault().运费); }
                }
            }
            MemoryStream stream = new MemoryStream();
            excelBook.Write(stream);
            var buf = stream.ToArray();
            fileUrl = _aliYunPostFileSerivce.PostHttpFile(new MemoryStream(buf), Guid.NewGuid().ToString() + ".xlsx");

            return fileUrl;
        }

        public async Task<IActionResult> GetExoressZones(int expressId)
        {
            var zones = await _quotationService.GetExpressZones(expressId);
            zones.Insert(0, "全部");
            return Ok(zones);
        }

        public async Task<IActionResult> GetFedexFeeOther()
        {

            var feeOther = await _serviceSurchargeService.GetFeeOther(new QueryModel
            {
                QueryParamer = new List<QueryParamer> { new QueryParamer {
                Filed = "ExpressId", Method = "Eq", Value = "48" } }
            });

            return Ok(feeOther);
        }

        public async Task<IActionResult> GetDHLFeeOther()
        {

            var feeOther = await _serviceSurchargeService.GetFeeOther(new QueryModel
            {
                QueryParamer = new List<QueryParamer> { new QueryParamer {
                Filed = "ExpressId", Method = "Eq", Value = "50" } }
            });

            return Ok(feeOther);
        }


        public async Task<IActionResult> GetFedexBaseFee(QueryModel queryModel)
        {
            var additionalCharge = await _serviceSurchargeService.QueryDetail(queryModel);
            var feeOther = await _serviceSurchargeService.GetFeeOther(queryModel);
            var feeBase = await _quotationService.QueryExpressFeeBase(queryModel);
            var jsonData = await _quotationService.QueryExpressSettlement(queryModel);

            //var FuelSurcharge = "";

            return Ok(new { feeBase = feeBase, jsonData = Newtonsoft.Json.JsonConvert.SerializeObject(jsonData), additionalCharge = additionalCharge, feeOther = feeOther });
        }

        public async Task<IActionResult> ImportExcelToJson(Dto dto)
        {
            var file = new System.Net.WebClient().DownloadData(dto.FileUrl);
            var list = _quotationService.ImportExcelToJson(file);
            return Ok(list);
        }


        public class Dto
        {
            public string FileUrl
            {
                get; set;
            }

            public string Remark
            {
                get; set;
            }
            public int[] ChangeCustomers
            {
                get; set;
            }

            public int ExpressId
            {
                get; set;
            }
            /// <summary>
            /// 渠道名称 
            /// 目前仅邮政公开价才有
            /// E特快 邮政E邮宝A  邮政E邮宝B  特货E邮宝
            /// </summary>
            public string ExpresssName { get; set; }
            public DateTime setTime
            {
                get; set;
            }

            public int userId
            {
                get; set;
            }

            public IEnumerable<View_Quotation> detail
            {
                get; set;
            }

        }


        [AllowAnonymous]
        [HttpGet]
        public async Task<IActionResult> GetKDFee(int customerId, bool isChengDuQuotation = false)
        {
            var fileName = await _quotationApproveService.GetGZKDFee2022(customerId, isChengDuQuotation);
            var stream = System.IO.File.OpenRead(fileName);
            return File(stream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        }


        [AllowAnonymous]
        [HttpGet]
        public async Task<IActionResult> GetCDKDFee(int customerId)
        {
            string fileName = await _quotationApproveService.GetGZKDFee2022(customerId, true);
            var stream = System.IO.File.OpenRead(fileName);
            return File(stream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            return Ok();
        }

        public async Task<IActionResult> SendDingDing(List<Dto> dtos)
        {
            if (dtos.Any(x => x.ChangeCustomers == null || x.ChangeCustomers.Length == 0))
                throw new Exception("必须选择变更客户");
            if (dtos.Count > 0)
            {
                CspaceFile cspaceFile = null;
                string fileUrl = dtos.First().FileUrl;
                int userId = User.GetUserContent().Id;
                var u = await _dingDingBaseService.GetDingDingUserInfo(userId);
                if (!string.IsNullOrEmpty(fileUrl))
                {
                    string tempFilePath = System.IO.Path.Combine(System.AppContext.BaseDirectory, "temp");
                    if (System.IO.Directory.Exists(tempFilePath))
                    {
                        System.IO.Directory.CreateDirectory(tempFilePath);
                    }
                    string fileName = System.IO.Path.GetFileName(fileUrl);
                    string filePath = System.IO.Path.Combine(tempFilePath, fileName);
                    System.Net.WebClient webClient = new System.Net.WebClient();
                    webClient.DownloadFile(fileUrl, filePath);
                    cspaceFile = await _dingDingBaseService.UpdateFileToCspace(u, fileName, filePath);
                }
                foreach (var dto in dtos)
                {
                    dto.userId = userId;
                    string processInstanceId =
                        await _quotationService.SendDingDing(dto.ChangeCustomers, dto.ExpressId, dto.setTime, dto.userId, dto.Remark, dto.detail, cspaceFile);
                    long approveId =
                        await _quotationApproveService.SaveApprove(processInstanceId, dto.ChangeCustomers, dto.ExpressId, dto.setTime, dto.userId, dto.detail, fileUrl, dto.Remark);


                    //userId = 163;
                    //await _quotationService.SendDingDing(dto.ChangeCustomers, dto.ExpressId, dto.setTime, userId, dto.detail);

                }
            }
            return Ok();
        }

        public async Task<IActionResult> SendNowCustomerQuotaion(FinanceQuotation financeQuotation)
        {
            string message = await _quotationApproveService.SendNowCustomerQuotaion(financeQuotation);
            return Ok(message);
        }

        public async Task<IActionResult> HandleQuotationApproved(string ddid)
        {
            await _quotationApproveService.HandleQuotationApproved(ddid);
            return Ok();
        }
        public async Task<IActionResult> SendNowCustomerQuotaions(FinanceQuotation financeQuotation)
        {
            foreach (var item in financeQuotation.CustomerIds)
            {
                var customer = await _userCustomerRepository.GetAsync(item);
                FinanceQuotation f = new FinanceQuotation
                {
                    CusotmerId = item,
                    CustomerName = customer.CompanyName,
                    EntryTime = "2021-12-03",
                    UserId = 52
                };
                await _quotationApproveService.SendNowCustomerQuotaion(f);
            }
            return Ok();
        }

        [AllowAnonymous]
        [HttpGet]
        public async Task<IActionResult> TestProcess(string pid)
        {
            try
            {
                //await _quotationApproveService.HandleQuotationApproved(pid);
                List<int> ids = new List<int> { 9390 };
                await _quotationApproveService.SendGenerateFeeBaseFileMessage(ids, 6, "2021-11-19");
            }
            catch (Exception ex)
            {

            }

            return Ok();
        }

        [AllowAnonymous]
        [HttpPost]
        public async Task<IActionResult> TestSub(FinanceQuotation quotation)
        {
            await _MQManager.Publish(quotation);
            return Ok();
        }

        public async Task<IActionResult> PassQuotationApproved(string quotationId)
        {
            await _quotationApproveService.HandleQuotationDiscountApproved(quotationId);
            return Ok();
        }

        public async Task<IActionResult> PassExpressApproved(string quotationId)
        {
            await _quotationApproveService.HandleQuotationApproved(quotationId);
            return Ok();
        }

        [HttpPost]
        public async Task<IActionResult> QueryQuotationApproveRecord(QueryModel queryModel)
        {
            PageResult<QuotationApproveRecordDto> data = await _quotationApproveService.QueryApproveRecord(queryModel);
            return Ok(data);
        }
        [HttpGet]
        public async Task<IActionResult> GetQuotationDetail(int id)
        {
            IEnumerable<Finance_QutationApproveDetail> data = await _quotationApproveService.GetQuotationDetail(id);
            return Ok(data);
        }



        [HttpGet]
        public async Task<IActionResult> ExportQuotation(int customerId)
        {
            ExportQuotationParam param = new ExportQuotationParam { CustomerId = customerId };
            byte[] data = await _quotationApproveService.ExportQuotation(customerId);
            return File("报价.xlsx", data);

            //var fileName = await _quotationApproveService.GetCDKDFee(customerId);
            //var stream = System.IO.File.OpenRead(fileName);
            //return File(stream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        }

        public class ExportQuotationRequest
        {
            public List<int> CustomerIds
            {
                get; set;
            }


            public DateTime time
            {
                get; set;
            }
        }

        [HttpPost]
        public async Task<IActionResult> ExportQuotation(ExportQuotationRequest request)
        {
            byte[] data = await _quotationApproveService.ExportQuotation(request.CustomerIds, request.time);
            return File("报价.zip", data);
        }


        [AllowAnonymous]
        [HttpPost]
        public async Task<IActionResult> GenerateFeeBaseFile(GenerateFeeBaseFileMessage param)
        {
            await _quotationApproveService.UpdateFeeBaseFile(param);
            return Ok();
        }
        #region 快递调价处理
        [HttpPost]
        public async Task<IActionResult> InputExpressSettlement()
        {
            var filelist = (await Request.ReadFormAsync()).Files;
            if (filelist != null && filelist.Count > 0)
            {
                var file = filelist[0];
                using (var ms = new System.IO.MemoryStream())
                {
                    file.CopyTo(ms);

                    var result = _quotationService.InputExpressSettlement(ms.ToArray());
                    string json = _quotationService.ConvertSettlementView(result);
                    string url = _aliYunPostFileSerivce.PostHttpFile(new MemoryStream(ms.ToArray()), Guid.NewGuid().ToString() + ".xlsx");
                    return Ok(new { json = json, url = url, detail = result });
                }
            }
            else
            {
                return Error("请上传一个文件");
            }
        }


        #endregion



        #region 折扣信息处理
        [HttpPost]
        public async Task<IActionResult> InputChinaPostDiscountData()
        {
            var filelist = (await Request.ReadFormAsync()).Files;
            if (filelist != null && filelist.Count > 0)
            {
                var file = filelist[0];
                var result = await _quotationService.ImportExcelToChinaPostDiscountDataJson(file.OpenReadStream());
                return Ok(result);
            }
            else
            {
                return Error("请上传一个文件");
            }
        }
        public async Task<IActionResult> SendDingDingByDiscount(DiscountDto dto)
        {
            if (dto.discountData == null || dto.discountData.Count == 0)
                throw new Exception("无折扣数据提交，请导入数据后提交！");


            //四个渠道才有折扣
            if (dto.ExpressId != 26 && dto.ExpressId != 437 && dto.ExpressId != 106 && dto.ExpressId != 126) { throw new Exception("仅E邮宝A/E邮宝B/E特快/特货E邮宝，才有折扣！"); }

            if (dto.discountData.Count > 0)
            {
                int userId = User.GetUserContent().Id;
                string processInstanceId =
                    await _quotationService.SendDingDingByDiscount(dto, userId);
                long approveId =
                    await _quotationApproveService.SaveApproveByDiscount(processInstanceId, userId, dto);
            }
            return Ok();
        }
        #endregion
    }
}
