using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Net.Http;
using Microsoft.AspNetCore.Mvc;
using Siger.ApiCommon.Result;
using Siger.Middlelayer.Common;
using Siger.Middlelayer.Common.Configuration;
using Siger.Middlelayer.Common.Extensions;
using Siger.Middlelayer.Common.FieldEnum;
using Siger.Middlelayer.Common.Helpers;
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.WmsRepository.Repositories.Interface;
using Siger.Middlelayer.WmsRepository.Request;

namespace Siger.ApiTLM.Controllers
{
    public class ToolChoiceController : BaseController
    {
        private readonly IUnitOfWork _unitOfWork;
        private readonly IToolLifeToolChoiceRepository _choiceRepository;
        private readonly IToolLifeToolRepository _toolRepository;
        private readonly IToolLifeToolTechRepository _techRepository;
        private readonly IToolLifeWorkorderRepository _workorderRepository;
        private readonly IToolLifeTechnologyRepository _technologyRepository;
        private readonly IToolLifeToolChoiceSummaryRepository _choiceSummaryRepository;
        private readonly IProjectToollifeDetectionRecordRepository _detectionRecordRepository;
        private readonly Isiger_wms_stock_access_order_detailRepository _orderDetailRepository;
        private readonly IHttpClientFactory _httpClientFactory;

        public ToolChoiceController(IUnitOfWork unitOfWork, IToolLifeToolChoiceRepository choiceRepository,
            IToolLifeToolRepository toolRepository, IToolLifeToolTechRepository techRepository,
            IToolLifeWorkorderRepository workorderRepository, IToolLifeTechnologyRepository technologyRepository,
            IToolLifeToolChoiceSummaryRepository choiceSummaryRepository,IProjectToollifeDetectionRecordRepository detectionRecordRepository
            , Isiger_wms_stock_access_order_detailRepository orderDetailRepository,IHttpClientFactory httpClientFactory)
        {
            _unitOfWork = unitOfWork;
            _toolRepository = toolRepository;
            _choiceRepository = choiceRepository;
            _techRepository = techRepository;
            _workorderRepository = workorderRepository;
            _technologyRepository = technologyRepository;
            _choiceSummaryRepository = choiceSummaryRepository;
            _detectionRecordRepository = detectionRecordRepository;
            _orderDetailRepository = orderDetailRepository;
            _httpClientFactory = httpClientFactory;
        }

        [HttpPost]
        public IActionResult GetPagedList([FromBody]RequestGetToolChoice request)
        {
            var workOrder = _workorderRepository.Get(q =>
                q.workorder_code == request.workorder_code && q.id == request.id.ToInt()
                                                           && q.project_id == ProjectId && q.status == (int)RowState.Valid);
            if (workOrder == null)
            {
                throw new BadRequestException(RequestEnum.ToolWorkorderNotFound);
            }

            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 dataList = new List<ResponseGetTechToolList>();
            var total = 0;
            if (workOrder.order_status == OrderStatus.Completed)
            {
                var tools = _choiceRepository.GetPageList(technology.id, workOrder.id, "", request.page, request.pagesize, 0, ProjectId);
                dataList = tools.Data.ToList();
                total = tools.Total;
            }
            else
            {
                var tools = _techRepository.GetPagedList(technology.id, "", request.page, request.pagesize, 0, ProjectId, request.machine_type.ToInt(), request.tool_code);
                dataList = tools.Data.ToList();
                total = tools.Total;
            }

            var result = new List<ResponseGetTechToolList>();
            var choice = new siger_project_toollife_tool_choice();
            foreach (var tool in dataList)
            {
                ChoiceStatus status = ChoiceStatus.UnApply;
                if (workOrder != null)
                {
                    choice = _choiceRepository.Get(q => q.workorder_id == workOrder.id &&
                                                        q.technology_id == technology.id && q.material_id == tool.material_id
                                                        && q.project_id == ProjectId &&
                                                        q.status == (int)RowState.Valid);
                }
                if (choice != null)
                {
                    status = choice.choice_status;
                }

                var data = Mapper<ResponseGetTechToolList, ResponseGetTechToolList>.Map(tool);
                data.choice_status = (int) status;
                data.machine_quantity = workOrder?.count ?? 0;//设备数量
                data.quantity = choice?.quantity ?? tool.quantity;
                data.supplier = string.Join(',', _choiceRepository.GetSuppliersByPartNo(data.material_id, data.part_no, ProjectId).Select(t => t.name).ToList());

                result.Add(data);
            }

            return new PagedObjectResult(result, total, request.page, request.pagesize);
        }

