using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Mvc;
using Siger.Middlelayer.Common;
using Siger.Middlelayer.Common.Helpers;
using Siger.Middlelayer.Common.ModuleEnum;
using Siger.Middlelayer.Repository.Repositories.Interface;
using Siger.Middlelayer.WmsRepository.Entities;
using Siger.Middlelayer.WmsRepository.Repositories.Interface;
using Siger.Middlelayer.WmsRepository.Response;

namespace Siger.ApiWMS.Controllers
{
    /// <summary>
    /// 打印相关功能
    /// </summary>
    public class PrintController : BaseController
    {
        Isiger_wms_storageRepository storage;
        Isiger_wms_stock_access_orderRepository order;
        Isiger_wms_stock_access_order_detailRepository detail;
        Isiger_wms_bussinese_contactsRepository business;
        Isiger_wms_storage_locationRepository location;
        Isiger_wms_storage_location_typeRepository locationtype;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="storage"></param>
        /// <param name="order"></param>
        /// <param name="detail"></param>
        /// <param name="business"></param>
        /// <param name="location"></param>
        /// <param name="locationtype"></param>
        public PrintController(Isiger_wms_storageRepository storage, Isiger_wms_stock_access_orderRepository order, Isiger_wms_stock_access_order_detailRepository detail, Isiger_wms_bussinese_contactsRepository business, Isiger_wms_storage_locationRepository location, Isiger_wms_storage_location_typeRepository locationtype)
        {
            this.storage = storage;
            this.order = order;
            this.detail = detail;
            this.business = business;
            this.location = location;
            this.locationtype = locationtype;
        }

