using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using Microsoft.AspNetCore.Mvc;
using Siger.ApiCommon.Result;
using Siger.Middlelayer.Common.Extensions;
using Siger.Middlelayer.AccRepository.Entities;
using Siger.Middlelayer.AccRepository.Repositories.Interface;
using Siger.Middlelayer.AccRepository.Response;
using Siger.Middlelayer.Common;
using Siger.Middlelayer.Repository;
using Siger.Middlelayer.Repository.Extensions;
using Siger.Middlelayer.Repository.Repositories.Interface;
using Siger.Middlelayer.AccRepository.Request;
using System.Threading.Tasks;
using System.IO;
using System.Reflection;
using Siger.Middlelayer.Log;
using Siger.Middlelayer.Common.ModuleEnum;
using Siger.ApiCommon.Utilities;
using Siger.Middlelayer.Common.AppSettings;
using Siger.Middlelayer.Common.Helpers;
using Siger.Middlelayer.Utility.Helpers;
using Siger.Middlelayer.Utility.ImportEntities;
using System.Text;
using System.Net.Http;
using System.Net;
using System.Net.Http.Headers;
using Microsoft.AspNetCore.Http;
using Siger.ApiCommon.Filters;

namespace Siger.ApiACC.Controllers
{
    public class PrintLabelFileController : BaseController
    {
        private readonly IUnitOfWork _unitOfWork;
        private readonly ISigerPrinterLebleFile _printerLebleFile;
        private readonly ISigerProjectProductRepository _sigerTrProduct;
        private readonly ISigerDict _sigerDict;
        private readonly ISigerTrSnTraceRepository _traceRepository;
        private readonly ISigerTrSnTraceDetailsRepository _traceDetailRepository;
        private readonly ISigerRoutingStationRpt _sigerRoutingStationRpt;
        private readonly ISigerProjectLevelSectionRepository _sigerProjectLevelSection;
        private readonly ISigerRoutingStationRptItem _sigerRoutingStationRptItem;
        private readonly ISigerProjectUserRepository _sigerProjectUser;
        private readonly IProductPlanRepository _productPlanRepository;
        private readonly ISigerProjectProductRepository _sigerProjectProduct;
        public PrintLabelFileController(IUnitOfWork unitOfWork, ISigerPrinterLebleFile printerLebleFile, ISigerProjectProductRepository sigerTrProduct
            , ISigerDict sigerDict, ISigerTrSnTraceRepository sigerTrSnTrace, ISigerTrSnTraceDetailsRepository sigerTrSnTraceDetails, ISigerRoutingStationRpt sigerRoutingStationRpt, ISigerProjectLevelSectionRepository sigerProjectLevelSection
            , ISigerRoutingStationRptItem sigerRoutingStationRptItem, ISigerProjectUserRepository sigerProjectUser, IProductPlanRepository productPlanRepository, ISigerProjectProductRepository sigerProjectProduct)
        {
            _unitOfWork = unitOfWork;
            _printerLebleFile = printerLebleFile;
            _sigerTrProduct = sigerTrProduct;
            _sigerDict = sigerDict;
            _traceRepository = sigerTrSnTrace;
            _traceDetailRepository = sigerTrSnTraceDetails;
            _sigerRoutingStationRpt = sigerRoutingStationRpt;
            _sigerProjectLevelSection = sigerProjectLevelSection;
            _sigerRoutingStationRptItem = sigerRoutingStationRptItem;
            _sigerProjectUser = sigerProjectUser;
            _productPlanRepository = productPlanRepository;
            _sigerProjectProduct = sigerProjectProduct;
        }

