using CZFW.CMS.Admin;
using CZFW.Core;
using CZFW.Framework.Model.ViewModel;
using CZFW.Framework.Tools;
using CZFW.MDB;
using CZFW.MDB.Interface;
using CZFW.MDB.Util;
using Microsoft.AspNetCore.Mvc;
using MongoDB.Bson;
using Newtonsoft.Json.Linq;
using System.Collections.Generic;
using System.IO;

namespace CZFW.CMS.Admin.Controllers
{
    public class PageController : AdminControllerBase
    {
        ISchemaRepository _schemaLogic;
        IPage _pageLogic;
        IMongoRepository _repository;
        ICMSCategory _categoryRepository;
        public PageController(ISchemaRepository schemaLogic, IPage page, IMongoRepository repository, ICMSCategory category)
        {
            _repository = repository;
            _categoryRepository = category;
            _pageLogic = page;
            _schemaLogic = schemaLogic;
        }
        public IActionResult List(string id = null, string pageName = null, string query = "{}", string type = "backend.table", string projection = "{}", int pageIndex = 1, int pageSize = 20, string sort = "{}")
        {
            var data = new BsonArray();
            if (string.IsNullOrWhiteSpace(pageName))
                data = _pageLogic.GetList(Site.SiteName, id, type, query, projection, pageIndex, pageSize, sort);
            else
            {
                pageName = $"{Site.TplName}_{pageName}";
                data = _pageLogic.GetListByName(Site.SiteName, pageName, type, query, projection, pageIndex, pageSize, sort);
            }
            var json = data.CZToJson();
            return Content(json, "application/json");
        }

        public IActionResult GetHeader(string key, string type = "backend.table")
        {
            var data = _schemaLogic.GetHeader(key, type, out string name);
            var json = data.CZToJson();
            return Content(json, "application/json");
        }

        public ResultModel GetCount(string pageName, string query = "{}")
        {
            if (!pageName.Contains(Site.TplName))
                pageName = $"{Site.TplName}_{pageName}";
            _repository.SetCurrentTable(pageName);
            var qry = JObject.Parse(query);
            if (!qry.ContainsKey(Constants.SITE_NAME_FIELD))
                qry[Constants.SITE_NAME_FIELD] = Site.SiteName;
            else
                qry.Add(Constants.SITE_NAME_FIELD, Site.SiteName);
            query = qry.ToString();
            var count = _repository.GetCount(query);
            var res = new ResultModel { Success = true, Data = count };
            return res;
        }
        public IActionResult Get(string pageId, string dataId, string projection = null, string type = "backend.view")
        {
            var header = _schemaLogic.GetHeader(pageId, type, out string name);
            var json = header.CZToJson();
            if (string.IsNullOrWhiteSpace(projection))
            {
                projection = json;
            }
            _repository.SetCurrentTable(name);
            var res = _repository.Get(dataId, projection);
            var jsonRes = res.CZToJson();
            return Content(jsonRes, "application/json");
        }

        public IActionResult GetOne(string id = null, string pageName = null, string query = "{}", string type = "", string projection = "{}", string sort = "{}")
        {
            var data = new BsonArray();
            if (string.IsNullOrWhiteSpace(pageName))
                data = _pageLogic.GetList(Site.SiteName, id, type, query, projection, 1, 1, sort);
            else
            {
                pageName = $"{Site.TplName}_{pageName}";
                data = _pageLogic.GetListByName(Site.SiteName, pageName, type, query, projection, 1, 1, sort);
            }
            var json = "{}";
            if (data != null)
                if (data.Count > 0)
                    json = data[0].AsBsonDocument.CZToJson();
            return Content(json, "application/json");
        }


