using System;
using System.Collections.Generic;
using XYY.Model.Standard.Finance;
using XYY.Core.Standard.ExcelHelper.MSExcelHelper;
using System.Threading.Tasks;
using XYY.Data.Standard.Finance;
using XYY.Model.Standard;

namespace XYY.Service.Standard.Finance
{
    public interface IServiceDeliveyBillService
    {
        Task<AddDeliveryBillResult> AddDeliveryBill(Finance_ServiceDeliveryBill bill);
        Task ChangeBillName(Finance_ServiceDeliveryBill bill);
        Task DeleteBill(int billId);
        Task FreightRecalculation(int channelId, DateTime start, DateTime end);
        byte[] GetAddDeliverBillTempler();
        Task<List<Finance_ServiceDeliveryBillDetail>> GetConfirmeds(int billId);
        Task<byte[]> GetConfirmedsData(int billId);
        Task<List<Finance_ServiceDeliveryBillDto>> GetDataAsStatus(int status, string billName);
        Task<List<Finance_ServiceDeliveryBillDetail>> GetDeductions(int billId);
        Task<byte[]> GetDeductionsData(int billId);
        Task<Dictionary<int, int>> GetGroupCounts(string billName);
        Task<List<Finance_ServiceDeliveryBillDetail>> GetNotConfirmeds(int billId);
        Task<byte[]> GetNotConfirmedsData(int billId);
        Task<List<Finance_ServiceDeliveryBillDetail>> GetOriginals(int billId);
        Task<byte[]> GetOriginalsData(int billId);
        Task<List<Finance_Logistics_LadingBillLogDto>> GetPaymentLog(int billId);
        Task<List<Finance_ServiceDeliveryBillDetail>> GetSupplements(int billId);
        Task<byte[]> GetSupplementsData(int billId);
        Task InputSupplementOrDeduction(int billId, string url, int type);
        List<Finance_ServiceDeliveryBillDetail> LoadDetailInput(string url);
        List<Finance_ServiceDeliveryBillDetailInput> LoadDetailSimpleInput(string url);
        List<Finance_ServiceDeliveryBillDetailInput> LoadDetailSimpleInput2(string url);
        byte[] OutAddDeliveryBillData(List<Finance_ServiceDeliveryBillDetailInput> list);
        byte[] OutData(List<Finance_ServiceDeliveryBillDetail> list);
        byte[] OutDataSimple(List<Finance_ServiceDeliveryBillDetail> list);
        Task Pass(int billId);
        Task PostPayment(int Id, decimal PostPayment);
        Task Rereject(int billId);
        Task UpdateConfirmed(int billId, string url);
    }

    public class ServiceDeliveyBillService : IServiceDeliveyBillService
    {
        readonly string tempPath = AppContext.BaseDirectory + "\\temp";
        IFiannce_ServiceDeliveyBillRepository _deliveyBillRepository;
        IExcelHelper _excelHelper;
        public ServiceDeliveyBillService(IFiannce_ServiceDeliveyBillRepository deliveyBillRepository, IExcelHelper excelHelper)
        {
            _deliveyBillRepository = deliveyBillRepository;
            if (!System.IO.Directory.Exists(tempPath))
                System.IO.Directory.CreateDirectory(tempPath);
            _excelHelper = excelHelper;
        }

        public async Task DeleteBill(int billId)
        {
            await _deliveyBillRepository.DeleteBill(billId);
        }

        public class OutDataInfo : MSExcelClassMapping<Finance_ServiceDeliveryBillDetail>
        {
            public OutDataInfo()
            {
                Map(x => x.TrackingNumber).Name("运单号");
                Map(x => x.Amount).Name("金额");
                Map(x => x.ChannelName).Name("渠道名称");
                Map(x => x.SysAmount).Name("系统金额");
                Map(x => x.SystemZipCode).Name("系统邮编");
                Map(x => x.SystemAreaCode).Name("系统分区");
                Map(x => x.SystemOnlineTime).Name("系统上网时间");
                Map(x => x.ConfirmedAmount).Name("确认金额");
                Map(x => x.Weight).Name("重量").Formattext(ExcelFormattextHelper.DefaultAmount);
                Map(x => x.SysWeight).Name("系统重量").Formattext(ExcelFormattextHelper.DefaultAmount);
                Map(x => x.Remark).Name("备注");
                Map(x => x.CustomerName).Name("客户");
                Map(x => x.SettlementCompanyName).Name("所属");
                Map(x => x.OrderStatus).Name("订单状态");
            }
        }

