using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Siger.ApiCommon.Utilities;
using Siger.Middlelayer.Common;
using Siger.Middlelayer.Common.AppSettings;
using Siger.Middlelayer.Common.Helpers;
using Siger.Middlelayer.Common.Log;
using Siger.Middlelayer.Common.ModuleEnum;
using Siger.Middlelayer.Repository.Data;
using Siger.Middlelayer.Repository.Repositories.Interface;
using Siger.Middlelayer.Utility.ExcelImport;
using Siger.Middlelayer.Utility.Helpers;
using Siger.Middlelayer.Utility.ImportEntities;

namespace Siger.ApiConfig.Controller
{
    public class BeatSetDownLoadController : BaseController
    {
        private readonly ISigerProjectLevelRepository _levelRepository;
        private readonly ISigerProjectLevelSectionRepository _levelSectionRepository;
        private readonly ISigerProjectMachineRepository _machineRepository;
        public BeatSetDownLoadController(ISigerProjectLevelRepository levelRepository, ISigerProjectLevelSectionRepository levelSectionRepository,
            ISigerProjectMachineRepository machineRepository)
        {
            _levelRepository = levelRepository;
            _levelSectionRepository = levelSectionRepository;
            _machineRepository = machineRepository;
        }

        [HttpGet]
        public IActionResult GetTemplate()
        {
            var fileSetting = Config<FileSettings>.Get();
            if (fileSetting == null)
            {
                throw new BadRequestException(CommonEnum.GetCommCfgFailed);
            }

            var rootDir = FileSystemHelper.GetPhysicalFolders(FileSystemHelper.CommonFileSetting.PhysicalFolder);
            

            return new ObjectResult(CreateBeatSetTemplate());
        }

        private string CreateBeatSetTemplate()
        {
            var language = _machineRepository.GetProjectLanguage(ProjectId);
            var columnNames = new List<string>();
            var titles = _levelRepository.GetLevelTitles(0, ProjectId);
            bool ColumnOnly(CustomAttributeData y) => y.AttributeType == typeof(ExcelColumn);
            var columns = typeof(BeatSetList)
                .GetProperties()
                .Where(x => x.CustomAttributes.Any(ColumnOnly)
                            && x.CustomAttributes.All(m => m.AttributeType != typeof(DonnetExportAttribute)))
                .Select(p => new
                {
                    Column = (language == 0 || !EpPlusLanguageHelper.LanguageDictionary.ContainsKey(p.GetCustomAttributes<ExcelColumn>().First().ColumnName))
                        ? p.GetCustomAttributes<ExcelColumn>().First().ColumnName
                        : EpPlusLanguageHelper.LanguageDictionary[p.GetCustomAttributes<ExcelColumn>().First().ColumnName]
                }).ToList();
            columnNames.AddRange(titles);
            columnNames.AddRange(columns.Select(m => m.Column));

            var helper = new EpPlusForBeatSetHelper();
            var rootDir = FileSystemHelper.GetPhysicalFolders(FileSystemHelper.CommonFileSetting.PhysicalFolder, FileSystemHelper.ExportFileName);
            var levels = new List<string>();
            var list = _levelSectionRepository.GetLevelSectionTree(ProjectId);
            foreach (var levelSectionTree in GetLastLevels(list))
            {
                var names = _levelSectionRepository.GetLevelSectionTitles(levelSectionTree.id, ProjectId);
                levels.Add(string.Join(',', names));
            }

            var temporaryFileName = $"西格云平台-标准节拍配置导入模板_{DateTime.Now:yyyyMMddHHmmss}.xlsx";
            var fileName = Path.Combine(rootDir, temporaryFileName);
            helper.GenerateExcel(columnNames, levels, fileName);
            return $"{FileSystemHelper.CommonFileSetting.RequestPath}/{FileSystemHelper.ExportFileName}/{temporaryFileName}";
        }

        private IList<LevelSectionTree> GetLastLevels(IEnumerable<LevelSectionTree> models)
        {
            var result = new List<LevelSectionTree>();
            foreach (var levelSectionTree in models)
            {
                var model = models.FirstOrDefault(q => q.pid == levelSectionTree.id);
                if (model == null)
                {
                    result.Add(levelSectionTree);
                }
            }
            return result;
        }

        [HttpGet]
        public IActionResult GetTemplates(string name)
        {
            if (string.IsNullOrEmpty(name))
            {
                throw new BadRequestException(ConfigEnum.FileNameIsEmpty);
            }
            var rootDir = FileSystemHelper.GetPhysicalFolders(FileSystemHelper.CommonFileSetting.PhysicalFolder, FileSystemHelper.ExportFileName);
           

            var result = Enum.TryParse(typeof(TemplateNameEnums), name, true, out var template);
            if (!result)
            {
                throw new BadRequestException(ConfigEnum.TemplateFileNotFound);
            }
            var temporaryFileName = $"{name}_{DateTime.Now:yyyyMMddHHmmss}.xlsx";
            var fileName = Path.Combine(rootDir, temporaryFileName);

            var helper = new EpPlusExcelTemplateHelper();
            var type = GetType((TemplateNameEnums)template);
            if (type == null)
            {
                throw new BadRequestException(ConfigEnum.TemplateFileNotFound);
            }
            try
            {
                helper.GenerateTemplate(type, fileName);
                return new ObjectResult($"{FileSystemHelper.CommonFileSetting.RequestPath}/{FileSystemHelper.ExportFileName}/{temporaryFileName}");
            }
            catch (Exception e)
            {
                Logger.WriteLineError("create template file failed, error: " + e.Message);
                throw new BadRequestException(RequestEnum.ExportFailed);
            }
            finally
            {
                helper.Dispose();
            }
        }

        private Type GetType(TemplateNameEnums template)
        {
            Type type = null;
            switch (template)
            {
                case TemplateNameEnums.WorkModeList:
                    type = typeof(WorkModeList);
                    break;
            }

            return type;
        }
    }
}