using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using Microsoft.AspNetCore.Mvc;
using Siger.ApiCommon.Result;
using Siger.ApiCommon.Utilities;
using Siger.Middlelayer.Common;
using Siger.Middlelayer.Common.AppSettings;
using Siger.Middlelayer.Common.Helpers;
using Siger.Middlelayer.Common.ModuleEnum;
using Siger.Middlelayer.Log;
using Siger.Middlelayer.Repository;
using Siger.Middlelayer.Repository.Entities;
using Siger.Middlelayer.Repository.Extensions;
using Siger.Middlelayer.Repository.Repositories.Interface;
using Siger.Middlelayer.Repository.Request;
using Siger.Middlelayer.Repository.Response;
using Siger.Middlelayer.Utility.Helpers;
using Siger.Middlelayer.Utility.ImportEntities;
using UnixTimeHelper = Siger.Middlelayer.Common.Helpers.UnixTimeHelper;

namespace Siger.ApiConfig.Controller
{
    public class ProjectProductController : BaseController
    {
        private readonly IUnitOfWork _unitOfWork;
        private readonly ISigerProjectProductRepository _productRepository;
        private readonly ISigerProjectProductStructure _sigerProjectProductStructure;
        public ProjectProductController(IUnitOfWork unitOfWork, ISigerProjectProductRepository productRepository, ISigerProjectProductStructure sigerProjectProduct)
        {
            _unitOfWork = unitOfWork;
            _productRepository = productRepository;
            _sigerProjectProductStructure = sigerProjectProduct;
        }

        [HttpGet]
        public IActionResult GetProductItems(string key, int page = 1, int pagesize = PageSize)
        {
            var response = new List<ResponseGetProduct>();

            Expression<Func<siger_project_product, bool>> deaultExpression = q => q.status == (int)RowState.Valid && q.projectid == ProjectId;
            Expression<Func<siger_project_product, bool>> codeExpression = q => true;
            if (!string.IsNullOrWhiteSpace(key))
            {
                codeExpression = q => (q.code.Contains(key) || q.name.Contains(key) || q.remark.Contains(key) || q.drawingcode.Contains(key));
            }

            var predicate = deaultExpression.And(codeExpression);
            var list = _productRepository.GetPagedList(page, pagesize, predicate);

            foreach (var product in list.Data)
            {
                response.Add(Mapper<siger_project_product, ResponseGetProduct>.Map(product));
            }
            return new PagedObjectResult(response, list.Total, page, pagesize);
        }

        [HttpPost]
        public IActionResult OptProduct([FromBody] RequestUpdateProduct request)
        {
            if (string.IsNullOrWhiteSpace(request.code))
            {
                throw new BadRequestException(RequestEnum.ProductCodeIsNull);
            }
            var product = new siger_project_product();
            product.code = request.code;
            product.drawingcode = request.drawingcode;
            product.creatorid = UserId;
            product.name = request.name;
            product.projectid = ProjectId;
            product.remark = request.remark;
            product.createtime = UnixTimeHelper.GetNow();
            product.image = request.image;

            if (request.id == 0)
            {
                var code = _productRepository.Get(t => t.code == request.code && t.status == (int)RowState.Valid && t.projectid == ProjectId);
                if (code != null)
                    throw new BadRequestException(RequestEnum.ProductCodeIsExist);
                _productRepository.Insert(product);
            }
            else
            {
                var entity = _productRepository.Get(request.id);
                if (entity == null || entity.status != (int)RowState.Valid)
                {
                    throw new BadRequestException(RequestEnum.ProductNotFound);
                }
                var code = _productRepository.Get(t => t.code == request.code && t.status == (int)RowState.Valid && t.projectid == ProjectId && t.id != entity.id);
                if (code != null)
                {
                    throw new BadRequestException(RequestEnum.ProductCodeIsExist);
                }
                entity.code = request.code;
                entity.drawingcode = request.drawingcode;
                entity.name = request.name;
                entity.remark = request.remark;
                entity.image = request.image;
                _productRepository.Update(entity);
            }
            if (_unitOfWork.Commit() > 0)
            {
                if (request.id == 0)
                {
                    AddProductStructure(product.id);
                }
                return new ObjectResult(CommonEnum.Succefull);
            }
            throw new BadRequestException(CommonEnum.SystemExcetion);
        }
        void AddProductStructure(int productId)
        {
            _sigerProjectProductStructure.Insert(new siger_project_product_structure
            {
                parent_id = 0,
                itemid = productId,
                itemtype = ComboxItem.Product,
                user = UserId,
                status = (int)RowState.Valid,
                datetime = DateTime.Now,
                projectid = ProjectId,
            });
            if (_unitOfWork.Commit() < 0)
                Logger.WriteLineInfo("save AddProductStructure Error");
        }
        [HttpPost]
        public IActionResult DeleteProduct(int id)
        {
            var entity = _productRepository.Get(id);
            if (entity == null || entity.status != (int)RowState.Valid)
            {
                throw new BadRequestException(RequestEnum.ProductNotFound);
            }

            entity.status = (int)RowState.Invalid;
            _productRepository.Update(entity);
            if (_unitOfWork.Commit() > 0)
            {
                return new ObjectResult(CommonEnum.Succefull);
            }
            throw new BadRequestException(CommonEnum.SystemExcetion);
        }

