using Bailun.DC.Common;
using Bailun.DC.DB.Base;
using Bailun.DC.Models;
using Bailun.DC.Models.Common;
using Bailun.DC.Models.Common.Page;
using Bailun.DC.Models.Dtos.Finance;
using Bailun.DC.Models.WebApiModels;
using Dapper;
using MySql.Data.MySqlClient;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;

namespace Bailun.DC.Services.WebApiService
{
    public partial class FinanceService
    {
        public CommonApiResponseDto<FinanceDto> GetCashFlowStatement(GetCashFlowStatementInput input)
        {
            try
            {
                var dtos = new FinanceDto();
                var data = GetFinanceFeeList(input);
                if (data.Count > 0)
                {
                    var url = ConfigHelper.AppSetting("cwUrl");
                    url += $"?BeginRepayTime={input.PaymentTimeStart.ToString("yyyy-MM-dd")}&EndRepayTime={input.PaymentTimeEnd.ToString("yyyy-MM-dd")}";
                    var listInterest = new FinanceReportServices().ListInterestExpense(url);//手续费
                    var listHandleFee = new FinanceReportServices().ListFinanceHandleFee(input.PaymentTimeStart, input.PaymentTimeEnd, null, "");//利息支出

                    var Col = data.GroupBy(a => a.company_name).Select(p => p.Key).OrderBy(a => a).ToList();
                    var listValue = new List<Tuple<string, List<decimal>>>();
                    for (var i = 0; i < Col.Count; i++)
                    {
                        //主体下所有费用单
                        var feedata = data.Where(x => x.company_name == Col[i]).ToList();
                        foreach (var item in feedata)
                        {
                            var obj = listValue.Where(a => a.Item1 == item.type_name).FirstOrDefault();

                            if (obj == null)
                            {
                                var listItems = new List<decimal>();
                                while (listItems.Count < Col.Count)//所有主体都添加上
                                {
                                    listItems.Add(0.00M);
                                }
                                listItems[i] = item.amount_rmb ?? 0;//当前主体赋值
                                listValue.Add(new Tuple<string, List<decimal>>(item.type_name, listItems));
                            }
                            else
                            {
                                obj.Item2[i] += item.amount_rmb ?? 0;
                            }
                        }
                    }
                   var jsonStr = GenerateStr(Col, listValue);
                    //dtos.Col.Add(new columnsObj
                    //{
                    //    key = "key",
                    //    title = "费用类型"
                    //});
                    //for (int j = 0; j < Col.Count; j++)
                    //{
                    //    var keyInfo = new columnsObj
                    //    {
                    //        key = "key" + j,
                    //        title = Col[j]
                    //    };
                    //    dtos.Col.Add(keyInfo);
                    //}
                    //var jsonStr = "[";
                    //for (int i = 0; i < listValue.Count; i++)
                    //{
                    //    jsonStr += "{";
                    //    jsonStr += "\"key\":\"" + listValue[i].Item1 + "\",";//第一条费用类型
                    //    for (int j = 0; j < listValue[i].Item2.Count; j++)//第一条类型里所有数据
                    //    {
                    //        jsonStr += "\"" + dtos.Col[j + 1].key + "\":\"" + listValue[i].Item2[j] + "\",";
                    //    }
                    //    jsonStr = jsonStr.Trim(',');
                    //    jsonStr += "},";
                    //}
                    //jsonStr = jsonStr.Trim(',');
                    //jsonStr += "]";
                    //if (listInterest.Count > 0)
                    //{

                    //}
                    //if (listHandleFee.Count > 0)
                    //{

                    //}
                    dtos.Col = jsonStr.Item1;
                    dtos.Data = jsonStr.Item2;
                }
                return new CommonApiResponseDto<FinanceDto>
                {
                    Data = dtos
                };
            }
            catch (Exception e)
            {
                return new CommonApiResponseDto<FinanceDto> { IsSuccess = false, Message = e.Message };
            }
        }
        private List<Models.Api.mInterestExpense> GetMInterestExpense(string url)
        {
            using (var http = new HttpClient())
            {
                var result = http.GetStringAsync(url).GetAwaiter().GetResult();
                var obj = Newtonsoft.Json.JsonConvert.DeserializeObject<List<Models.Api.mInterestExpense>>(result);
                return obj;
            };
        }


