using ClosedXML.Excel;
using CloudBuilder.Core.DependencyInjection.Form;
using CloudBuilder.Core.Report;
using CloudBuilder.Core.Service;
using CloudBuilder.Gui;
using CloudBuilder.Gui.DependencyInjection;
using CloudBuilder.Request.Security;
using CloudBuilder.Security.Data;
using CloudBuilder.Security.Entity;
using CloudBuilder.Security.Linkup;
using CloudBuilder.Security.Policy;
using CloudBuilder.Security.SearchCriteria;
using DocumentFormat.OpenXml.Spreadsheet;
using Krypton.Toolkit;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;


namespace CloudBuilder.Security.Gui
{
    public partial class SecurityUserEnquiryPage : AbstractPage
    {
        private SecurityUserEntity[] securityUsers = null!;
        private SecurityUserSearchCriteria searchCriteria = null!;
        private BindingContextAttributeProvider provider;
        private SecurityUserRequest securityUserRequest;
        private SecurityMessagePolicy securityMessagePolicy;

        //初始化Page，注入容器内，不要在此做任何事情
        public SecurityUserEnquiryPage()
        {
            InitializeComponent();
        }

        /// <summary>
        /// 第一次加载时执行，只执行一次
        /// </summary>
        public override void FunctionLoaded()
        {
            HandleException(() => onFunctionLoaded());
        }

        private void onFunctionLoaded()
        {
            base.FunctionLoaded();
            //初始化容器-------------------------------------
            securityUserRequest = ServiceHelper.GetTypeService<SecurityUserRequest>();
            securityMessagePolicy = ServiceHelper.GetTypeService<SecurityMessagePolicy>()!;

            //界面初始化
            InitGui();
        }

        /// <summary>
        /// 每次从别的界面进入时执行，不包括下面的界面切换，发生在FunctionLoaded之后
        /// 这个是有参数传入，常用于查询界面进入到操作界面发生
        /// </summary>
        /// <param name="param"></param>
        public override void FunctionActivated(object param)
        {
            base.FunctionActivated(param);
            userNameTxt.Focus();
        }
        /// <summary>
        /// 当Page被选中时执行,用于Tab导航的切换，没有参数变化，跟FunctionActivated有区别
        /// </summary>
        public override void FunctionSelected()
        {
            this.ParentAbstractForm.AcceptButton = this.searchBut;
            if (!IsDialog)
                this.ParentAbstractForm.CancelButton = this.resetBut;
            else
                this.ParentAbstractForm.CancelButton = this.cancelBut;

            userNameTxt.Focus();
        }
        /// <summary>
        /// 控件的初始化
        /// </summary>
        private void InitGui()
        {
            //DataGridView初始化不要自动生成列，且允许重排列名操作
            dataGv.InitColumn(true, true);
            //绑定ComboBox数据源
            InitCombo();
            //设置userIsValidIndcCombo默认值
            userIsValidIndcCombo.SelectedValue = YesNoPolicy.YES;
            //初始化绑定设置
            InitBindingContext();
            //设置显示模式
            SetDisplayMode(true);

            InitGridViewPagination();
        }
        /// <summary>
        /// DataGridView分页控件初始化
        /// </summary>
        private void InitGridViewPagination()
        {
            searchCriteria = new SecurityUserSearchCriteria();
            gridViewPagination.SetLimit(searchCriteria.limit);
            gridViewPagination.OnPaginationChanged += Search;
            gridViewPagination.OnPrint += Print;
        }

        /// <summary>
        /// 打印当前查询结果
        /// </summary>
        private void Print()
        {
            //設置Value與description的映射，另一方式是dataValeOperation传入函数
            Dictionary<string, Dictionary<string, object>> mappings = new Dictionary<string, Dictionary<string, object>>();
            Dictionary<string, object> validDic = YesNoPolicy.GetInstance().GetDictionary();
            mappings.Add(SecurityUserEntity.USER_IS_VALID_INDC, validDic);
            //設置查詢條件
            List<string> searCriteria = new List<string>();
            if (!string.IsNullOrEmpty(userNameTxt.Text))
                searCriteria.Add(userNameLabel.Text + userNameTxt.Text);
            if (!string.IsNullOrEmpty(userIsValidIndcCombo.Text))
                searCriteria.Add(deleteLabel.Text + userIsValidIndcCombo.Text);
            //設置每列的格式
            TemplateHeader[] headers = dataGv.GetTemplateHeaders();
            headers.Where(x => x.BindingName == SecurityUserEntity.USER_IS_VALID_INDC).FirstOrDefault().CellTypeFormatName = SecurityUserEntity.USER_IS_VALID_INDC;
            //打印Excel
            new DataToExcelHelper<SecurityUserEntity>(null).PrintExcel(this.Parent.Text, this.Parent.Text, searCriteria, headers, securityUsers, mappings, null, CellTypeFormatOperation, null);
        }

