using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Logging;
using MadRunFabric.Common;
using PLCAutomationApi.IRepositories;
using MadRunFabric.Model.PLCAutomationApi;
using MongoDB.Driver;
using PLCAutomationApi.Repositories;

namespace PLCAutomationApi.Controllers
{
    
    [Produces("application/json")]
    [Route("api/[controller]")]
    public class PLCAddrInfoController : BaseController
    {

        private readonly ILogger<PLCAddrInfoController> _logger;
        private readonly IPLCAddrRepository _plc_addrRepository;
        private readonly IDistributedCache _cache;
        private readonly IPLC_IPManageRepository _ipmanageRepository;
        private readonly IPLC_AccessRecordsRepository _plc_recordsRepository;

        public PLCAddrInfoController(ILogger<PLCAddrInfoController> logger, IPLCAddrRepository plc_addrRepository,
            IDistributedCache cache, IPLC_IPManageRepository ipmanageRepository, IPLC_AccessRecordsRepository plc_recordsRepository)
        {
            _logger = logger;
            _plc_addrRepository = plc_addrRepository;
            _cache = cache;
            _ipmanageRepository = ipmanageRepository;
            _plc_recordsRepository = plc_recordsRepository;
        }

        public IActionResult Index()
        {
            return Success("plc读取测试");
            //return View();
        }


        /// <summary>
        /// 上传文件并导入数据库
        /// </summary>
        /// <returns></returns>
        [HttpPost("importexcel")]
        public async Task<IActionResult> ImportExcel(int headrow = 0)
        {
            //if (string.IsNullOrEmpty(taskid))
            //    return Error("任务id不能为空");

            Microsoft.AspNetCore.Http.IFormFile _upfile = Request.Form.Files[0];
            if (!_upfile.ContentType.Equals("application/vnd.ms-excel") && !_upfile.ContentType.Equals("application/x-xls") && !_upfile.ContentType.Equals("application/x-xlsx") && !_upfile.ContentType.Equals("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") && !_upfile.ContentType.Equals("application/octet-stream"))
                return Error($"请正确上传Excel文件：file.ContentType={_upfile.ContentType}");

            NPOIHelper npoi = new NPOIHelper();
            var dtExcel = npoi.ExcelToTable1(_upfile, headrow);
            int num = dtExcel.Rows.Count;
            var cols = dtExcel.Columns;
            int colnum = cols.Count;

            string dbkeys = "equipnum,addr,type,isdelete,note";// _configuration["upload:acotdbkeys"].ToString();
            string[] dbcols = dbkeys.Split(",");
            string errmsg = string.Empty;

            if (num > 0)
            {
                int index = 1;
                foreach (System.Data.DataRow dr in dtExcel.Rows)
                {
                    var model = new PLCAddr();

                    /*model.taskid = taskid;
                    //model.cusname = dr.cusname;
                    //model.phone = dr.phone;
                    //model.cusaddr = dr.cusaddr;
                    model.createtime = DateTime.Now.ToLocalTime();
                    model.deleteflag = 0;*/

                    var dbcolslist = dbcols.ToList();

                    Type t = model.GetType();
                    PropertyInfo[] PropertyList = t.GetProperties();

                    foreach (PropertyInfo item in PropertyList)
                    {
                        if (dbcolslist.Contains(item.Name))
                        {
                            object v = Convert.ChangeType(dr[dbcolslist.IndexOf(item.Name)].ToString(), item.PropertyType);
                            item.SetValue(model, v, null);
                        }
                    }

                    bool b = await _plc_addrRepository.Add(model);
                    if (!b)
                    {
                        if (!string.IsNullOrEmpty(errmsg))
                        {
                            errmsg = errmsg + "\r\n第" + index + "行导入失败！";
                        }
                        else
                        {
                            errmsg = "第" + index + "行导入失败！";
                        }
                    }
                    index++;
                }
            }
            else
            {
                return Error("文件中无数据");
            }

            if (!string.IsNullOrEmpty(errmsg))
            {
                //删除已导入的部分
                return Error(errmsg);
            }

            return Success("导入成功");
        }