        [HttpPost]
        public IActionResult DeleteProducts([FromBody] RequestDeleteEntities request)
        {
            if (request.ids == null || !request.ids.Any())
            {
                throw new BadRequestException(RequestEnum.ParameterError);
            }
            var entities = _productRepository.GetList(q => request.ids.Contains(q.id) && q.projectid == ProjectId).ToList();
            foreach (var entity in entities)
            {
                entity.status = (int)RowState.Invalid;
                _productRepository.Update(entity);
            }

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

        [HttpGet]
        public IActionResult ExportProducts()
        {
            var rootDir = FileSystemHelper.GetPhysicalFolders(FileSystemHelper.CommonFileSetting.PhysicalFolder, FileSystemHelper.ExportFileName);

            var products = _productRepository.GetList(q => q.projectid == ProjectId && q.status == (int)RowState.Valid);
            if (!products.Any())
            {
                throw new BadRequestException(RequestEnum.ProductNotFound);
            }
            var temporaryFileName = $"productlist_{DateTime.Now:yyyyMMddHHmmss}.xlsx";
            var fileName = Path.Combine(rootDir, temporaryFileName);

            var helper = new EpPlusExcelHelper<ProductList>();
            try
            {
                var productList = new List<ProductList>();
                var index = 1;
                foreach (var pro in products.ToList())
                {
                    var product = new ProductList
                    {
                        Name = pro.name,
                        DrawingCode = pro.drawingcode,
                        Code = pro.code,
                        Remark = pro.remark,
                        No = index
                    };
                    productList.Add(product);
                    index++;
                }

                helper.GenerateExcel(productList, fileName);
                return new ObjectResult($"{FileSystemHelper.CommonFileSetting.RequestPath}/{FileSystemHelper.ExportFileName}/{temporaryFileName}");
            }
            catch (Exception e)
            {
                Logger.WriteLineError("ExportProducts failed, error: " + e.Message);
                throw new BadRequestException(RequestEnum.ExportFailed);
            }
            finally
            {
                helper.Dispose();
            }
        }

        [HttpGet]
        public IActionResult GetProducts()
        {
            var products =
                _productRepository.GetList(q => q.projectid == ProjectId && q.status == (int)RowState.Valid);

            var responses = new List<ResponseGetProduct>();
            foreach (var product in products.ToList())
            {
                responses.Add(new ResponseGetProduct
                {
                    id = product.id,
                    name = product.name,
                    code = product.code,
                    drawingcode = product.drawingcode
                });
            }

            return new ObjectResult(responses);
        }
        /// <summary>
        /// 获取产品信息
        /// </summary>
        /// <param name="name"></param>
        /// <param name="count"></param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult GetProductsByCode(string name, int count)
        {
            if (count == 0)
            {
                count = 50;
            }
            var resp = _productRepository.GetData(ProjectId, name, count).Select(s => new ResponseGetProduct { id = s.id, name = s.name, code = s.code, drawingcode = s.drawingcode });
            return new ObjectResult(resp);
        }

        [HttpPost]
        public IActionResult UploadProductImages([FromBody] RequestUploadProductImage request)
        {
            if (request.ids == null || !request.ids.Any() || string.IsNullOrWhiteSpace(request.img))
            {
                throw new BadRequestException(RequestEnum.ParameterError);
            }
            var entities = _productRepository.GetList(q => request.ids.Contains(q.id) && q.projectid == ProjectId).ToList();
            foreach (var entity in entities)
            {
                entity.image = request.img;
                _productRepository.Update(entity);
            }

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