        /// <summary>
        /// 单据信息
        /// </summary>
        /// <param name="billCode"></param>
        /// <returns></returns>
        public IActionResult GetBillInfo(string billCode)
        {
            //get order
            var orderData = order.Get(f => f.status == (int)RowState.Valid && f.order_number == billCode && f.projectid == ProjectId);
            if (orderData == null)
            {
                throw new BadRequestException(CommonEnum.RecordNotFound);
            }
            if (orderData.order_status == (int)WaveHousingState.Deleted || orderData.order_status == (int)WaveHousingState.Failed)
            {
                throw new BadRequestException(RequestEnum.CanNotPrint);
            }
            //get detail
            var details = detail.GetList(f => f.status == (int)RowState.Valid && f.orderid == orderData.id && f.projectid == ProjectId).ToList();

            var result = Mapper<siger_wms_stock_access_order, ResponseBillPrintInfo>.Map(orderData);
            result.detail = new List<ResponseStockAccessOrderDetail>();
            foreach (var item in details)
            {
                var tmp = Mapper<siger_wms_stock_access_order_detail, ResponseStockAccessOrderDetail>.Map(item);
                result.detail.Add(tmp);
            }

            //translate field
            //供应商、部门检测
            if (orderData.category == EnumHelper.GetEnumDesc(WaveHousingType.Production))
            {
                result.businessname = order.getDepartmentName(orderData.contactid, ProjectId);
            }
            else
            {
                //供应商
                var businessIDs = details.Select(f => f.businessid).Distinct().ToList();
                var businessDic = business.GetList(f => f.status == (int)RowState.Valid && f.projectid == ProjectId && businessIDs.Contains(f.id)).ToList().ToDictionary(f => f.id, f => f.name);
                //获取供应商名称
                foreach (var item in result.detail)
                {
                    if(item.businessid!=0)
                    {
                        if (businessDic.TryGetValue(item.businessid, out string v))
                        {
                            item.businessName = v;
                        }
                    }
                }
                var businessData = business.Get(f => f.status == (int)RowState.Valid && f.projectid == ProjectId && f.id == orderData.contactid);
                if (businessData != null)
                {
                    result.businessname = businessData.name;
                    result.businessContractUser = businessData.linkman;
                    result.phone = businessData.phone;
                }
                else if (businessData == null && businessDic.Any())
                {
                    var bus = business.Get(f => f.status == (int)RowState.Valid && f.projectid == ProjectId && f.id == businessDic.First().Key);
                    result.businessname = bus.name;
                    result.businessContractUser = bus.linkman;
                    result.phone = bus.phone;
                }
                else
                {
                    result.businessname = "NA";
                    result.businessContractUser = "NA";
                    result.phone = "NA";
                }
            }

            var createUser = detail.GetUserName(orderData.creator);
            var checkUser = detail.GetUserName(orderData.creator);
            var state = EnumHelper.GetEnumDesc((WaveHousingState)orderData.order_status);

            result.stateName = state;
            result.createName = createUser;
            result.checkName = checkUser;
            var storageData = storage.Get(orderData.storageid);
            if (storageData == null)
            {
                throw new BadRequestException(RequestEnum.StorageIDNotNull);
            }
            result.storagename = storageData.name;
            return new ObjectResult(result);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="type"></param>
        /// <param name="id">出入库单详情id</param>
        /// <returns></returns>
        public IActionResult GetWavehousingQRCode(managemodel type, int id)
        {
            switch (type)
            {
                case managemodel.Batch:
                    break;
                case managemodel.No:
                    break;
                default:
                    throw new BadRequestException(RequestEnum.ErrorPrintType);
            }

            var data = detail.Get(f => f.id == id && f.projectid == ProjectId && f.status == (int)RowState.Valid);
            if (data == null)
            {
                throw new BadRequestException(CommonEnum.NoData);
            }
            if (data.manage_mode != ((int)type).ToString())
            {
                throw new BadRequestException(RequestEnum.ManageModeNotMatching);
            }
            switch (type)
            {
                case managemodel.Batch:
                    return new ObjectResult(
                    new
                    {
                        code = data.batch_number,
                        time = data.audit_time == null || data.audit_time == DateTime.MinValue ? "" : data.audit_time.ToString(UnixTimeHelper.DateFormat),
                        data.material_name,
                        data.material_spec
                    });
                case managemodel.No:
                    return new ObjectResult(
                    new
                    {
                        code = data.serial_number,
                        time = data.audit_time == null || data.audit_time == DateTime.MinValue ? "" : data.audit_time.ToString(UnixTimeHelper.DateFormat),
                        data.material_name,
                        data.material_spec
                    });
                default:
                    throw new BadRequestException(RequestEnum.ErrorPrintType);
            }
        }

        #region 储位信息二维码
        /// <summary>
        /// 储位信息二维码
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public IActionResult GetLocation(int id)
        {
            var first = location.Get(f => f.id == id && f.status == (int)RowState.Valid && f.projectid == ProjectId);
            if (first == null)
            {
                throw new BadRequestException(CommonEnum.NoData);
            }
            //暂存所有操作过的id和名称
            var nodes = new List<Node>();
            nodes.Add(new Node { id = first.id, pid = first.parentid, name = first.realname, serial_number = first.serial_number });
            var pid = new List<int>() { first.id };
            //获取所有子级的数据
            while (true)
            {
                var data = location.GetList(f => pid.Contains(f.parentid) && f.status == (int)RowState.Valid && f.projectid == ProjectId).ToList();
                if (data.Count() == 0)
                {
                    break;
                }
                pid = data.Select(f => f.id).ToList();

                var tmpDic = data.Select(f => new Node { id = f.id, pid = f.parentid, name = f.realname, serial_number = f.serial_number }).ToList();
                nodes.AddRange(tmpDic);
            }

            var title = new List<string>();
            var range = locationtype.GetList(f => f.status == (int)RowState.Valid && f.projectid == ProjectId).OrderBy(f => f.parentid).Select(f => f.name).ToList();
            title.AddRange(range);
            //整理数据
            var result = GetLocationInfo(title, nodes);

            return new ObjectResult(result);
        }

        private List<List<ResponseKVQRCode>> GetLocationInfo(List<string> titles, List<Node> nodes)
        {
            var result = new List<List<ResponseKVQRCode>>();
            var tmp = new List<string>();

            foreach (var item in nodes)
            {
                int count = 1;
                tmp = new List<string>();
                tmp.Add(item.name);
                tmp.Add(item.serial_number);
                var pid = item.pid;
                var entity = location.Get(f => f.status == (int)RowState.Valid && f.projectid == ProjectId && f.id == pid);
                var storageLocation = location.Get(f => f.status == (int)RowState.Valid && f.projectid == ProjectId && f.id == item.id);
                var storageData = storage.Get(f => f.status == (int)RowState.Valid && f.projectid == ProjectId && f.id == storageLocation.storageid);
                if (entity != null)
                {
                    while (pid != 0)
                    {
                        try
                        {
                            pid = entity.parentid;
                            tmp.Insert(0, entity.serial_number);
                            tmp.Insert(0, entity.realname);
                            count++;

                            //避免脏数据影响
                            if (count > 5)
                                break;
                        }
                        catch (Exception)
                        {
                        }
                        entity = location.Get(f => f.status == (int)RowState.Valid && f.projectid == ProjectId && f.id == pid);
                        if (entity == null)
                        {
                            break;
                        }
                    }
                }
                //add storagename
                var data = Arrange(titles, tmp);
                var tmpStorage = new ResponseKVQRCode() { k = "仓库", v = storageData.name, sn = storageData.serial_number };
                data.Insert(0, tmpStorage);
                result.Add(data);
            }
            return result;
        }
        #endregion

        /// <summary>
        /// 按照title-value整理
        /// </summary>
        /// <param name="titles"></param>
        /// <param name="tmp"></param>
        private List<ResponseKVQRCode> Arrange(List<string> titles, List<string> tmp)
        {
            var result = new List<ResponseKVQRCode>();
            if (tmp.Count > titles.Count)
            {
                //配置数量大于类型数量
            }
            for (int i = 0; i < tmp.Count / 2; i++)
            {
                var tmpDic = new ResponseKVQRCode() { k = titles[i], v = tmp[i * 2], sn = tmp[i * 2 + 1] };
                result.Add(tmpDic);
            }
            return result;
        }

        class Node
        {
            public int id;
            public int pid;
            public string name;
            public string serial_number;
        }
    }
}