        [HttpPost]
        public IActionResult GetSummaryPagedList([FromBody] RequestGetToolChoice 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);
                return new ObjectResult(new List<ResponseGetToolChoiceSummary>());
            }

            var workOrder = _workorderRepository.Get(q =>
                q.workorder_code == request.workorder_code && q.technology_id == technology.id
                                                           && q.project_id == ProjectId && q.status == (int)RowState.Valid);
            if (workOrder == null)
            {
                throw new BadRequestException(RequestEnum.ToolWorkorderNotFound);
            }

            var res = new List<ResponseGetToolChoiceSummary>();
            var apply = false;
            var summarys =
                _choiceSummaryRepository.GetSummaryPagedList(technology.id, workOrder.id, ProjectId).ToList();
            if (!summarys.Any())
            {
                apply = true;
                summarys = _choiceSummaryRepository.GetDataListFromTechTool(technology.id, "", ProjectId).ToList();
            }
            foreach (var summary in summarys)
            {
                if (!string.IsNullOrEmpty(summary.number) && res.Select(t => t.number).Contains(summary.number))
                {
                    continue;
                }
                var record = _detectionRecordRepository.Get(f => f.Projectid == ProjectId && f.Status != 0 && f.serial_number == summary.number && f.State != TlmDetectionState.InStock);
                if (record != null)
                {
                    continue;
                }
                summary.supplier = string.Join(',',
                    _choiceRepository.GetSuppliersByPartNo(0, summary.part_no, ProjectId).Select(t => t.name).ToList());
                summary.stock = _choiceSummaryRepository.CountStockQuantity(summary.material_id, summary.part_no, ProjectId, summary.positionId, summary.number);
                summary.quantity = apply ? summary.quantity * workOrder.count : summary.quantity;
                res.Add(summary);
            }

