using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
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.Extensions;
using Siger.Middlelayer.Common.Helpers;
using Siger.Middlelayer.Log;
using Siger.Middlelayer.Repository;
using Siger.Middlelayer.TlmRepository.Entities;
using Siger.Middlelayer.TlmRepository.Repositories.Interface;
using Siger.Middlelayer.TlmRepository.Request;
using Siger.Middlelayer.TlmRepository.Response;
using Siger.Middlelayer.Utility.Helpers;
using Siger.Middlelayer.Utility.ImportEntities;

namespace Siger.ApiTLM.Controllers
{
    public class TechToolController : BaseController
    {
        private readonly IUnitOfWork _unitOfWork;
        private readonly IToolLifeToolTechRepository _lifeToolTechRepository;
        private readonly IToolLifeTechnologyRepository _technologyRepository;
        private readonly IToolLifeToolRepository _lifeToolRepository;
        public TechToolController(IUnitOfWork unitOfWork, IToolLifeToolTechRepository lifeToolTechRepository,
            IToolLifeTechnologyRepository technologyRepository, IToolLifeToolRepository lifeToolRepository)
        {
            _unitOfWork = unitOfWork;
            _technologyRepository = technologyRepository;
            _lifeToolTechRepository = lifeToolTechRepository;
            _lifeToolRepository = lifeToolRepository;
        }

        [HttpPost]
        public IActionResult GetPagedList([FromBody]RequestGetTechnology request)
        {
            var technology = _technologyRepository.Get(q =>
                q.product_id == request.product_id.ToInt() && q.route_id == request.route.ToInt() && q.status == (int)RowState.Valid
                                                   && q.project_id == ProjectId&&q.machine_type==request.machine_type.ToInt());
            if (technology == null)
            {
                throw new BadRequestException(RequestEnum.TechnologyNotFound);
            }
            var data = _lifeToolTechRepository.GetPagedList(technology.id, request.cutter_number, request.page, request.pagesize, request.toexcel.ToInt(), ProjectId);

            var res = new List<ResponseGetTechToolList>();
            foreach (var tooltech in data.Data)
            {
                tooltech.supplier = string.Join(',',
                    _technologyRepository.GetSuppliersByPartNo(0, tooltech.part_no, ProjectId).Select(t => t.name)
                        .ToList());
                res.Add(tooltech);
            }
            if (request.toexcel.ToInt() == 0)
            {
                return new PagedObjectResult(res, data.Total, request.page, request.pagesize);
            }

            return ExportTools(res);
        }