        [HttpGet]
        public IActionResult Getlist(string productid, string pn, string labeltype, int page = 1, int pagesize = 10)
        {
            Expression<Func<SigerTrPrinterLebleFile, bool>> Funcat = f => f.projectId == ProjectId && f.status == RowState.Valid.GetHashCode();
            Expression<Func<SigerTrPrinterLebleFile, bool>> Funproduct = f => true;
            Expression<Func<SigerTrPrinterLebleFile, bool>> Funpn = f => true;
            Expression<Func<SigerTrPrinterLebleFile, bool>> Funlabeltype = f => true;
            if (!string.IsNullOrEmpty(productid) && productid != "0")
                Funproduct = f => f.productid == productid;
            if (!string.IsNullOrEmpty(pn) && pn != "0")
                Funpn = f => f.pn.Contains(pn);
            if (!string.IsNullOrEmpty(labeltype) && labeltype != "0")
                Funlabeltype = f => f.labeltype == labeltype;
            var predicate = Funcat.And(Funproduct).And(Funpn).And(Funlabeltype);
            var data = _printerLebleFile.GetPagedList(page, pagesize, predicate);

            var response = new List<ResponsePrintLabelFile>();
            foreach (var item in data.Data)
            {
                var products = _sigerTrProduct.Get(t => t.projectid == ProjectId && t.code == item.productid && t.status == (int)RowState.Valid);
                var users = _printerLebleFile.GetUserInfo(item.uid.ToInt(), ProjectId);
                response.Add(new ResponsePrintLabelFile
                {
                    id = item.id,
                    productid = item.productid,
                    pn = item.pn,
                    pn_value = item.pn,
                    productid_value = products != null ? products.code : "",
                    labelfilename = item.labelfilename,
                    filepath = item.filepath,
                    labeltype_value = _sigerDict.GetDictValue(ProjectId, AccDictCost.labeltype, item.labeltype),
                    labeltype = item.labeltype,
                    uid = item.uid,
                    uid_value = users != null ? users.name : "",
                    transdatetime = item.transdatetime.ToString(ParameterConstant.DateTimeFormat),
                    image = item.image,
                    printtype = item.printtype
                });
            }

            return new PagedObjectResult(response, data.Total, page, pagesize);
        }

        [HttpPost]
        public IActionResult Add([FromBody] RequestPrinterLable lable)
        {
            var model = _printerLebleFile.Get(t => t.printtype == lable.Printtype && t.productid == lable.ProductId && t.projectId == ProjectId && t.status == (int)RowState.Valid && t.pn == lable.Pn);
            if (model != null)
            {
                throw new BadRequestException(RequestEnum.ProductPnFileIsExist);
            }
            _printerLebleFile.Insert(new SigerTrPrinterLebleFile
            {
                projectId = ProjectId,
                productid = lable.ProductId,
                pn = lable.Pn,
                labeltype = lable.Labeltype,
                labelfilename = lable.LabelFileName,
                filepath = lable.FilePath,
                transdatetime = DateTime.Now,
                uid = UserId.ToString(),
                image = lable.Image,
                printtype = lable.Printtype
            });
            if (_unitOfWork.Commit() > 0)
                return new ObjectResult(CommonEnum.Succefull);
            throw new BadRequestException(CommonEnum.Fail);
        }


        [HttpGet]
        public IActionResult Delete(string id)
        {
            foreach (var item in id.Split(','))
            {
                var NewObj = _printerLebleFile.Get(item.ToInt());
                if (NewObj == null)
                    throw new BadRequestException(CommonEnum.RecordNotFound);
                NewObj.status = (int)RowState.Invalid;
                _printerLebleFile.Update(NewObj);
            }

            if (_unitOfWork.Commit() > 0)
                return new ObjectResult(CommonEnum.Succefull);
            throw new BadRequestException(CommonEnum.Fail);
        }