        public class InputDataSimpleInfo : MSExcelClassMapping<Finance_ServiceDeliveryBillDetailInput>
        {
            public InputDataSimpleInfo()
            {
                Map(x => x.TrackingNumber).Name("运单号");
                Map(x => x.Amount).Name("金额");
                Map(x => x.Remark).Name("备注");
            }
        }


        public class InputDataSimpleInfo3 : MSExcelClassMapping<Finance_ServiceDeliveryBillDetailInput>
        {
            public InputDataSimpleInfo3()
            {
                Map(x => x.TrackingNumber).Name("运单号");
                Map(x => x.Amount).Name("金额");
                Map(x => x.Weight).Name("重量").Formattext(ExcelFormattextHelper.DefaultAmount);
                Map(x => x.Remark).Name("错误");
            }
        }

        public class InputDataSimpleInfo2 : MSExcelClassMapping<Finance_ServiceDeliveryBillDetailInput>
        {
            public InputDataSimpleInfo2()
            {
                Map(x => x.TrackingNumber).Name("运单号");
                Map(x => x.Amount).Name("金额");
                Map(x => x.Weight).Name("重量").Formattext(ExcelFormattextHelper.DefaultAmount);
            }
        }

        public class OutDataSimpleInfo : MSExcelClassMapping<Finance_ServiceDeliveryBillDetail>
        {
            public OutDataSimpleInfo()
            {
                Map(x => x.TrackingNumber).Name("运单号");
                Map(x => x.Amount).Name("金额");
                Map(x => x.Remark).Name("备注");
            }
        }


        public byte[] OutAddDeliveryBillData(List<Finance_ServiceDeliveryBillDetailInput> list)
        {
            return _excelHelper.OutDataAsByte<InputDataSimpleInfo2, Finance_ServiceDeliveryBillDetailInput>(list);
        }


        public byte[] OutData(List<Finance_ServiceDeliveryBillDetail> list)
        {
            return _excelHelper.OutDataAsByte<OutDataInfo, Finance_ServiceDeliveryBillDetail>(list);

        }


        public byte[] OutDataSimple(List<Finance_ServiceDeliveryBillDetail> list)
        {
            return _excelHelper.OutDataAsByte<OutDataSimpleInfo, Finance_ServiceDeliveryBillDetail>(list);
        }



        public List<Finance_ServiceDeliveryBillDetail> LoadDetailInput(string url)
        {
            string filePath = tempPath + "\\" + Guid.NewGuid() + ".xlsx";
            System.Net.WebClient webClient = new System.Net.WebClient();
            byte[] data = webClient.DownloadData(url);
            return _excelHelper.LoadDataByByte<OutDataInfo, Finance_ServiceDeliveryBillDetail>(data);
        }

        public List<Finance_ServiceDeliveryBillDetailInput> LoadDetailSimpleInput(string url)
        {
            string filePath = tempPath + "\\" + Guid.NewGuid() + ".xlsx";
            System.Net.WebClient webClient = new System.Net.WebClient();
            byte[] data = webClient.DownloadData(url);
            return _excelHelper.LoadDataByByte<InputDataSimpleInfo, Finance_ServiceDeliveryBillDetailInput>(data);
        }


        public List<Finance_ServiceDeliveryBillDetailInput> LoadDetailSimpleInput2(string url)
        {
            string filePath = tempPath + "\\" + Guid.NewGuid() + ".xlsx";
            System.Net.WebClient webClient = new System.Net.WebClient();
            byte[] data = webClient.DownloadData(url);
            return _excelHelper.LoadDataByByte<InputDataSimpleInfo2, Finance_ServiceDeliveryBillDetailInput>(data);
        }

        public byte[] GetAddDeliverBillTempler()
        {
            List<Finance_ServiceDeliveryBillDetailInput> finance_ServiceDeliveryBillDetail = new List<Finance_ServiceDeliveryBillDetailInput>();
            return OutAddDeliveryBillData(finance_ServiceDeliveryBillDetail);
        }


        public async Task<AddDeliveryBillResult> AddDeliveryBill(Finance_ServiceDeliveryBill bill)
        {
            var details = LoadDetailSimpleInput2(bill.ServiceBillUrl);
            var result = await _deliveyBillRepository.AddDeliveryBill(bill, details);
            result.ErrorFileUrl = string.Empty;
            if (result.ErrorQty > 0)
            {
                result.ErrorFileUrl = _excelHelper.OutData<InputDataSimpleInfo3, Finance_ServiceDeliveryBillDetailInput>(result.ErrorList);
            }


            return result;
        }

