using NPOI.SS.Formula.PTG;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ZhonTai.Admin.Core.Consts;
using ZhonTai.Admin.Services.ProjectLink;
using ZhonTai.DynamicApi.Attributes;
using ZhonTai.DynamicApi;
using ZhonTai.Admin.Domain.Project;
using Microsoft.AspNetCore.Mvc;
using ZhonTai.Admin.Core.Dto;
using ZhonTai.Admin.Services.ProjectStat.Dto;
using ZhonTai.Admin.Domain.Org;
using System.ComponentModel.DataAnnotations;
using Microsoft.AspNetCore.Http;
using ZhonTai.Admin.Core.Configs;
using Microsoft.Extensions.Options;
using System.IO;
using ZhonTai.Common.Files;
using ZhonTai.Admin.Core.Helpers;
using Microsoft.AspNetCore.Hosting;
using System.Data;
using ZhonTai.Admin.Domain.ProjectLink;
using ZhonTai.Common.Extensions;

namespace ZhonTai.Admin.Services.ProjectStat
{
    /// <summary>
    /// 项目统计服务
    /// </summary>
    [Order(10)]
    [DynamicApi(Area = AdminConsts.AreaName)]
    public class ProjectStatService : BaseService, IProjectStatService, IDynamicApi
    {
        private IProjectStatRepository _projectStatRepository => LazyGetRequiredService<IProjectStatRepository>();
        private IProjectRepository _projectRepository => LazyGetRequiredService<IProjectRepository>();
        private IProjectPriceRepository _projectPriceRepository => LazyGetRequiredService<IProjectPriceRepository>();
        private IOrgRepository _orgRepository => LazyGetRequiredService<IOrgRepository>();
        private OSSConfig _oSSConfig => LazyGetRequiredService<IOptions<OSSConfig>>().Value;
        private IHttpContextAccessor _httpContextAccessor => LazyGetRequiredService<IHttpContextAccessor>();
        private IProjectLinkRepository _projectLinkRepository => LazyGetRequiredService<IProjectLinkRepository>();

        public ProjectStatService()
        {
        }
        /// <summary>
        /// 查询统计管理分页
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<PageOutput<ProjectStatManagePageOutput>> GetManagePageAsync(PageInput<ProjectStatManagePageInput> input)
        {
            var ProjectId = input.Filter?.ProjectId;
            var TenantId = input.Filter?.TenantId;
            var IsSettele = input.Filter?.IsSettele;
            var EffectDate = input.Filter?.EffectDate;

            var list = _projectStatRepository.Select.DisableGlobalFilter(FilterNames.Tenant)
                .WhereIf(ProjectId.HasValue && ProjectId.Value > 0, a => a.ProjectId == ProjectId)
                .WhereIf(TenantId.HasValue && TenantId.Value > 0, a => a.TenantId == TenantId)
                .WhereIf(IsSettele.HasValue, a => a.IsSettle == IsSettele)
                .WhereIf(EffectDate.HasValue, a => a.EffectDate == EffectDate)
                .GroupBy(m => new { m.ProjectId, m.TenantId, m.EffectDate })
            .Count(out var total)
            .Page(input.CurrentPage, input.PageSize)
            .ToList(m => new ProjectStatManagePageOutput()
            {
                ProjectId = m.Key.ProjectId,
                TenantId = m.Key.TenantId.Value,
                EffectDate = m.Key.EffectDate,
                VaildCount = m.Sum(m.Value.ValidCount),
                Count = m.Sum(m.Value.ValidCount),
                IsSettle = m.Sum(m.Value.IsSettle) > 0 ? 1 : 0,
                ProjectName = "",
                OrgName = "",
                TotalCommission = m.Sum(m.Value.CommissionPrice * m.Value.ValidCount),
            });
            //项目名称
            var listProjectId = list.Select(m => m.ProjectId).Distinct().ToList();
            if (listProjectId.Count() > 0)
            {
                var listProject = await _projectRepository.Select.DisableGlobalFilter(FilterNames.Tenant).Where(m => listProjectId.Contains(m.Id)).ToListAsync(m => new
                {
                    m.Id,
                    m.Name
                });
                foreach (var item in list)
                {
                    var project = listProject.FirstOrDefault(m => m.Id == item.ProjectId);
                    if (project != null)
                        item.ProjectName = project.Name;
                }
            }
            //平台
            var listTenantId = list.Select(m => m.TenantId).Distinct().ToList();
            if (listTenantId.Count() > 0)
            {
                var listTenant = await _orgRepository.Select.DisableGlobalFilter(FilterNames.Tenant).Where(m => listTenantId.Contains(m.TenantId.Value)).ToListAsync(m => new
                {
                    m.TenantId,
                    m.Name
                });
                foreach (var item in list)
                {
                    var model = listTenant.FirstOrDefault(m => m.TenantId == item.TenantId);
                    if (model != null)
                        item.OrgName = model.Name;
                }
            }
            var data = new PageOutput<ProjectStatManagePageOutput>()
            {
                List = list,
                Total = total
            };

            return data;
        }