        [HttpPost]
        public IActionResult Add([FromBody] RequestAddTechTool request)
        {
            var technology = _technologyRepository.Get(q =>
                q.product_id == request.product_id.ToInt() && q.route_id == request.route.ToInt() && q.status == (int)RowState.Valid
                                                   && q.machine_type==request.machine_type.ToInt() && q.project_id == ProjectId);
            if (technology == null)
            {
                throw new BadRequestException(RequestEnum.TechnologyNotFound);
            }

            var isExist = _lifeToolTechRepository.IsExist(q => q.technology_id == technology.id
                 && q.status == (int)RowState.Valid && q.project_id == ProjectId && q.cutter_number == request.location);
            if (isExist)
            {
                throw new BadRequestException(RequestEnum.TechToolNumbersExist);
            }

            if (request.Materials == null || !request.Materials.Any())
            {
                throw new BadRequestException(RequestEnum.InputValueError);
            }

            foreach (var material in request.Materials)
            {
                if (material.quantity.ToInt() <= 0)
                {
                    throw new BadRequestException(RequestEnum.CountError);
                }

                var materialModel = _lifeToolTechRepository.GetMaterial(0, material.part_no, ProjectId);
                if (materialModel == null)
                {
                    throw new BadRequestException(RequestEnum.MaterialNotExist);
                }

                var tool = _lifeToolRepository.Get(t =>
                    (t.material_id == materialModel.id || t.part_no == material.part_no) && t.project_id == ProjectId && t.status == (int)RowState.Valid);
                if (tool == null)
                {
                    throw new BadRequestException(RequestEnum.CategoryNotNull);
                }

                var entity = new siger_project_toollife_tech_tool
                {
                    technology_id = technology.id,
                    remark = request.remark,
                    project_id = ProjectId,
                    cutter_number = request.location,
                    down_length = request.down_length,
                    down_tolerance = request.down_tolerance,
                    flute_count = request.flute_count.ToInt(),
                    flute_length = request.flute_length.ToDouble(),
                    reach_length = request.reach_length,
                    upper_tolerance = request.upper_tolerance,
                    tool_model = request.tool_model.ToInt(),
                    handle_model = request.handle_model.ToInt(),
                    part_no = material.part_no,
                    quantity = material.quantity.ToInt(),
                    rated_life = request.rated_life,
                    material_id = materialModel.id,
                    tool_code = string.IsNullOrEmpty(request.tool_code) ? "" : request.tool_code
                };
                _lifeToolTechRepository.Insert(entity);
            }

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

        [HttpPost]
        public IActionResult Edit([FromBody] RequestEditTechTool request)
        {
            var technology = _technologyRepository.Get(q =>
                q.product_id == request.product_id.ToInt() && q.route_id == request.route.ToInt() && q.status == (int)RowState.Valid
                && q.project_id == ProjectId);
            if (technology == null)
            {
                throw new BadRequestException(RequestEnum.TechnologyNotFound);
            }

            var toolTechs = _lifeToolTechRepository.GetList(q =>
                q.cutter_number == request.location && q.technology_id == technology.id && q.project_id == ProjectId &&
                q.status == (int)RowState.Valid).ToList();
            if (toolTechs == null)
            {
                throw new BadRequestException(CommonEnum.RecordNotFound);
            }

            if (request.Materials == null || !request.Materials.Any())
            {
                throw new BadRequestException(RequestEnum.InputValueError);
            }

            var oldPartNos = toolTechs.Select(t => t.part_no).ToList();
            var newPartNos = request.Materials.Select(t => t.part_no).ToList();
            foreach (var partNo in oldPartNos)
            {
                if (!newPartNos.Contains(partNo))
                {
                    var entity = toolTechs.FirstOrDefault(t => t.part_no == partNo);
                    if (entity == null)
                    {
                        continue;
                    }

                    entity.status = (int)RowState.Invalid;
                    _lifeToolTechRepository.Update(entity);
                }
            }
            foreach (var material in request.Materials)
            {
                if (material.quantity.ToInt() <= 0)
                {
                    throw new BadRequestException(RequestEnum.CountError);
                }
                var materialModel = _lifeToolTechRepository.GetMaterial(0, material.part_no, ProjectId);
                if (materialModel == null)
                {
                    throw new BadRequestException(RequestEnum.MaterialNotExist);
                }
                if (oldPartNos.Contains(material.part_no))
                {
                    var entity = toolTechs.FirstOrDefault(t => t.part_no == material.part_no);
                    if (entity != null)
                    {
                        entity.remark = request.remark;
                        entity.cutter_number = request.location;
                        entity.down_length = request.down_length;
                        entity.down_tolerance = request.down_tolerance;
                        entity.flute_count = request.flute_count.ToInt();
                        entity.flute_length = request.flute_length.ToDouble();
                        entity.handle_model = request.handle_model.ToInt();
                        entity.flute_length = request.flute_length.ToDouble();
                        entity.remark = request.remark;
                        entity.upper_tolerance = request.upper_tolerance;
                        entity.reach_length = request.reach_length;
                        entity.tool_model = request.tool_model.ToInt();
                        entity.rated_life = request.rated_life;
                        entity.material_id = materialModel.id;
                        entity.quantity = material.quantity.ToInt();
                    }
                    _lifeToolTechRepository.Update(entity);
                }
                else
                {
                    var entity = new siger_project_toollife_tech_tool
                    {
                        technology_id = technology.id,
                        remark = request.remark,
                        project_id = ProjectId,
                        cutter_number = request.location,
                        down_length = request.down_length,
                        down_tolerance = request.down_tolerance,
                        flute_count = request.flute_count.ToInt(),
                        flute_length = request.flute_length.ToDouble(),
                        reach_length = request.reach_length,
                        upper_tolerance = request.upper_tolerance,
                        tool_model = request.tool_model.ToInt(),
                        handle_model = request.handle_model.ToInt(),
                        part_no = material.part_no,
                        quantity = material.quantity.ToInt(),
                        rated_life = request.rated_life,
                        material_id = materialModel.id
                    };
                    _lifeToolTechRepository.Insert(entity);
                }
            }

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

        [HttpPost]
        public IActionResult Delete(int id)
        {
            var entity = _lifeToolTechRepository.Get(q =>
                q.id == id && q.project_id == ProjectId && q.status == (int)RowState.Valid);
            if (entity == null)
            {
                throw new BadRequestException(CommonEnum.RecordNotFound);
            }

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

        private IActionResult ExportTools(IEnumerable<ResponseGetTechToolList> responses)
        {
            if (!responses.Any())
            {
                throw new BadRequestException(CommonEnum.RecordNotFound);
            }

           
            var rootDir = FileSystemHelper.GetPhysicalFolders(FileSystemHelper.CommonFileSetting.PhysicalFolder, FileSystemHelper.ExportFileName);
            var temporaryFileName = $"Technology{DateTime.Now:yyyyMMddHHmmss}.xlsx";
            var fileName = Path.Combine(rootDir, temporaryFileName);

            var helper = new EpPlusExcelHelper<TechToolList>();
            try
            {
                var list = new List<TechToolList>();
                var index = 1;
                foreach (var tech in responses)
                {
                    var product = _lifeToolTechRepository.GetProduct(tech.product_id, ProjectId);
                    var productRoute = _lifeToolTechRepository.GetProductRoute(tech.route_id, ProjectId);
                    var entity = new TechToolList
                    {
                        Remark = tech.remark,
                        CutterNumber = tech.cutter_number,
                        DownTolerance = tech.down_tolerance.ToStr(),
                        UpperTolerance = tech.upper_tolerance.ToStr(),
                        ReachLength = tech.reach_length.ToStr(),
                        PartNo = tech.part_no,
                        MaterialName = tech.material_name,
                        Quantity = tech.quantity.ToString(),
                        Supplier = string.Join(',', _lifeToolTechRepository.GetSuppliersByPartNo(tech.material_id, tech.part_no, ProjectId).Select(t => t.name).ToList()),
                        ToolCategory = tech.category_name,
                        RatedLife = tech.rated_life.ToString(),
                        ProductName = product?.name ?? "",
                        Route = productRoute?.name ?? "",
                        ToolCode = tech.tool_code
                    };
                    list.Add(entity);
                    index++;
                }

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

        /// <summary>
        /// 获取刀位号
        /// </summary>
        /// <param name="productid"></param>
        /// <param name="route"></param>
        /// <param name="machine_type"></param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult GetCutterNumbers(string productid, string route,string machine_type)
        {
            var technology = _technologyRepository.Get(q =>
                q.product_id == productid.ToInt() && q.route_id == route.ToInt() && q.status == (int)RowState.Valid
                && q.project_id == ProjectId && q.machine_type==machine_type.ToInt());
            if (technology == null)
            {
                throw new BadRequestException(RequestEnum.TechnologyNotFound);
            }

            var CutterNumbers = _lifeToolTechRepository.GetList(t =>
                t.technology_id == technology.id && t.project_id == ProjectId && t.status == (int)RowState.Valid);
            var res = from r in CutterNumbers
                      select new ResponseCutterNumbers
                      {
                          cutter_number = r.cutter_number,
                          text = r.cutter_number
                      };
            return new ObjectResult(res.GroupBy(t => t.cutter_number).Select(t => t.FirstOrDefault()).ToList());
        }
    }
}