using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Authentication;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using System.Security.Claims;
using System.Linq.Expressions;
using System.IO;

using System.Collections;
using Newtonsoft;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Converters;


using XHD.Core.IServices;
using XHD.Core.IRepository;
using XHD.Core.Common;
using XHD.Core.Models;

using XHD.Core.View.Configs;

using NPOI;
using NPOI.OpenXml4Net;
using NPOI.OpenXmlFormats;
using NPOI.XWPF.UserModel;

using NPOI.SS;
using NPOI.SS.UserModel;
using NPOI.SS.Util;
using NPOI.HSSF.UserModel;
using NPOI.HSSF.Util;
using NPOI.SS.Formula.Functions;

namespace XHD.Core.View.Controllers
{
    [Authorize]
    public class CustomerController : Controller
    {
        private readonly ILogger<CustomerController> _logger;
        private readonly ICRM_CustomerService _service;
        private readonly ICRM_ContactService _Contactservice;
        private readonly ICRM_followService _followservice;
        private readonly ISale_orderService _orderservice;
        private readonly ISale_contractService _Contractservice;
        private readonly ISys_ParamService _Paramservice;
        private readonly ISys_Param_ProvincesService _Provincesservice;
        private readonly ISys_logService _LogService;
        private readonly IDBAuthService _dBAuthService;
        private readonly ISys_infoService _infoservice;

        private readonly SysLogExt<CRM_Customer> logext = new SysLogExt<CRM_Customer>();
        private readonly NPOIExt _npoi;

        public CustomerController(
            ILogger<CustomerController> logger,
            ICRM_CustomerService service,
            ICRM_ContactService Contactservice,
            ICRM_followService followservice,
            ISale_orderService orderservice,
            ISale_contractService Contractservice,
            ISys_ParamService Paramservice,
            ISys_Param_ProvincesService Provincesservice,
            ISys_logService LogService,
            IDBAuthService dBAuthService,
             ISys_infoService infoservice,
             NPOIExt npoi
            )
        {
            _service = service;
            _logger = logger;
            _Contactservice = Contactservice;
            _orderservice = orderservice;
            _Contractservice = Contractservice;
            _followservice = followservice;
            _Paramservice = Paramservice;
            _Provincesservice = Provincesservice;
            _LogService = LogService;
            _infoservice = infoservice;

            _dBAuthService = dBAuthService;
            _npoi = npoi;
        }

        public IActionResult Info()
        {
            return View();
        }

        public IActionResult Index()
        {
            Expression<Func<Sys_Param, bool>> expparam = a => 1 == 1;
            var parasmdata = _Paramservice.Grid(expparam);

            Dictionary<string, string> cus_industry = new Dictionary<string, string>();
            Dictionary<string, string> cus_type = new Dictionary<string, string>();
            Dictionary<string, string> cus_level = new Dictionary<string, string>();
            Dictionary<string, string> cus_source = new Dictionary<string, string>();
            Dictionary<string, string> Province = new Dictionary<string, string>();

            if (parasmdata.count > 0)
            {
                var industrylist = parasmdata.data.Where(a => a.params_type == "cus_industry");

                foreach (var l in industrylist)
                {
                    cus_industry.Add(l.id, l.params_name);
                }

                var typelist = parasmdata.data.Where(a => a.params_type == "cus_type");

                foreach (var l in typelist)
                {
                    cus_type.Add(l.id, l.params_name);
                }

                var levellist = parasmdata.data.Where(a => a.params_type == "cus_level");

                foreach (var l in levellist)
                {
                    cus_level.Add(l.id, l.params_name);
                }

                var sourcelist = parasmdata.data.Where(a => a.params_type == "cus_source");

                foreach (var l in sourcelist)
                {
                    cus_source.Add(l.id, l.params_name);
                }
            }

            Expression<Func<Sys_Param_Provinces, bool>> expprovinces = a => 1 == 1;
            var provincedata = _Provincesservice.Grid(expprovinces);

            if (provincedata.count > 0)
            {
                foreach (var l in provincedata.data)
                {
                    Province.Add(l.id, l.Provinces);
                }
            }

            ViewData["cus_industry"] = cus_industry;
            ViewData["cus_type"] = cus_type;
            ViewData["cus_level"] = cus_level;
            ViewData["cus_source"] = cus_source;
            ViewData["Province"] = Province;

            return View();
        }