        private static object locker = new object();//创建锁
        private static List<long> ProjectIds = new List<long>();//项目
        /// <summary>
        /// 上传统计文件
        /// </summary>
        /// <param name="file">文件</param>
        /// <param name="ProjectId">文件目录</param>      
        /// <returns></returns>            
        public async Task UploadAsync([Required] IFormFile file, [Required] long ProjectId)
        {
            try
            {
                lock (locker)//加锁
                {
                    if (ProjectIds.Contains(ProjectId))
                    {
                        throw new Exception("该项目统计数据正在上传，请稍后");
                    }
                }
                var localUploadConfig = _oSSConfig.LocalUploadConfig;

                var extention = Path.GetExtension(file.FileName).ToLower();
                if (extention != ".xlsx")
                {
                    throw new Exception($"请上传.xlsx格式文件");
                }
                var fileLenth = file.Length;
                if (fileLenth <= 0)
                {
                    throw new Exception("文件不能为空");
                }
                if (fileLenth > localUploadConfig.MaxSize)
                {
                    throw new Exception($"文件大小不能超过{new FileSize(localUploadConfig.MaxSize)}");
                }
                if (ProjectId <= 0)
                {
                    throw new Exception($"请输入有效项目Id");
                }

                string fileDirectory = "stat";

                string SaveFileName = FreeUtil.NewMongodbId().ToString();

                var filePath = Path.Combine(fileDirectory, SaveFileName + extention).ToPath();

                var uploadHelper = LazyGetRequiredService<UploadHelper>();
                var env = LazyGetRequiredService<IWebHostEnvironment>();
                fileDirectory = Path.Combine(env.WebRootPath, fileDirectory).ToPath();
                if (!Directory.Exists(fileDirectory))
                {
                    Directory.CreateDirectory(fileDirectory);
                }
                filePath = Path.Combine(env.WebRootPath, filePath).ToPath();
                await uploadHelper.SaveAsync(file, filePath);

                //导入数据
                var datatable = NOPIHelper.ReadExcel(filePath);
                if (datatable == null || datatable.Rows.Count <= 0)
                {
                    throw new Exception($"文件不能为空");
                }
                var listPrice = await _projectPriceRepository.Select.DisableGlobalFilter(FilterNames.Tenant).Where(m => m.ProjectId == ProjectId).ToListAsync();
                if (listPrice.Count() <= 0)
                {
                    throw new Exception($"项目不存在");
                }
                bool IsComplete = true; //标准是否完整 true完整 false不完整
                foreach (var item in listPrice)
                {
                    if (datatable.Columns[item.Name] == null)
                    {
                        IsComplete = false;
                        break;
                    }
                }
                if (datatable.Columns["二维码编号"] == null || datatable.Columns["作业日期"] == null|| !IsComplete)
                {
                    throw new Exception($"导入格式不正确");
                }
                List<string> listDate = (from d in datatable.AsEnumerable() select d.Field<string>("作业日期")).ToList();
                var listDateInt = listDate.Select(m => int.Parse(m.Replace("-", "")));
                //已结算数据是否存在
                var count = await _projectStatRepository.Select.DisableGlobalFilter(FilterNames.Tenant).Where(m => m.ProjectId == ProjectId && listDateInt.Contains(m.EffectDateNum) && m.IsSettle == 1).CountAsync();
                if (count > 0)
                {
                    throw new Exception($"请删除作业时间已结算的数据");
                }
                //是否有覆盖数据存在
                var listFuGai = await _projectStatRepository.Select.DisableGlobalFilter(FilterNames.Tenant).Where(m => m.ProjectId == ProjectId && listDateInt.Contains(m.EffectDateNum) && m.IsSettle == 0).ToListAsync(m=>m.EffectDateNum);
                if (listFuGai.Count() > 0)
                {
                     listFuGai = listFuGai.Distinct().ToList();
                     await _projectStatRepository.UpdateDiy.Set(m=>m.IsDeleted,true).Where(m => listFuGai.Contains(m.EffectDateNum)).ExecuteUpdatedAsync();
                }
                List<ProjectStatEntity> list = new List<ProjectStatEntity>();
                foreach (DataRow row in datatable.Rows)
                {
                    string num = row["二维码编号"]?.ToString();
                    DateTime EffectDate = row["作业日期"].ToDateTime();
                    int EffectDateNum = EffectDate.ToString("yyyyMMdd").ToInt();

                    var link = await _projectLinkRepository.Select.DisableGlobalFilter(FilterNames.Tenant).Where(m => m.ProjectId == ProjectId && m.Num==num ).ToOneAsync();                    
                    foreach (var price in listPrice)
                    {
                        var model=new ProjectStatEntity()
                        {
                            Num = num,
                            EffectDate = EffectDate,
                            EffectDateNum = EffectDateNum,
                            ProjectPriceId = price.Id,
                            ProjectId = price.ProjectId,
                            ValidCount = row[price.Name].ToInt(),
                            Name = price.Name,
                            CommissionPrice = 0,
                            IsSettle = 0,
                            TenantId = link?.TenantId,
                        };
                        list.Add(model);
                    }
                }
                await _projectStatRepository.InsertAsync(list);
            }
            catch (Exception ex)
            {
                throw new Exception($"导入项目统计异常");
            }
            finally
            {
                ProjectIds.Remove(ProjectId);
            }
        }
        /// <summary>
        /// 下载项目统计模板
        /// </summary>        
        /// <returns></returns>        
        [HttpGet]
        public string DownLinkCodeAsync()
        {
            string fileDirectory = "stat";
            var filePath = Path.Combine(fileDirectory, "statcode.xlsx").ToPath();

            var env = LazyGetRequiredService<IWebHostEnvironment>();
            var file = Path.Combine(env.WebRootPath, filePath).ToPath();
            if (!System.IO.File.Exists(file))
            {
                throw new Exception($"项目统计模板文件不存在");
            }

            var linkUrl = $"{_httpContextAccessor.HttpContext.Request.Scheme}://{_httpContextAccessor.HttpContext.Request.Host.Value}/{filePath}";

            return linkUrl;
        }
    }
}