        /// <summary>
        /// 上传文件
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public async Task<IActionResult> Upload()
        {
            var files = Request.Form.Files;

            //同时只能上传一个文件
            if (1 != files.Count)
            {
                //只允许上传单个文件
                throw new BadRequestException(RequestEnum.ErrorFileCount);
            }

            var formFile = files.First();
            if (".txt" != Path.GetExtension(formFile.FileName).ToLower())
            {
                //文件类型错误
                throw new BadRequestException(RequestEnum.ErrorFileType);
            }
            else
            {
                try
                {
                    long size = formFile.Length; //获得文件大小，以字节为单位
                    string newFileName = Guid.NewGuid().ToString() + ".txt";

                    var savefilepath = "TemporaryFiles/" + CommonConst.UploadLabelFilePath;
                    var physicaPath = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), savefilepath);
                    if (!Directory.Exists(physicaPath))
                    {
                        Directory.CreateDirectory(physicaPath);
                    }
                    var filePath = Path.Combine(physicaPath, newFileName);

                    using (var stream = new FileStream(filePath, FileMode.Create))
                    {
                        await formFile.CopyToAsync(stream);
                    }
                    var filename = Path.GetFileName(filePath);
                    var retName = Path.Combine(CommonConst.UploadLabelFilePath, filename);
                    return new ObjectResult(new { file_url = retName, name = formFile.FileName, size });
                }
                catch (Exception e)
                {
                    Logger.WriteLineError($"upload {formFile} failed, error:" + e.Message);
                    throw new BadRequestException(RequestEnum.ImportFailed);
                }
            }
        }

        /// <summary>
        /// 证书打印管理
        /// </summary>
        /// <param name="req"></param>
        /// <returns></returns>
        [HttpPost]
        public IActionResult GetCertificateList([FromBody] RequestPostCertificate req)
        {
            var result = _printerLebleFile.GetAllList(req, ProjectId);
            var response = new List<RequestCertificate>();
            foreach (var item in result.Data)
            {
                response.Add(new RequestCertificate
                {
                    id = item.id,
                    SN = item.SN,
                    productId = item.productId,
                    product_code = item.product_code,
                    product_name = item.product_name,
                    labeltype = item.labeltype,
                    printtype = item.printtype,
                    FilePath = item.FilePath,
                    FileName = item.FileName,
                    UID = item.UID,
                    TransDateTime = item.TransDateTime,
                    wo = item.wo,
                    Line = item.Line,
                    spec = item.spec,
                    lable_value = _sigerDict.GetDictValue(ProjectId, AccDictCost.labeltype, item.labeltype)
                });
            }
            return new PagedObjectResult(response, result.Total, req.page, req.pagesize);
        }

        /// <summary>
        /// excel模板查询               
        /// </summary>
        /// <param name="rpt"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<string> TrackingDetail([FromBody] RequestGeneralReport rpt)
        {

            if (!rpt.file_url.ToLower().EndsWith(".xlsx") && !rpt.file_url.ToLower().EndsWith(".xls"))
            {
                throw new BadRequestException(AccEnum.FileTypeError);
            }
            var product = _sigerProjectProduct.Get(q => q.id == rpt.id && q.status == (int)RowState.Valid && q.projectid == ProjectId);
            var productPlan = _productPlanRepository.Get(q => q.code == rpt.wo && q.status == (int)RowState.Valid && q.projectId == ProjectId);
            var query = new ResponseSnList()
            {
                Sn = rpt.sn,
                ProductCode = rpt.productCode,
            };
            var headerRoute = _sigerRoutingStationRpt.GetReportRouteHeaders(rpt.section, rpt.productCode, ProjectId);
            if (!headerRoute.Any())
                throw new BadRequestException(AccEnum.RouteRptIsEmpty);

            var stations = _sigerProjectLevelSection.GetLevelSectionIds(rpt.section, ProjectId).ToList();
            var HeaderItems = await _sigerRoutingStationRptItem.GetListAsync(f => f.projectId == ProjectId && f.Line == rpt.section && f.status == (int)RowState.Valid);

            var tracking = await GetNormals(rpt.sn, headerRoute, HeaderItems.ToList());
            var outPut = new List<TrackingSnStationUIFL>();
            var groupData = tracking.Bodys.GroupBy(g => g.Row);
            foreach (var g in groupData)
            {
                outPut.Add(new TrackingSnStationUIFL
                {
                    RowNo = g.Key,
                    RowsCols = g.ToList()
                });
            }
            var result = new GeneralTrackingSnResultFL
            {
                Heads = tracking.Heads,
                Bodys = outPut
            };
            if (string.IsNullOrEmpty(rpt.file_url))
            {
                throw new BadRequestException(RequestEnum.ErrorFilePath);
            }

            var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, rpt.file_url).Replace("Files", "TemporaryFiles");// FileUtility.GetTruePathFL(rpt.file_url);
            if (!System.IO.File.Exists(path))
            {
                throw new BadRequestException(RequestEnum.ErrorFilePath);
            }
            var path2 = FileUtility.GetTruePathDffl(CommonConst.DfflProgramFilePath);
            System.IO.File.Copy(path, path2, true);//允许覆盖目的地的同名文件
            EpPlusExcelTemplateHelper helper = new EpPlusExcelTemplateHelper();
            helper.GenerateTemplateFL(result, path2);
            var filename = Path.GetFileName(path2);
            var retName = Path.Combine("Files/image/", filename);
            path2 = "";
            result = null;
            return retName;


        }
        private async Task<GeneralTrackingSnFL> GetNormals(string sn, IEnumerable<HeaderStation> headerRoute, IEnumerable<SigerTrRoutingStaionRptItem> HeaderItems)
        {
            var tracking = new GeneralTrackingSnFL { Heads = new List<TrackingSnStationFL>(), Bodys = new List<TrackingSnStationFL>() };
            int row = 0;
            var snList = _printerLebleFile.GetSnList(sn, ProjectId);
            row += 1;
            var tracelst = await _traceRepository.GetListAsync(f => f.projectId == ProjectId && f.SN == sn, "TransDateTime");
            //RPT 标题
            int col = 0;
            var delivery_time = UnixTimeHelper.ConvertIntDateTime(snList.delivery_time);
            foreach (var h in headerRoute)
            {
                col += 1;
                var head = new TrackingSnStationFL
                {
                    Sn = sn,
                    Section = h.Station,
                    ProductCode = snList.ProductCode,
                    ProductNmae = snList.ProductNmae,
                    spec = snList.spec,
                    Line = snList.title,
                    WO = snList.WO,
                    install_count = snList.install_count,
                    ordernumber = snList.ordernumber,
                    quantity = snList.quantity.ToInt(),
                    delivery_time = delivery_time,
                    Station = h.Title,
                    Items = new List<ItemDtsFL>()
                };
                var body = new TrackingSnStationFL
                {
                    Row = row,
                    Sn = sn,
                    ProductCode = snList.ProductCode,
                    ProductNmae = snList.ProductNmae,
                    spec = snList.spec,
                    Line = snList.title,
                    WO = snList.WO,
                    install_count = snList.install_count,
                    ordernumber = snList.ordernumber,
                    quantity = snList.quantity.ToInt(),
                    delivery_time = delivery_time,
                    Section = h.Station,
                    Station = h.Title,
                    Items = new List<ItemDtsFL>()
                };
                var stationItem = HeaderItems.Where(f => f.Station == h.Station);
                var stationTracelst = tracelst.Where(f => f.Station == h.Station);
                if (!stationTracelst.Any())
                {

                    foreach (var hItem in stationItem)
                    {
                        //占位
                        head.Items.Add(new ItemDtsFL { Item = hItem.Item });
                        body.Items.Add(new ItemDtsFL { Item = hItem.Item, Values = "" });
                    }
                    head.Items.Add(new ItemDtsFL { Item = "结果", Values = "" });
                    head.Items.Add(new ItemDtsFL { Item = "人员", Values = "" });
                    head.Items.Add(new ItemDtsFL { Item = "时间", Values = "" });

                    body.Items.Add(new ItemDtsFL { Item = "结果", Values = "" });
                    body.Items.Add(new ItemDtsFL { Item = "人员", Values = "" });
                    body.Items.Add(new ItemDtsFL { Item = "时间", Values = "" });
                }
                else
                {
                    var trace = stationTracelst.FirstOrDefault();
                    if (trace != null)
                    {
                        var user = _sigerProjectUser.Get(f => f.mid == trace.UID);
                        var userName = user != null ? user.name : trace.UID.ToStr();

                        //取最新一条明细
                        var traceDtls = _traceDetailRepository.GetList(f => f.projectId == ProjectId && f.SeqID == trace.SeqID).ToList();
                        //整理检查项
                        foreach (var hItem in stationItem)
                        {
                            head.Items.Add(new ItemDtsFL { Item = hItem.Item });
                            var curItemDtls = traceDtls.Where(f => f.Item == hItem.Item).ToList();
                            if (!curItemDtls.Any())
                            {
                                body.Items.Add(new ItemDtsFL { Item = hItem.Item, Values = " " });
                                continue;
                            }
                            foreach (var d in curItemDtls)
                            {
                                if (body.Items.Exists(f => f.Item.Contains(hItem.Item)))
                                    continue;
                                body.Items.Add(new ItemDtsFL { Item = hItem.Item, Values = d.Value });
                            }
                        }
                        head.Items.Add(new ItemDtsFL { Item = "结果", Values = trace.Station != h.Station ? "" : trace.Result });
                        head.Items.Add(new ItemDtsFL { Item = "人员", Values = trace.Station != h.Station ? "" : userName });
                        head.Items.Add(new ItemDtsFL { Item = "时间", Values = trace.Station != h.Station ? "" : trace.TransDateTime.ToStr() });

                        if (traceDtls.Any())
                        {
                            body.Items.Add(new ItemDtsFL { Item = "结果", Values = trace.Station != h.Station ? "" : trace.Result });
                            body.Items.Add(new ItemDtsFL { Item = "人员", Values = trace.Station != h.Station ? "" : userName });
                            body.Items.Add(new ItemDtsFL { Item = "时间", Values = trace.Station != h.Station ? "" : trace.TransDateTime.ToStr() });
                        }
                        else
                        {
                            body.Items.Add(new ItemDtsFL { Item = "结果", Values = "" });
                            body.Items.Add(new ItemDtsFL { Item = "人员", Values = "" });
                            body.Items.Add(new ItemDtsFL { Item = "时间", Values = "" });
                        }
                    }
                }
                tracking.Bodys.Add(body);
                if (!tracking.Heads.Exists(f => f.Section == head.Section))
                    tracking.Heads.Add(head);
            }
            return tracking;
        }

        /// <summary>
        /// 下载文件
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        [NoTokenValidateFilter]
        public IActionResult DownloadFile(string file_url)
        {
            if (string.IsNullOrWhiteSpace(file_url))
            {
                return new NoContentResult();
            }
            var fileSetting = Config<FileSettings>.Get();
            if (fileSetting == null)
            {
                return new NoContentResult();
            }
            var rootDir = FileSystemHelper.GetPhysicalFolders( FileSystemHelper.CommonFileSetting.PhysicalFolder);

            if (!Directory.Exists(rootDir))
            {
                return new NoContentResult();
            }

            var url = file_url.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
            if (url.Length != 3)
            {
                return new NoContentResult();
            }

            var path = Path.Combine(rootDir, url[1], url[2]);
            if (!System.IO.File.Exists(path))
            {
                return new NoContentResult();
            }
            try
            {
                var stream = new FileStream(path, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite);
                var response = new HttpResponseMessage(HttpStatusCode.OK) { Content = new StreamContent(stream) };
                response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
                response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
                {
                    FileName = string.IsNullOrWhiteSpace(file_url) ? "" : file_url
                };

                return File(stream, "application/octet-stream");
            }
            catch
            {
                throw new BadRequestException(CommonEnum.Fail);
            }
        }

        [HttpPost]
        public IActionResult UploadPrintLable(IFormFile formFile)
        {
            if (Request.Form?.Files == null)
            {
                throw new BadRequestException(ConfigEnum.UploadFileNotFound);
            }
           
            var date = DateTime.Now.ToString("yyyy-MM-dd");

            var rootDir = FileSystemHelper.GetPhysicalFolders(FileSystemHelper.CommonFileSetting.PhysicalFolder, "PrintLable", date);           
          
            var files = Request.Form.Files;
            var file = files[0];
            var temporaryFileName = Guid.NewGuid().ToString("N") + FileHelper.GetExtension(file.FileName);
            var fileName = Path.Combine(rootDir, temporaryFileName);

            using (var stream = new FileStream(fileName, FileMode.Create))
            {
                file.CopyTo(stream);
            }

            return new ObjectResult($"{FileSystemHelper.CommonFileSetting.RequestPath}/PrintLable/{date}/{temporaryFileName}");
        }
    }
}