        public IActionResult Add()
        {
            return View();
        }

        public IActionResult map()
        {
            Expression<Func<Sys_info, bool>> exp = a => a.sys_key == "map_baidu_key";

            var infodata = _infoservice.Grid(exp);

            ViewData["map_key"] = infodata.data[0].sys_value;

            return View();
        }

        public IActionResult mapmark()
        {
            Expression<Func<Sys_info, bool>> exp = a => a.sys_key == "map_baidu_key";

            var infodata = _infoservice.Grid(exp);

            ViewData["map_key"] = infodata.data[0].sys_value;

            return View();
        }

        public async Task<string> Grid(PageView<CRM_Customer> model)
        {
            Expression<Func<CRM_Customer, bool>> exp = a => 1 == 1;

            if (!string.IsNullOrWhiteSpace(Request.Query["cus_name"]))
            {
                exp = exp.And(a => a.cus_name.Contains(Request.Query["cus_name"]));
            }

            if (!string.IsNullOrWhiteSpace(Request.Query["keyword"]))
            {
                exp = exp.And(a => a.cus_name.Contains(Request.Query["keyword"]));
            }

            if (!string.IsNullOrWhiteSpace(Request.Query["id"]))
            {
                exp = exp.And(a => a.id == Request.Query["id"]);
            }

            if (!string.IsNullOrWhiteSpace(Request.Query["cus_tel"]))
            {
                exp = exp.And(a => a.cus_tel.Contains(Request.Query["cus_tel"]));
            }

            if (!string.IsNullOrWhiteSpace(Request.Query["cus_industry_id"]))
            {
                exp = exp.And(a => a.cus_industry_id == Request.Query["cus_industry_id"]);
            }

            if (!string.IsNullOrWhiteSpace(Request.Query["cus_type_id"]))
            {
                exp = exp.And(a => a.cus_type_id == Request.Query["cus_type_id"]);
            }

            if (!string.IsNullOrWhiteSpace(Request.Query["cus_level_id"]))
            {
                exp = exp.And(a => a.cus_level_id == Request.Query["cus_level_id"]);
            }

            if (!string.IsNullOrWhiteSpace(Request.Query["cus_source_id"]))
            {
                exp = exp.And(a => a.cus_source_id == Request.Query["cus_source_id"]);
            }

            if (!string.IsNullOrWhiteSpace(Request.Query["Provinces_id"]))
            {
                exp = exp.And(a => a.Provinces_id == Request.Query["Provinces_id"]);
            }

            if (!string.IsNullOrWhiteSpace(Request.Query["City_id"]))
            {
                exp = exp.And(a => a.City_id == Request.Query["City_id"]);
            }


            if (!string.IsNullOrWhiteSpace(Request.Query["emp_id"]))
            {
                exp = exp.And(a => a.emp_id == Request.Query["emp_id"]);
            }

           

            if (PageValidate.IsDateTime(Request.Query["date1"]))
            {
                exp = exp.And(a => a.create_time >= DateTime.Parse(Request.Query["date1"]));
            }

            if (PageValidate.IsDateTime(Request.Query["date2"]))
            {
                exp = exp.And(a => a.create_time <= DateTime.Parse(Request.Query["date2"]));
            }

            if (PageValidate.IsNumber(Request.Query["isPrivate"]))
            {

                if (Request.Query["isPrivate"] == "1")
                {
                    exp = exp.And(a => a.isPrivate == 1);
                }
                else
                {
                    exp = exp.And(a => a.isPrivate == 0);

                    //权限
                    var roledata = await _dBAuthService.GetDataAuth(User.FindFirst(ClaimTypes.Sid).Value);

                    if (roledata.authtype != 4)
                    {
                        exp = exp.And(a => roledata.empList.Contains(a.emp_id) );
                    }

                }
            }
            else
            {
                //权限

                var roledata = await _dBAuthService.GetDataAuth(User.FindFirst(ClaimTypes.Sid).Value);

                if (roledata.authtype != 4)
                {
                    exp = exp.And(a => roledata.empList.Contains(a.emp_id) || a.isPrivate == 1);

                    //exp.Or(a => a.isPrivate == 1);
                }
            }
                

            var result = await _service.GridAsync(exp, model.Page, model.Limit, "a.create_time desc");

            return result.ToString();
        }