        public ResultModel Create(string pageId, [FromBody]string objJson)
        {
            var name = _schemaLogic.GetNameById(pageId);
            var jobj = JObject.Parse(objJson);
            if (jobj.ContainsKey(Constants.SITE_NAME_FIELD))
                jobj[Constants.SITE_NAME_FIELD] = Site.SiteName;
            else
                jobj.Add(Constants.SITE_NAME_FIELD, Site.SiteName);
            if (jobj.ContainsKey(Constants.SORT_ORDER_FIELD))
            {
                if (jobj[Constants.SORT_ORDER_FIELD] == null)
                    jobj[Constants.SORT_ORDER_FIELD] = AutoInc.GetNext(Site.SiteName, name, Site.TplName);
                else if (!int.TryParse(jobj[Constants.SORT_ORDER_FIELD].ToString(), out int sort))
                {
                    jobj[Constants.SORT_ORDER_FIELD] = AutoInc.GetNext(Site.SiteName, name, Site.TplName);
                }
            }
            objJson = jobj.ToString();
            _repository.SetCurrentTable(name);
            var res = _repository.Insert(objJson);
            return res;
        }

        public ResultModel Replace(string pageId, string dataId, [FromBody]string objJson)
        {
            var name = _schemaLogic.GetNameById(pageId);
            _repository.SetCurrentTable(name);
            var jobj = JObject.Parse(objJson);
            if (jobj.ContainsKey(Constants.SITE_NAME_FIELD))
                jobj[Constants.SITE_NAME_FIELD] = Site.SiteName;
            else
                jobj.Add(Constants.SITE_NAME_FIELD, Site.SiteName);
            objJson = jobj.ToString();
            var res = _repository.Replace(dataId, objJson);
            return res;
        }

        public ResultModel Remove(string pageId, string dataId)
        {
            var name = _schemaLogic.GetNameById(pageId);
            _repository.SetCurrentTable(name);
            var res = _repository.Remove(dataId);
            return res;
        }

        public ResultModel SyncCate()
        {
            var res = _categoryRepository.SyncTplCategorySource(Site.TplName, Site.SiteName);
            return res;
        }



        /// <summary>
        /// 导出Excel
        /// </summary>
        /// <param name="pageName">页面名称</param>
        /// <param name="data">标题key/value对象</param>
        /// <param name="query">查询条件</param>
        /// <param name="projection">查询列</param>
        /// <param name="pageIndex">页码</param>
        /// <param name="pageSize">每页条数</param>
        /// <param name="sort">排序条件</param>
        /// <returns>文件二进制流</returns>
        public ResultModel Export(string pageName, [FromBody]JObject data, string query = "{}", string projection = "{}", int pageIndex = 1, int pageSize = 20, string sort = "{}")
        {
            // 设置页面名称
            if (!pageName.Contains(Site.TplName))
                pageName = $"{Site.TplName}_{pageName}";
            _repository.SetCurrentTable(pageName);

            var titleList = data.Value<JArray>("data");
            var titleKeys = new List<string>();
            var titleValues = new List<string>();
            foreach (var item in titleList)
            {
                titleKeys.Add(item.Value<string>("key"));
                titleValues.Add(item.Value<string>("value"));
            }

            var list = _repository.GetList(query, projection, pageIndex, pageSize, sort);
            var dataList = new List<BsonDocument>();
            foreach (var item in list)
            {
                dataList.Add(item.AsBsonDocument);
            }

            var res = NPOIHelper.OutputExcel(dataList, titleKeys, titleValues);
            var fileName = Utility.GetUnixTimeTick().ToString() + ".xlsx";
            var filePathRoot = ConfigHelper.GetValue<string>("ResourcePathRoot");
            var destPath = Path.Combine(filePathRoot, Site.SiteName, "export", fileName);
            using (FileStream fs = new FileStream(destPath, FileMode.OpenOrCreate, FileAccess.ReadWrite))
            {
                fs.Write(res, 0, res.Length);
            }
            return Result(data: $"/{Constants.RESOURCE_FILE_URL_PREFIX}/{Site.SiteName}/export/{fileName}");
        }
    }
}