        public void CellTypeFormatOperation(IXLWorksheet xLWorksheet, string functionName, object cellValue, int rowIndex, int ColIndex, SecurityUserEntity[] datas)
        {
            SecurityUserEntity entity = (SecurityUserEntity)cellValue;
            if (entity.UserIsValidIndc == YesNoPolicy.NO)
            {
                xLWorksheet.Range(rowIndex, ColIndex, rowIndex, ColIndex).Style.Fill.PatternType = XLFillPatternValues.Solid;
                xLWorksheet.Range(rowIndex, ColIndex, rowIndex, ColIndex).Style.Fill.SetBackgroundColor(XLColor.Red);
            }
        }

        private void InitCombo()
        {
            userIsValidIndcCombo.SetDataSource(YesNoPolicy.GetInstance().GetComposeMessages(), true);
        }

        /// <summary>
        /// 有特殊要求的UI控件初始化设置，使用guiOperateHelper管理
        /// </summary>
        private void InitBindingContext()
        {
            InitPermission();

            guiOperateHelper = new GuiOperateHelper();
        }

        private void InitPermission()
        {
            viewBut.Set(SecurityPermissionPolicy.SecurityUser, Operate.Find);
            createBut.Set(SecurityPermissionPolicy.SecurityUser, Operate.Insert);
            amendBut.Set(SecurityPermissionPolicy.SecurityUser, Operate.Update);
            deleteBut.Set(SecurityPermissionPolicy.SecurityUser, Operate.Delete);
        }

        private void SetDisplayMode(bool enable)
        {
            guiOperateHelper.EnableControls(true, this.searchPanel, this.bottomPanel);
            guiOperateHelper.EnableControls(false, dataGv);

            if (securityUsers != null)
                guiOperateHelper.EnableControls(enable, viewBut, amendBut, deleteBut);
            else
                guiOperateHelper.EnableControls(false, viewBut, amendBut, deleteBut);

            //如果是弹出的窗口，不显示
            createBut.Visible = !IsDialog;
            dialogPanel.Visible = IsDialog;
            operationPanel.Visible = !IsDialog;

            this.userNameTxt.Focus();
        }

        private void searchBut_Click(object sender, EventArgs e)
        {
            HandleException(() => Search());
        }

        /// <summary>
        /// 与Web同步写法
        /// </summary>
        /// <returns></returns>
        private SecurityUserSearchCriteria PackSearchCriteria()
        {
            searchCriteria = new SecurityUserSearchCriteria();
            searchCriteria.limit = gridViewPagination.Limit;
            searchCriteria.page = gridViewPagination.CurrentPage;

            List<SearchFilter> filters = new List<SearchFilter>();

            SearchFilter filter = new SearchFilter();
            filter.Column = SecurityUserEntity.DB_USER_NAME;
            filter.Type = SearchFilterTypePolicy.TEXT;
            filter.Operator = SearchFilterOperatorPolicy.CONTAIN;
            filter.Value = userNameTxt.GetValue();
            filters.Add(filter);

            filter = new SearchFilter();
            filter.Column = SecurityUserEntity.DB_USER_IS_VALID_INDC;
            filter.Type = SearchFilterTypePolicy.TEXT;
            filter.Operator = SearchFilterOperatorPolicy.SINGLE;
            filter.Value = (string)userIsValidIndcCombo.GetValue();
            filters.Add(filter);

            searchCriteria.Filter = filters.ToArray();

            return searchCriteria;
        }