        public async Task<List<Finance_ServiceDeliveryBillDetail>> GetConfirmeds(int billId)
        {
            return await _deliveyBillRepository.GetDetail(billId, 0, true);
        }


        public async Task<byte[]> GetConfirmedsData(int billId)
        {
            var list = await GetConfirmeds(billId);
            return OutData(list);
        }



        public async Task<List<Finance_ServiceDeliveryBillDto>> GetDataAsStatus(int status, string billName)
        {
            return await _deliveyBillRepository.GetDataAsStatus(status, billName);
        }

        public async Task<List<Finance_ServiceDeliveryBillDetail>> GetDeductions(int billId)
        {
            return await _deliveyBillRepository.GetDetail(billId, 1, null);
        }

        public async Task<byte[]> GetDeductionsData(int billId)
        {
            var list = await GetDeductions(billId);
            return OutDataSimple(list);
        }
        public async Task<Dictionary<int, int>> GetGroupCounts(string billName)
        {
            return await _deliveyBillRepository.GetGroupCounts(billName);
        }

        public async Task<List<Finance_ServiceDeliveryBillDetail>> GetNotConfirmeds(int billId)
        {
            return await _deliveyBillRepository.GetDetail(billId, 0, false);
        }


        public async Task<byte[]> GetNotConfirmedsData(int billId)
        {
            var list = await GetNotConfirmeds(billId);
            return OutData(list);

        }



        public async Task<List<Finance_ServiceDeliveryBillDetail>> GetOriginals(int billId)
        {
            return await _deliveyBillRepository.GetDetail(billId, 0, null);
        }

        public async Task<byte[]> GetOriginalsData(int billId)
        {
            var list = await GetOriginals(billId);
            return OutData(list);
        }

        public async Task<List<Finance_ServiceDeliveryBillDetail>> GetSupplements(int billId)
        {
            return await _deliveyBillRepository.GetDetail(billId, 2, null);
        }

        public async Task<byte[]> GetSupplementsData(int billId)
        {
            var list = await GetSupplements(billId);
            return OutDataSimple(list);
        }

        public async Task InputSupplementOrDeduction(int billId, string url, int type)
        {
            var list = LoadDetailSimpleInput(url);
            await _deliveyBillRepository.InputSupplementOrDeduction(billId, list, type);
        }

        public async Task UpdateConfirmed(int billId, string url)
        {
            var list = LoadDetailInput(url);
            List<Finance_ServiceDeliveryBillDetailInput> input = new List<Finance_ServiceDeliveryBillDetailInput>();
            foreach (var item in list)
            {
                input.Add(new Finance_ServiceDeliveryBillDetailInput
                {
                    Amount = item.ConfirmedAmount,
                    Remark = item.Remark,
                    TrackingNumber = item.TrackingNumber
                });
            }
            await _deliveyBillRepository.UpdateConfirmed(billId, input);
        }

        public async Task Pass(int billId)
        {
            await _deliveyBillRepository.Pass(billId);
        }

        public async Task Rereject(int billId)
        {
            await _deliveyBillRepository.Rereject(billId);
        }


        public async Task<List<Finance_Logistics_LadingBillLogDto>> GetPaymentLog(int billId)
        {
            return await _deliveyBillRepository.GetPaymentLog(billId);
        }


        public async Task PostPayment(int Id, decimal PostPayment)
        {
            var bill = await _deliveyBillRepository.GetAsync(Id);
            if (bill.Payment + PostPayment > bill.Receivables)
                throw new Exception("收款金额不可大于应收金额");
            bill.Payment += PostPayment;
            if (bill.Payment == bill.Receivables)
            {
                //更新结款完成
                bill.Status = FiannceServiceBillStatus.无欠款;
            }
            await _deliveyBillRepository.UpdateAsync(bill);
        }

        public async Task ChangeBillName(Finance_ServiceDeliveryBill bill)
        {
            await _deliveyBillRepository.UpdateByPrimaryKeyAsync(bill.Id, "Name", bill.Name);
        }

        public async Task FreightRecalculation(int channelId, DateTime start, DateTime end)
        {
           await  _deliveyBillRepository.FreightRecalculation(channelId, start, end);
        }
    }
}
