using CloudBuilder.Core.DatabaseAccessor;
using CloudBuilder.Core.DatabaseAccessor.Entity;
using CloudBuilder.Core.Extensions;
using CloudBuilder.Core.Policy;
using CloudBuilder.Core.Report;
using CloudBuilder.Core.Service;
using CloudBuilder.Security.Data;
using CloudBuilder.Security.Entity;
using CloudBuilder.Security.Policy;
using CloudBuilder.Security.SearchCriteria;
using CloudBuilder.Security.Utility;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Security.Permissions;
namespace CloudBuilder.Security.Service
{
    public class SecurityMasterService : ISecurityMasterService
    {
        private readonly IApplicationService service;

        private IRepository<SecurityMasterEntity> repository;
        public SecurityMasterService(IApplicationService service)
        {
            this.service = service;
            repository = service.GetRepository<IRepository<SecurityMasterEntity>>();
        }

        [PermissionOperate(name: SecurityPermissionPolicy.SecurityMaster, operate: Operate.Find)]
        public SecurityMasterEntity FindByKey(SecurityMasterEntityKey key)
        {
            return repository.DetachedEntities.Where(x => x.MasterCategory == key.MasterCategory
            && x.MasterSubcategory == key.MasterSubcategory
            && x.MasterCodeItem == key.MasterCodeItem
           ).FirstOrDefault()!;
        }

        [AllowAnonymous]
        [HttpGet]
        public SecurityMasterEntity[] FindAll()
        {
            return repository.DetachedEntities.ToArray();
        }


        [PermissionOperate(name: SecurityPermissionPolicy.SecurityMaster, operate: Operate.Find)]
        public SecurityMasterResultData FindBySearchCriteria(SecurityMasterSearchCriteria criteria)
        {
            SecurityMasterResultData data = new SecurityMasterResultData();
            SecurityMasterEntity[] list = null;

            int count = 0;

            string sqlWhere = null;

            if (criteria.Filter != null && criteria.Filter.Length > 0)
            {
                sqlWhere = SearchFilter.ComposeWhereClause(criteria.Filter);
            }

            SecurityMasterEntity entity = SecurityMasterEntity.GetInstance();
            string sql = entity.GetSelectTopFrom(criteria.limit, criteria.page, criteria.orderby.StringToDbField(), criteria.orderbytag, sqlWhere);

            string err = null;
            try
            {
                list = repository.FromSql(sql).ToArray();
            }
            catch (System.Exception ex)
            {
                err = ex.Message;
            }


            if (list != null && list.Length > 0)
            {
                sql = entity.GetSelectCountFrom(sqlWhere);
                count = (int)repository.ExecuteScalar(sql);
            }

            data.Limit = criteria.limit;
            data.Page = criteria.page;
            data.Datas = list;
            data.Total = count;
            //data.Sql = sql;
            data.ErrorMessage = err;
            return data;
        }

        [PermissionOperate(name: SecurityPermissionPolicy.SecurityMaster, operate: Operate.Print)]
        public dynamic PrintBySearchCriteria(SecurityMasterSearchCriteria criteria)
        {
            string sqlWhere = string.Empty;
            List<TemplateHeader> headers = new List<TemplateHeader>();

            Dictionary<string, Dictionary<string, object>> mappings = new Dictionary<string, Dictionary<string, object>>();
            Dictionary<string, object> validDic = new Dictionary<string, object>();
            foreach (string v in YesNoPolicy.GetInstance().GetValues())
            {
                validDic.Add(v, YesNoPolicy.GetInstance().ComposeMessage(v, service.Locale));
            }
            mappings.Add(SecurityMasterEntity.VALID_INDC, validDic);

            List<string> searCriteria = criteria.PackSearchCriteriaDisplay(ref headers, ref sqlWhere, mappings);

            SecurityMasterEntity entity = SecurityMasterEntity.GetInstance();
            string sql = entity.GetSelectFrom() + " where 1=1 " + sqlWhere;

            SecurityMasterEntity[] list = repository.FromSql(sql).ToArray();

            return new DataToExcelHelper<SecurityMasterEntity>(service).ToExcel(criteria.ReportName, criteria.ReportName, searCriteria, headers.ToArray(), list, mappings);

        }

        [PermissionOperate(name: SecurityPermissionPolicy.SecurityMaster, operate: Operate.Insert)]
        [UnitOfWork]
        public SecurityMasterEntity Insert(SecurityMasterEntity data)
        {
            SecurityMasterEntity securityMaster = repository.DetachedEntities.Where(x => x.MasterCategory == data.MasterCategory &&
            x.MasterSubcategory == data.MasterSubcategory && x.MasterCodeItem == data.MasterCodeItem).FirstOrDefault()!;
            if (securityMaster != null)
            {
                throw new ValidatedException("记录已存在.");
            }

            ValidateHelper.Validate(service, data, SecurityMasterEntity.DB_NAME_SECURITY_MASTER);

            securityMaster = new SecurityMasterEntity();

            ObjectCopyHelper.Copy(data, securityMaster);

            securityMaster.ValidIndc = YesNoPolicy.YES;
            repository.InsertNow(securityMaster);

            return FindByKey(new SecurityMasterEntityKey { MasterCategory = data.MasterCategory, MasterCodeItem = data.MasterCodeItem, MasterSubcategory = data.MasterSubcategory });

        }

        [PermissionOperate(name: SecurityPermissionPolicy.SecurityMaster, operate: Operate.Update)]
        [UnitOfWork]
        public SecurityMasterEntity Update(SecurityMasterEntity data)
        {
            SecurityMasterEntity securityMaster = repository.DetachedEntities.Where(x => x.MasterCategory == data.MasterCategory &&
       x.MasterSubcategory == data.MasterSubcategory && x.MasterCodeItem == data.MasterCodeItem).FirstOrDefault()!;
            if (securityMaster == null)
            {
                throw new ValidatedException("记录不存在.");
            }

            ValidateHelper.Validate(service, data, SecurityMasterEntity.DB_NAME_SECURITY_MASTER);
            ObjectCopyHelper.Copy(data, securityMaster);

            repository.UpdateNow(securityMaster);

            return FindByKey(new SecurityMasterEntityKey { MasterCategory = data.MasterCategory, MasterCodeItem = data.MasterCodeItem, MasterSubcategory = data.MasterSubcategory });
        }


        [PermissionOperate(name: SecurityPermissionPolicy.SecurityMaster, operate: Operate.Delete)]
        public void Delete(SecurityMasterEntityKey key)
        {
            SecurityMasterEntity ent = repository.DetachedEntities.Where(x => x.MasterCategory == key.MasterCategory
              && x.MasterSubcategory == key.MasterSubcategory
              && x.MasterCodeItem == key.MasterCodeItem
             ).FirstOrDefault()!;
            if (ent != null) { repository.DeleteNow(ent); }
        }


        [PermissionOperate(name: SecurityPermissionPolicy.SecurityMaster, operate: Operate.Delete)]
        public void Deletes(SecurityMasterEntity[] datas)
        {
            if (datas == null || datas.Length == 0) return;
            repository.DeleteNow(datas);
        }

    }
}