        #region 付现流水明细
        /// <summary>
        /// 分页查询付现流水明细
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public CommonApiResponseDto<FinanceFeeDetailsPageOutputDto> GetFinanceFeeDetailsPage(FinanceFeeDetailsPageInputDto input)
        {
            var result = new CommonApiResponseDto<FinanceFeeDetailsPageOutputDto> { Data = new FinanceFeeDetailsPageOutputDto() };
            var sqlWhere = BuildAllotOperationLogPageQuerySqlWhere(input, out DynamicParameters parameters);
            if (!input.IsPages)
            {
                result.Data.Items = SimpleCRUD.Query<FinanceFeeDetailsListItem>(sqlWhere, parameters, GlobalConfig.ConnectionString).ToList();
                return result;
            }
            using (var cn = new MySqlConnection(GlobalConfig.ConnectionString))
            {
                int total = 0;
                result.Data.Items = cn.Page<FinanceFeeDetailsListItem>(input.PageIndex, input.PageNumber, sqlWhere, ref total, parameters).AsList();
                result.Data.Pages.CurrentPage = input.PageIndex;
                result.Data.Pages.PageSize = input.PageNumber;
                result.Data.Pages.Total = total;
            }
            return result;
        }

        public string BuildAllotOperationLogPageQuerySqlWhere(FinanceFeeDetailsPageInputDto input, out DynamicParameters parameters)
        {
            parameters = new DynamicParameters();
            StringBuilder sqlText = new StringBuilder();
            sqlText.Append(@"SELECT t1.* FROM dc_base_finance_fee AS t1
                             INNER JOIN dc_base_finance_company AS t2 ON t2.company_name = t1.company_name
                             WHERE t1.cost_status = 4 
                             AND (t1.is_lend IS NULL OR t1.is_lend = 1
                             	OR (t1.is_lend = 2 AND t1.lend_balance > 0)
                             	OR (t1.is_lend = 2 AND t1.cost_form = 1)
                             )");
            if (!string.IsNullOrWhiteSpace(input.CostNo))
            {
                sqlText.Append(" AND t1.cost_no = @CostNo ");
                parameters.Add("CostNo", input.CostNo);
            }
            if (!string.IsNullOrWhiteSpace(input.CompanyName))
            {
                sqlText.Append(" AND t1.company_name = @CompanyName ");
                parameters.Add("CompanyName", input.CompanyName);
            }
            if (!string.IsNullOrWhiteSpace(input.CostTypeName))
            {
                sqlText.Append(" AND t1.type_name = @CostTypeName ");
                parameters.Add("CostTypeName", input.CostTypeName);
            }
            if (input.CreateTime != null && input.CreateTime.Length == 2&& !string.IsNullOrWhiteSpace(input.CreateTime[0]) && !string.IsNullOrWhiteSpace(input.CreateTime[1]))
            {
                sqlText.Append(" AND t1.create_time >= @StartCreateTime  AND t1.create_time < @EndCreateTime ");
                parameters.Add("StartCreateTime", Convert.ToDateTime(input.CreateTime[0]));
                parameters.Add("EndCreateTime", Convert.ToDateTime(input.CreateTime[1]));
            }
            if (input.LastModifyDate != null && input.LastModifyDate.Length == 2 && !string.IsNullOrWhiteSpace(input.LastModifyDate[0]) && !string.IsNullOrWhiteSpace(input.LastModifyDate[1]))
            {
                sqlText.Append(" AND t1.last_modify_date >= @StartLastModifyDate AND t1.last_modify_date < @EndLastModifyDate ");
                parameters.Add("StartLastModifyDate", Convert.ToDateTime(input.LastModifyDate[0]));
                parameters.Add("EndLastModifyDate", Convert.ToDateTime(input.LastModifyDate[1]));
            }
            if (input.PayTime != null && input.PayTime.Length == 2 && !string.IsNullOrWhiteSpace(input.PayTime[0]) && !string.IsNullOrWhiteSpace(input.PayTime[1]))
            {
                sqlText.Append(" AND t1.pay_time = @StartPayTime AND t1.pay_time < @EndPayTime ");
                parameters.Add("StartPayTime", Convert.ToDateTime(input.PayTime[0]));
                parameters.Add("EndPayTime", Convert.ToDateTime(input.PayTime[1]));
            }
            sqlText.Append(" ORDER BY t1.create_time DESC ");
            return sqlText.ToString();
        }
        #endregion
        private List<ManagementCost> GetFinanceFeeList(GetCashFlowStatementInput input)
        {
            var sql = $@"select * from dc_base_finance_fee s1
left JOIN dc_base_finance_company s2
ON s1.company_name = s2.company_name
where s1.cost_status = 4
and (s1.is_lend is null or s1.is_lend = 1
or (s1.is_lend = 2 and s1.lend_balance > 0) or (s1.is_lend = 2 and s1.cost_form = 1))
and s1.pay_time >= @PaymentTimeStart and s1.pay_time < @PaymentTimeEnd
and s2.company_type = @CorporateEntity ";
            var para = new DynamicParameters();
            para.Add("PaymentTimeStart", input.PaymentTimeStart.Date);
            para.Add("PaymentTimeEnd", input.PaymentTimeEnd.AddDays(1).Date);
            para.Add("CorporateEntity", input.CorporateEntity);
            if (!string.IsNullOrWhiteSpace(input.CompanyName)
                && !string.IsNullOrWhiteSpace(input.FeeType))
            {
                sql += " and s1.type_name=@type and s1.company_name = @companyname";
                para.Add("type", input.FeeType);
                para.Add("companyname", input.CompanyName);
                if (input.IsPage)
                {
                    sql += "limit @limit offset @offset";
                    para.Add("limit", (input.PageIndex - 1) * input.PageNumber);
                    para.Add("offset", input.PageNumber);
                }
            }
            var data = SimpleCRUD.Query<ManagementCost>(sql, para, GlobalConfig.ConnectionString).ToList();
            foreach (var item in data)
            {
                if (item.cost_form == 2)
                {
                    item.amount = -(item.amount);
                    item.amount_rmb = -(item.amount_rmb);
                }

                //借支单待还余额
                if (item.cost_form == 3)
                {
                    if (item.is_lend.HasValue && item.is_lend.Value == 2 && ((item.lend_balance ?? 0) > 0))  //归还金额
                    {
                        item.amount = -(item.amount);
                        item.amount_rmb = -(item.amount_rmb);
                    }
                }
            }
            return data;
        }
        public CommonApiResponseDto<List<FinanceDetailsDto>> GetFinanceDetails(GetCashFlowStatementInput input)
        {
            try
            {
                //input.IsPage = true;
                var data = new List<ManagementCost>();
                if (input.Flag == 1)
                {
                    data = GetManagementCostList(input);
                }
                else
                {
                    data = GetFinanceFeeList(input);
                }
                var dto = data.Select(x => new FinanceDetailsDto
                {
                    Amount = Convert.ToDecimal(x.amount),
                    AmountRmb = Convert.ToDecimal(x.amount_rmb),
                    CompanyName = x.company_name,
                    Currency = x.dic,
                    DepartmentName = x.department_name,
                    FeeSuperType = x.type_name,
                    FeeId = x.cost_no,
                    Accounting = x.accounting_subject_name,
                    Reason = string.IsNullOrEmpty(x.cost_reason) ? x.cost_remark : x.cost_reason,
                    PayTime = x.pay_time.HasValue ?
                    x.pay_time.Value.ToString("yyyy-MM-dd HH:mm:ss") : "",
                    ReceiveUnit = x.bank_company
                }).ToList();
                dto.Add(new FinanceDetailsDto
                {
                    FeeId = "合计",
                    AmountRmb = dto.Sum(x => x.AmountRmb),
                    Amount = dto.Sum(x => x.Amount)
                });
                return new CommonApiResponseDto<List<FinanceDetailsDto>> { Data = dto };
            }
            catch (Exception e)
            {
                return new CommonApiResponseDto<List<FinanceDetailsDto>> { IsSuccess = false, Message = e.Message };
            }
        }

        public CommonApiResponseDto<FinanceDto> GetManagementCost(GetCashFlowStatementInput input)
        {
            var data = GetManagementCostList(input);
            var dtos = new FinanceDto();
            //var typeNameList = data.Select(x => x.TypeName).Distinct().ToList();//费用标题
            var costNameList = data.Select(x => x.management_cost_name).Distinct().ToList();//费用类型（借支/借还、付款、收款）
            var listValue = new List<Tuple<string, List<decimal>>>();
            for (var i = 0; i < costNameList.Count; i++)//根据费用类型取数
            {
                //从源数据里拿到所有数据
                var feedata = data.Where(x => x.management_cost_name == costNameList[i]).ToList();
                //赋值所有费用标题 没有的默认赋值0
                foreach (var item in feedata)
                {
                    //var fee = feedata.Where(x => x.TypeName == item).ToList();
                    var obj = listValue.Where(a => a.Item1 == item.type_name).FirstOrDefault();

                    if (obj == null)
                    {
                        var listItems = new List<decimal>();
                        while (listItems.Count < costNameList.Count)//所有主体都添加上
                        {
                            listItems.Add(0.00M);
                        }
                        listItems[i] = item.amount_rmb ?? 0;//当前主体赋值
                        listValue.Add(new Tuple<string, List<decimal>>(item.type_name, listItems));
                    }
                    else
                    {
                        obj.Item2[i] += item.amount_rmb ?? 0;
                    }
                }
            }
            var jsonStr = GenerateStr(costNameList, listValue);
            dtos.Col = jsonStr.Item1;
            dtos.Data = jsonStr.Item2;
            return new CommonApiResponseDto<FinanceDto>
            {
                Data = dtos,
            };
        }

        private List<ManagementCost> GetManagementCostList(GetCashFlowStatementInput input)
        {
            var sql = $@"select *
from dc_base_finance_management_cost s1
LEFT JOIN dc_base_finance_fee s2
ON s1.management_cost_type = s2.cost_form
and s1.management_cost_category = s2.accounting_subject_name
and s1.management_cost_title = s2.type_name
LEFT JOIN dc_base_finance_company s3 
ON s3.company_name = s2.company_name
where s2.cost_status = 4
and (s2.is_lend is null or s2.is_lend = 1
or (s2.is_lend = 2 and s2.lend_balance > 0) or (s2.is_lend = 2 and s2.cost_form = 1))
and s2.pay_time >= '{input.PaymentTimeStart.Date}' 
and s2.pay_time < '{input.PaymentTimeEnd.AddDays(1).Date}'
and s3.company_type = {input.CorporateEntity} ";
            var para = new DynamicParameters();
            if (!string.IsNullOrEmpty(input.CompanyName) &&
                !string.IsNullOrEmpty(input.FeeType))
            {
                sql += @" and s2.type_name = @typename 
and s1.management_cost_name = @managementcostname";
                para.Add("typename", input.FeeType);
                para.Add("managementcostname", input.CompanyName);
            }
            var data = SimpleCRUD.Query<ManagementCost>(sql, para, GlobalConfig.ConnectionString).ToList();
            data.ForEach((item) =>
            {
                if (item.cost_form == 2)
                {
                    item.amount = -(item.amount);
                    item.amount_rmb = -(item.amount_rmb);
                }
                //借支单待还余额
                if (item.cost_form == 3)
                {
                    if (item.is_lend.HasValue && item.is_lend.Value == 2 && ((item.lend_balance ?? 0) > 0))  //归还金额
                    {
                        item.amount = -(item.amount);
                        item.amount_rmb = -(item.amount_rmb);
                    }
                }
            });
            return data;
        }
        /// <summary>
        /// 生成前端需要的表头和内容
        /// </summary>
        /// <param name="Col"></param>
        /// <param name="listValue"></param>
        /// <returns></returns>
        private (List<columnsObj>,string) GenerateStr(List<string> Col, List<Tuple<string, List<decimal>>> listValue)
        {
            var colList = new List<columnsObj>();
            colList.Add(new columnsObj
            {
                key = "key",
                title = "费用类型"
            });
            for (int j = 0; j < Col.Count; j++)
            {
                var keyInfo = new columnsObj
                {
                    key = "key" + j,
                    title = Col[j]
                };
                colList.Add(keyInfo);
            }
            var jsonStr = "[";
            for (int i = 0; i < listValue.Count; i++)
            {
                jsonStr += "{";
                jsonStr += "\"key\":\"" + listValue[i].Item1 + "\",";//第一条费用类型
                for (int j = 0; j < listValue[i].Item2.Count; j++)//第一条类型里所有数据
                {
                    jsonStr += "\"" + colList[j + 1].key + "\":\"" + listValue[i].Item2[j] + "\",";
                }
                jsonStr = jsonStr.Trim(',');
                jsonStr += "},";
            }
            jsonStr = jsonStr.Trim(',');
            jsonStr += "]";
            return (colList, jsonStr);
        }
    }
}