        public async Task<string> GetPoint()
        {
            Expression<Func<CRM_Customer, bool>> exp = a => 1 == 1;

            //权限

            var roledata = await _dBAuthService.GetDataAuth(User.FindFirst(ClaimTypes.Sid).Value);

            if (roledata.authtype != 4)
            {
                exp = exp.And(a => roledata.empList.Contains(a.emp_id));
            }

            var result = await _service.GridAsync(exp);

            JArray arr = new JArray();
            foreach (var data in result.data)
            {
                if (data.x > 0 && data.y > 0)
                {
                    JObject obj = new JObject();

                    obj.Add("cus_name", data.cus_name);
                    obj.Add("cus_add", data.cus_add);
                    obj.Add("cus_tel", data.cus_tel);

                    obj.Add("x", data.x);
                    obj.Add("y", data.y);


                    arr.Add(obj);
                }
            }

            return XHDResult.Success(arr).ToString();
        }

        public async Task<string> Save(CRM_Customer model)
        {
            var result = 0;

            if (string.IsNullOrWhiteSpace(model.id))
            {
                model.id = UUIDNext.Uuid.NewSequential().ToString();

                var ids = model.id.Split("-");
                var sn = $"{DateTime.Now.ToString("yyyyMMddHHmmss")}{ids[2]}";

                model.Serialnumber = sn;
                model.create_id = User.FindFirst(ClaimTypes.Sid).Value;
                model.create_time = DateTime.Now;
                model.isDelete = 0;

                //权限
                var authbtn = await _dBAuthService.GetAuth(User.FindFirst(ClaimTypes.Sid).Value, "CRM_Customer|add");

                if (!authbtn)
                {
                    return XHDResult.Error("无权限！").ToString();

                }
                result = await _service.AddAsync(model);
            }
            else
            {
                //权限
                var authbtn = await _dBAuthService.GetAuth(User.FindFirst(ClaimTypes.Sid).Value, "CRM_Customer|edit");

                if (!authbtn)
                {
                    return XHDResult.Error("无权限！").ToString();
                }
                //日志
                Expression<Func<CRM_Customer, bool>> exp = a => a.id == model.id;
                var customerdata = await _service.GridAsync(exp, 1, 1);

                if (customerdata.count == 0)
                {
                    return XHDResult.Error("找不到数据！").ToString();
                }

                //更新
                result = await _service.UpdateAsync(model);

                //对比实体差别

                var content = logext.LogContent(customerdata.data[0], model);

                if (content.Length > 0)
                {
                    //添加修改日志
                    Sys_log logmodels = new Sys_log();

                    logmodels.id = System.Guid.NewGuid().ToString();
                    logmodels.EventType = "[客户]修改";
                    logmodels.EventID = model.id;
                    logmodels.EventTitle = model.cus_name;
                    logmodels.UserID = User.FindFirst(ClaimTypes.Sid).Value;
                    logmodels.UserName = User.FindFirst(ClaimTypes.Name).Value;
                    logmodels.IPStreet = HttpContext.Connection.RemoteIpAddress.ToString();
                    logmodels.EventDate = DateTime.Now;
                    logmodels.Log_Content = content;

                    //
                    await _LogService.UpdateLog(logmodels);
                }


            }

            if (result == 0)
            {
                return XHDResult.Error("操作失败，系统错误！").ToString();
            }

            HttpContext.Session.SetString("newCustomerID", model.id);

            return XHDResult.Success().ToString();
        }

        public async Task<string> Excute()
        {
            var cus_name = Request.Form["cus_name"].ToString();

            Expression<Func<CRM_Customer, bool>> exp = a => a.cus_name == cus_name && a.id != Request.Form["id"];

            var data = await _service.GridAsync(exp);

            if (data.count > 0)
            {
                return XHDResult.Success().ToString();
            }

            return XHDResult.Error("").ToString();
        }