        /// <summary>
        /// 从redis缓存中获取设备信息
        /// </summary>
        /// <param name="equipnum"></param>
        /// /// <param name="note"></param>
        /// <returns></returns>
        [HttpGet("getplcvalue")]
        public async Task<IActionResult> GetPLCValueAsync(string ipaddress, string macaddress,string equipnum = "",string note="")
        {
            #region 参数检查
            if (string.IsNullOrWhiteSpace(equipnum))
                return Error("设备编号是必需字段");
            #endregion

            #region 判断权限
            PLC_IPManage comodel = new PLC_IPManage();

            var list = new List<FilterDefinition<PLC_IPManage>>();
            var filterBuilder = Builders<PLC_IPManage>.Filter;
            list.Add(filterBuilder.Eq("ipaddress", ipaddress));
            list.Add(filterBuilder.Eq("macaddress", macaddress));
            var filter = Builders<PLC_IPManage>.Filter.And(list);
            var count = await _ipmanageRepository.CountAsync(filter);
            if (count > 0)
            {
                var dModel = await _ipmanageRepository.GetSingle(s => s.ipaddress.Equals(ipaddress) & s.macaddress == macaddress & s.deleteflag == 0, null);
                if (dModel.forbidread == 1)
                {
                    #region 记录接口访问信息
                    PLC_AccessRecords romodel = new PLC_AccessRecords();
                    romodel.ipaddress = ipaddress;
                    romodel.macaddress = macaddress;
                    romodel.createtime = DateTime.Now;
                    romodel.interfacename = "getplcvalue";
                    romodel.flag = 0;
                    bool b = await _plc_recordsRepository.Add(romodel);
                    #endregion
                    return Error("没有接口访问权限！");
                }
            }
            else
            {
                var model = new PLC_IPManage();
                model.ipaddress = ipaddress;
                model.macaddress = macaddress;
                model.createtime = DateTime.Now;
                model.forbidread = 0;
                model.forbidwrite = 0;
                model.deleteflag = 0;

                bool b = await _ipmanageRepository.Add(model);
            }
            #endregion

            #region 记录接口访问信息
            PLC_AccessRecords rmodel = new PLC_AccessRecords();
            rmodel.ipaddress = ipaddress;
            rmodel.macaddress = macaddress;
            rmodel.createtime = DateTime.Now;
            rmodel.interfacename = "getplcvalue";
            rmodel.flag = 1;
            bool r = await _plc_recordsRepository.Add(rmodel);
            #endregion

            string cvalue = "";
            #region 从Redis缓存中查询信息
            
            var locationStr = await _cache.GetStringAsync($"{equipnum}{note}");//($"{equipnum+note}")
            if (!string.IsNullOrWhiteSpace(locationStr))
            {
                cvalue = locationStr.ToObject<string>();
            }
            #endregion

            if (cvalue == "")
                return Error("获取数据失败");

            return Success("成功", cvalue);
        }

        //[Authorize]
        [HttpGet("getlistbypage")]
        public async Task<IActionResult> GetListsByPageAsync(string ipaddress, string stime, string etime, string macaddress, int pageindex = 1, int pagesize = 10)
        {
            try
            {
                //排序字段
                var sort = Builders<PLC_AccessRecords>.Sort.Descending("createtime");

                //根据条件查询集合
                var flist = new List<FilterDefinition<PLC_AccessRecords>>();
                flist.Add(Builders<PLC_AccessRecords>.Filter.Eq("deleteflag", 0));
                if (!string.IsNullOrWhiteSpace(ipaddress))
                    flist.Add(Builders<PLC_AccessRecords>.Filter.Where(s => s.ipaddress.Equals(ipaddress)));
                if (!string.IsNullOrWhiteSpace(macaddress))
                    flist.Add(Builders<PLC_AccessRecords>.Filter.Where(s => s.macaddress.Equals(macaddress)));
                if (!string.IsNullOrWhiteSpace(stime))
                {
                    DateTime dt2 = new DateTime();
                    if (DateTime.TryParse(stime.Trim(), out dt2))
                        flist.Add(Builders<PLC_AccessRecords>.Filter.Gt("createtime", stime + " 00:00:00"));
                }
                if (!string.IsNullOrWhiteSpace(etime))
                {
                    DateTime dt2 = new DateTime();
                    if (DateTime.TryParse(etime.Trim(), out dt2))
                        flist.Add(Builders<PLC_AccessRecords>.Filter.Lt("createtime", etime + " 23:59:59"));
                }
                var filter = Builders<PLC_AccessRecords>.Filter.And(flist);
                var list = await _plc_recordsRepository.GetByPage(filter, pageindex, pagesize, sort);
                var count = await _plc_recordsRepository.CountAsync(filter);
                var obj = new
                {
                    state = "success",
                    message = "根据条件获取分页数据成功",
                    rows = list,
                    total = count,
                };
                return Content(obj.ToJson());

            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "根据条件获取分页数据异常");
                return Error("根据条件获取分页数据异常");
            }
        }
    }
}