            return new ObjectResult(res.Where(f => !string.IsNullOrEmpty(f.number)).ToList());
        }

        /// <summary>
        /// 根据型号从wms获取库存信息
        /// </summary>
        /// <param name="id"></param>
        /// <param name="type"></param>
        /// <param name="page"></param>
        /// <param name="pagesize"></param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult GetStockFromWms(int id, int type, int page = 1, int pagesize = 10)
        {
            var responses = new List<ResponseGetStockFromWms>();
            if (type == 3) //取全部附件
            {
                Expression<Func<siger_project_toollife_tool, bool>> express = q =>
                    q.status == (int) RowState.Valid && q.project_id == ProjectId &&
                    q.category == TlmSettingCategory.Attachment;
                var entities = _toolRepository.GetList(express);
                if (!entities.Any())
                {
                    return new ObjectResult(responses);
                }

                var response = _choiceRepository.GetStockFromWms(entities.Select(m => m.part_no).ToList(), ProjectId);
                foreach (var fromWmse in response)
                {
                    var entity = entities.FirstOrDefault(q => q.part_no == fromWmse.category);
                    if (entity != null)
                    {
                        var data = Mapper<ResponseGetStockFromWms, ResponseGetStockFromWms>.Map(fromWmse);
                        data.tool_id = entity.id;
                        data.category = entity.name;
                        responses.Add(data);
                    }
                }
                var pagedEntities = responses.Skip((page - 1) * pagesize).Take(pagesize).ToList();
                return new PagedObjectResult(pagedEntities, responses.Count, page, pagesize);
            }
            else
            {
                var entity = _toolRepository.Get(q => q.id == id && q.status == (int)RowState.Valid && q.project_id == ProjectId && (int)q.category == type);
                if (entity == null)
                {
                    throw new BadRequestException(CommonEnum.RecordNotFound);
                }

                var response = _choiceRepository.GetStockFromWms(new List<string>{ entity.part_no }, ProjectId);
                foreach (var fromWmse in response)
                {
                    var data = Mapper<ResponseGetStockFromWms, ResponseGetStockFromWms>.Map(fromWmse);
                    data.tool_id = entity.id;
                    data.category = entity.name;
                    responses.Add(data);
                }
                var pagedEntities = responses.Skip((page - 1) * pagesize).Take(pagesize).ToList();
                return new PagedObjectResult(pagedEntities, responses.Count, page, pagesize);
            }
        }

        [HttpPost]
        public IActionResult GetHasChoice([FromBody]RequestGetHasChoice 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 workOrder = _workorderRepository.Get(q => q.technology_id == technology.id &&
                                                          q.workorder_code == request.workorder_code && q.project_id == ProjectId && q.status == (int)RowState.Valid);

            if (workOrder == null)
            {
                throw new BadRequestException(RequestEnum.ToolWorkorderNotFound);
            }

            var choices = _choiceRepository.GetPagedList(request.page, request.pagesize, q =>
                q.workorder_id == workOrder.id && q.technology_id == technology.id
                                               && q.project_id == ProjectId && q.status == (int) RowState.Valid
                                               && q.cutter_number == request.cutter_number);

            var responses = new List<ResponseGetStockFromWms>();
            var response = _choiceRepository.GetStockInfoes(choices.Data.Select(m => m.id).ToList(), ProjectId);
            foreach (var fromWmse in response)
            {
                var data = Mapper<ResponseGetStockFromWms, ResponseGetStockFromWms>.Map(fromWmse);
                responses.Add(data);
            }

            return new PagedObjectResult(responses, choices.Total, request.page, request.pagesize);
        }

        [HttpPost]
        public IActionResult EditSummary([FromBody]RequestEditSummary request)
        {
            if (request.Summarys == null || request.Summarys.Any())
            {
                throw new BadRequestException(CommonEnum.NoData);
            }

            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 workOrder = _workorderRepository.Get(q => q.technology_id == technology.id &&
                                                          q.workorder_code == request.workorder_code &&
                                                          q.project_id == ProjectId &&
                                                          q.status == (int) RowState.Valid);
            if (workOrder == null)
            {
                throw new BadRequestException(RequestEnum.ToolWorkorderNotFound);
            }

            if (workOrder.order_status != OrderStatus.Completed)
            {
                throw new BadRequestException(RequestEnum.PleaseOutStock);
            }

            foreach (var summary in request.Summarys)
            {
                var entity = _choiceSummaryRepository.Get(t =>
                    t.technology_id == technology.id && t.workorder_id == workOrder.id
                                                     && t.cutter_number == summary.cutter_number &&
                                                     t.part_no == summary.part_no
                                                     && t.status == (int) RowState.Valid && t.project_id == ProjectId);
                if (entity != null)
                {
                    entity.quantity = summary.quantity.ToInt();
                    _choiceSummaryRepository.Update(entity);
                    if (_unitOfWork.Commit() > 0)
                    {
                        return new ObjectResult(CommonEnum.Succefull);
                    }
                }
            }

            throw new BadRequestException(CommonEnum.Fail);
        }

        /// <summary>
        /// 出库
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [HttpPost]
        public IActionResult ToolOutStock([FromBody] RequestAddChoice request)
        {
            var workOrder = _workorderRepository.Get(q =>
                q.workorder_code == request.workorder_code && q.id == request.id.ToInt()
                                                           && q.project_id == ProjectId && q.status == (int)RowState.Valid);
            if (workOrder == null)
            {
                throw new BadRequestException(RequestEnum.ToolWorkorderNotFound);
            }

            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);
            }

            if (workOrder.order_status == OrderStatus.Completed)
            {
                throw new BadRequestException(RequestEnum.ToolsHasOutStock);
            }
            //TODO check

            //var tools = _techRepository.GetDataList(technology.id, request.paras.Select(s=>s.cutter_number).FirstOrDefault()??"", ProjectId);
            var cutternumber = request.paras.Select(s => s.cutter_number).FirstOrDefault() ?? "";
            var tools = _techRepository.GetList(f => f.project_id == ProjectId && f.status != 0 && f.technology_id == technology.id).ToList();
            if (!string.IsNullOrEmpty(cutternumber))
            {
                tools = tools.Where(f => f.cutter_number == cutternumber).ToList();
            }
            var choices = _choiceRepository.GetList(q =>
                q.workorder_id == workOrder.id && q.technology_id == technology.id && q.project_id == ProjectId &&
                q.status == (int) RowState.Valid).ToList();
            //var partNos = tools.Select(t => t.part_no).ToList();
            foreach (var choice in choices)
            {
                choice.status = (int)RowState.Invalid;
                _choiceRepository.Update(choice);
            }
            var toolList = new List<siger_project_toollife_tool_choice>();
            foreach (var tool in tools)
            {
                var stockStorages = _choiceRepository.GetStockStorage(tool.material_id);
                if(!stockStorages.Any())
                {
                    throw new BadRequestException(RequestEnum.LocationError);
                }                               
                var entity = new siger_project_toollife_tool_choice
                {
                    create_time = DateTime.Now,
                    creator = UserId,
                    cutter_number = tool.cutter_number,
                    workorder_id = workOrder.id,
                    technology_id = technology.id,
                    project_id = ProjectId,
                    choice_status = ChoiceStatus.HasApply,
                    part_no = tool.part_no,
                    quantity = tool.quantity,
                    supplier_id = stockStorages.FirstOrDefault().supplier_id,
                    material_id = tool.material_id,
                    remark = tool.remark
                };
                _choiceRepository.Insert(entity);
                toolList.Add(entity);
            }
            var chocieSummary = new List<siger_project_toollife_tool_choice_summary>();
            if (_unitOfWork.Commit() > 0)
            {
                var summarys = _choiceSummaryRepository.GetList(t =>
                    t.technology_id == technology.id && t.workorder_id == workOrder.id).ToList();
                foreach (var summary in summarys)
                {
                    summary.status = (int)RowState.Invalid;
                    _choiceSummaryRepository.Update(summary);
                }
                foreach (var para in request.paras)
                {
                    var tool = toolList.FirstOrDefault(t => t.part_no == para.part_no);
                    var model = new siger_project_toollife_tool_choice_summary
                    {
                        workorder_id = workOrder.id,
                        technology_id = technology.id,
                        quantity = para.count,
                        cutter_number = para.cutter_number,
                        part_no = para.part_no,
                        supplier_id = tool?.supplier_id ?? 0,
                        material_id = tool?.material_id ?? 0,
                        project_id = ProjectId,
                        serial_no = para.no,
                    };
                    chocieSummary.Add(model);
                    _choiceSummaryRepository.Insert(model);
                }
                if (_unitOfWork.Commit() > 0)
                {
                    //var choiceList = _choiceSummaryRepository.GetList(q => q.workorder_id == workOrder.id && q.technology_id == technology.id
                    //                                                                            && q.project_id == ProjectId && q.status == (int)RowState.Valid).ToList();
                    //if (!choiceList.Any())
                    //{
                    //    throw new BadRequestException(RequestEnum.NoChoiceTools);
                    //}

                    var result = _choiceRepository.OutStock(chocieSummary, ProjectId, UserId);
                    if (result)
                    {
                        var url = ConfigManager.GetValue("ChanglingErp", "Host", string.Empty);
                        if (!string.IsNullOrEmpty(url))
                        {
                            AsynToolData(url);
                        }
                        return new ObjectResult(CommonEnum.Succefull);
                    }
                }
            }
            throw new BadRequestException(CommonEnum.Fail);
        }

        private void AsynToolData(string url)
        {
            var client = _httpClientFactory.CreateClient();
            client.BaseAddress = new Uri(url);

        }
    }
}