        public async Task<string> Delete(string id)
        {
            //判断是否有联系人
            Expression<Func<CRM_Contact, bool>> expcontact = a => a.customer_id == id;
            var contactlist = await _Contactservice.GridAsync(expcontact, 1, 1);

            if (contactlist.count > 0)
            {
                return XHDResult.Error("此客户下含有联系人，不能删除！").ToString();
            }

            //判断是否有跟进
            Expression<Func<CRM_follow, bool>> expfollow = a => a.customer_id == id;
            var followlist = await _followservice.GridAsync(expfollow, 1, 1);

            if (followlist.count > 0)
            {
                return XHDResult.Error("此客户下含有跟进，不能删除！").ToString();
            }

            //判断是否有订单
            Expression<Func<Sale_order, bool>> exporder = a => a.customer_id == id;
            var orderlist = await _orderservice.GridAsync(exporder, 1, 1);

            if (orderlist.count > 0)
            {
                return XHDResult.Error("此客户下含有订单，不能删除！").ToString();
            }

            //判断是否有合同
            Expression<Func<Sale_contract, bool>> expcontract = a => a.customer_id == id;
            var contractlist = await _Contractservice.GridAsync(expcontract, 1, 1);

            if (contractlist.count > 0)
            {
                return XHDResult.Error("此客户下含有合同，不能删除！").ToString();
            }

            var result = 0;

            //权限
            var authbtn = await _dBAuthService.GetAuth(User.FindFirst(ClaimTypes.Sid).Value, "CRM_Customer|del");

            if (authbtn)
            {
                //判断是否有数据
                Expression<Func<CRM_Customer, bool>> exp = a => a.id == id;
                var checkdata = await _service.GridAsync(exp, 1, 1);

                if (checkdata.count == 0)
                {
                    return XHDResult.Error("找不到此数据！").ToString();
                }

                result = await _service.DeleteAsync(id);

                //日志                

                //先存储删除的实体记录，用日志形式
                logext.getEntityText(checkdata.data[0]);

                //记录日志
                Sys_log logmodels = new Sys_log();

                logmodels.id = System.Guid.NewGuid().ToString();
                logmodels.EventType = "[客户]删除";
                logmodels.EventID = id;
                logmodels.EventTitle = checkdata.data[0].cus_name;
                logmodels.UserID = User.FindFirst(ClaimTypes.Sid).Value;
                logmodels.UserName = User.FindFirst(ClaimTypes.Name).Value;
                logmodels.IPStreet = HttpContext.Connection.RemoteIpAddress.ToString();
                logmodels.EventDate = DateTime.Now;
                //logmodels.Log_Content = content;


                await _LogService.DeleteLog(logmodels);
            }
            else
            {
                return XHDResult.Error("无权限！").ToString();
            }

            //var result = await _service.Delete(id);

            if (result == 0)
            {
                return XHDResult.Error("删除失败！").ToString();
            }

            return XHDResult.Success().ToString();
        }