        private void Search()
        {
            var data = securityUserRequest.FindBySearchCriteria(PackSearchCriteria());

            if (data != null) securityUsers = data.Datas;

            gridViewPagination.SetTotal(data.Total);

            if (securityUsers == null || securityUsers.Length == 0)
            {
                ShowMessageBox.ShowInfo(securityMessagePolicy.ComposeMessage(SecurityMessagePolicy.GUI_WS_RECORD_NOT_FOUND));
                guiOperateHelper.ResetControls(this.dataGv);
                return;
            }

            dataGv.SetDataSource(securityUsers);

            SetDisplayMode(true);
        }

        private void resetBut_Click(object sender, EventArgs e)
        {
            guiOperateHelper.ResetControls(this.mainPanel);

            SetDisplayMode(false);

            userIsValidIndcCombo.SelectedValue = YesNoPolicy.YES;
        }

        private void createBut_Click(object sender, EventArgs e)
        {
            DisplayPage(GuiDisplayMode.Create, null);
        }

        private void DisplayPage(GuiDisplayMode mode, string userName)
        {
            SecurityUserOperationLinkup linkupData = new SecurityUserOperationLinkup();
            linkupData.DisplayMode = Convert.ToInt32(mode);
            linkupData.UserName = userName;

            this.DisplayAbstractPage(typeof(SecurityUserOperationPage).Name, linkupData);
        }


        private void viewBut_Click(object sender, EventArgs e)
        {
            if (dataGv.RowCount <= 0 || dataGv.SelectedCells.Count <= 0)
            {
                ShowMessageBox.ShowInfo(securityMessagePolicy.ComposeMessage(SecurityMessagePolicy.GUI_WS_RECORD_NOT_FOUND));
                return;
            }

            SecurityUserEntity data = dataGv.GetRowData<SecurityUserEntity>(dataGv.SelectedCells[0].RowIndex);

            DisplayPage(GuiDisplayMode.View, data.UserName);
        }

        private void amendBut_Click(object sender, EventArgs e)
        {
            if (dataGv.RowCount <= 0 || dataGv.SelectedCells.Count <= 0)
            {
                ShowMessageBox.ShowInfo(securityMessagePolicy.ComposeMessage(SecurityMessagePolicy.GUI_WS_RECORD_NOT_FOUND));
                return;
            }

            SecurityUserEntity data = dataGv.GetRowData<SecurityUserEntity>(dataGv.SelectedCells[0].RowIndex);

            DisplayPage(GuiDisplayMode.Amend, data.UserName);
        }

        private void deleteBut_Click(object sender, EventArgs e)
        {
            HandleException(() => Delete());
        }

        private void Delete()
        {
            if (dataGv.RowCount <= 0 || dataGv.SelectedCells.Count <= 0)
            {
                ShowMessageBox.ShowInfo(securityMessagePolicy.ComposeMessage(SecurityMessagePolicy.GUI_WS_RECORD_NOT_FOUND));
                return;
            }

            if (DialogResult.Yes != ShowMessageBox.ShowOption(securityMessagePolicy.ComposeMessage(SecurityMessagePolicy.GUI_CONFIRM_DEL_NULL), securityMessagePolicy.ComposeMessage(SecurityMessagePolicy.GUI_DELETE))) return;

            SecurityUserEntity[] datas = dataGv.GetSelectedCellsData<SecurityUserEntity>();

            securityUserRequest.Deletes(datas.Select(x => x.UserName).ToArray());

            ShowMessageBox.ShowInfo(securityMessagePolicy.ComposeMessage(SecurityMessagePolicy.GUI_SUCCEED_DELETED_NULL));

            Search();
        }

        private void okBut_Click(object sender, EventArgs e)
        {
            if (dataGv.RowCount <= 0 || dataGv.SelectedCells.Count <= 0) return;
            //SecurityUserEntity data = dataGv.GetRowData<SecurityUserEntity>(dataGv.SelectedCells[0].RowIndex);
            SecurityUserEntity[] datas = dataGv.GetSelectedCellsData<SecurityUserEntity>();

            this.ParentAbstractForm.OutputData = datas;
            this.ParentAbstractForm.DialogResult = DialogResult.OK;
            this.ParentAbstractForm.Close();
        }

        private void cancelBut_Click(object sender, EventArgs e)
        {
            this.ParentAbstractForm.DialogResult = DialogResult.Cancel;
            this.ParentAbstractForm.Close();
        }

        private void dataGv_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
        {
            if (IsDialog)
                okBut_Click(null, null);
            else
                viewBut_Click(null, null);
        }
    }
}