        public async Task<ActionResult> Export()
        {
            //先获取数据
            Expression<Func<CRM_Customer, bool>> exp = a => 1 == 1;

            if (!string.IsNullOrWhiteSpace(Request.Query["cus_name"]))
            {
                exp = exp.And(a => a.cus_name.Contains(Request.Query["cus_name"]));
            }

            if (!string.IsNullOrWhiteSpace(Request.Query["keyword"]))
            {
                exp = exp.And(a => a.cus_name.Contains(Request.Query["keyword"]));
            }

            if (!string.IsNullOrWhiteSpace(Request.Query["id"]))
            {
                exp = exp.And(a => a.id == Request.Query["id"]);
            }

            if (!string.IsNullOrWhiteSpace(Request.Query["cus_tel"]))
            {
                exp = exp.And(a => a.cus_tel.Contains(Request.Query["cus_tel"]));
            }

            if (!string.IsNullOrWhiteSpace(Request.Query["cus_industry_id"]))
            {
                exp = exp.And(a => a.cus_industry_id == Request.Query["cus_industry_id"]);
            }

            if (!string.IsNullOrWhiteSpace(Request.Query["cus_type_id"]))
            {
                exp = exp.And(a => a.cus_type_id == Request.Query["cus_type_id"]);
            }

            if (!string.IsNullOrWhiteSpace(Request.Query["cus_level_id"]))
            {
                exp = exp.And(a => a.cus_level_id == Request.Query["cus_level_id"]);
            }

            if (!string.IsNullOrWhiteSpace(Request.Query["cus_source_id"]))
            {
                exp = exp.And(a => a.cus_source_id == Request.Query["cus_source_id"]);
            }

            if (!string.IsNullOrWhiteSpace(Request.Query["Provinces_id"]))
            {
                exp = exp.And(a => a.Provinces_id == Request.Query["Provinces_id"]);
            }

            if (!string.IsNullOrWhiteSpace(Request.Query["City_id"]))
            {
                exp = exp.And(a => a.City_id == Request.Query["City_id"]);
            }


            if (!string.IsNullOrWhiteSpace(Request.Query["emp_id"]))
            {
                exp = exp.And(a => a.emp_id == Request.Query["emp_id"]);
            }

            if (PageValidate.IsNumber(Request.Query["isPrivate"]))
            {
                exp = exp.And(a => a.isPrivate == int.Parse(Request.Query["isPrivate"]));
            }

            if (PageValidate.IsDateTime(Request.Query["date1"]))
            {
                exp = exp.And(a => a.create_time >= DateTime.Parse(Request.Query["date1"]));
            }

            if (PageValidate.IsDateTime(Request.Query["date2"]))
            {
                exp = exp.And(a => a.create_time <= DateTime.Parse(Request.Query["date2"]));
            }

            //权限

            var roledata = await _dBAuthService.GetDataAuth(User.FindFirst(ClaimTypes.Sid).Value);

            if (roledata.authtype != 4)
            {
                exp = exp.And(a => roledata.empList.Contains(a.emp_id));
            }

            var result = await _service.GridAsync(exp, "a.create_time desc");



            string sheet_name = "客户列表";
            string title_name = "客户列表";

            var sheet_title = new string[] {
                "编号","客户名字","地址","电话","传真",
                "网址","行业","省份","城市","类别",
                "级别","来源","描述","备注","归属",
                "公私","最后跟进","坐标","创建时间"
            };

            JArray arr = new JArray();

            foreach (var customer in result.data)
            {
                var isprivate = "私客";
                if (customer.isPrivate == 1)
                {
                    isprivate = "公客";
                }

                var cus_industry = "";
                if (customer.cus_industry != null)
                {
                    cus_industry = customer.cus_industry.params_name;
                }

                var cus_level = "";
                if (customer.cus_level != null)
                {
                    cus_level = customer.cus_level.params_name;
                }

                var cus_type = "";
                if (customer.cus_type != null)
                {
                    cus_type = customer.cus_type.params_name;
                }

                var cus_source = "";
                if (customer.cus_source != null)
                {
                    cus_source = customer.cus_source.params_name;
                }

                var Provinces = "";
                if (customer.Provinces != null)
                {
                    Provinces = customer.Provinces.Provinces;
                }

                var City = "";
                if (customer.City != null)
                {
                    City = customer.City.City;
                }

                var Employee = "";
                if (customer.Employee != null)
                {
                    Employee = customer.Employee.name;
                }

                JObject obj = new JObject();

                obj.Add("Serialnumber", customer.Serialnumber);
                obj.Add("cus_name", customer.cus_name);
                obj.Add("cus_add", customer.cus_add);
                obj.Add("cus_tel", customer.cus_tel);
                obj.Add("cus_fax", customer.cus_fax);

                obj.Add("cus_website", customer.cus_website);
                obj.Add("cus_industry", cus_industry);
                obj.Add("Provinces", Provinces);
                obj.Add("City", City);
                obj.Add("cus_type", cus_type);

                obj.Add("cus_level", cus_level);
                obj.Add("cus_source", cus_source);
                obj.Add("DesCripe", customer.DesCripe);
                obj.Add("Remarks", customer.Remarks);
                obj.Add("Employee", Employee);

                obj.Add("isprivate", isprivate);
                obj.Add("lastfollow", customer.lastfollow);
                obj.Add("xy", customer.xy);
                obj.Add("create_time", customer.create_time);

                arr.Add(obj);
            }
            //表格
            HSSFWorkbook book = new HSSFWorkbook();

            _npoi.create_sheet(book, sheet_name, title_name, sheet_title, arr);

            MemoryStream memoryStream = new MemoryStream();
            book.Write(memoryStream);
            memoryStream.Seek(0, SeekOrigin.Begin);
            //byte[] buf = memoryStream.GetBuffer();
            //return buf;

            return File(memoryStream, "application/vnd.ms-excel", $"客户信息{DateTime.Now.ToString("yyyyMMddHH:mm:ss")}.xls");

        }


    }
}
