using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.AspNetCore.Mvc;
using Siger.ApiCommon.Result;
using Siger.ApiCommon.Utilities;
using Siger.Middlelayer.AccRepository.Entities;
using Siger.Middlelayer.AccRepository.Repositories.Interface;
using Siger.Middlelayer.AccRepository.Request;
using Siger.Middlelayer.AccRepository.Response;
using Siger.Middlelayer.Common;
using Siger.Middlelayer.Common.AppSettings;
using Siger.Middlelayer.Common.Extensions;
using Siger.Middlelayer.Common.Helpers;
using Siger.Middlelayer.Log;
using Siger.Middlelayer.Repository;
using Siger.Middlelayer.Repository.Repositories.Interface;
using Siger.Middlelayer.Repository.Request;
using Siger.Middlelayer.Utility.Helpers;
using Siger.Middlelayer.Utility.ImportEntities;

namespace Siger.ApiACC.Controllers
{
    public class ParameterConfigController : BaseController
    {
        private readonly IUnitOfWork _unitOfWork;
        private readonly ITrParameterConfigRepository _parameterConfigRepository;
        private readonly ISigerProjectLevelSectionRepository _levelSectionRepository;
        public ParameterConfigController(IUnitOfWork unitOfWork, ITrParameterConfigRepository parameterConfigRepository,
            ISigerProjectLevelSectionRepository levelSectionRepository)
        {
            _unitOfWork = unitOfWork;
            _parameterConfigRepository = parameterConfigRepository;
            _levelSectionRepository = levelSectionRepository;
        }

        [HttpGet]
        public IActionResult GetPageList(int sectionId, int page = PageIndex, int pagesize = PageSize, int toexcel = 0)
        {
            var data = _parameterConfigRepository.GetPagedConfigList(sectionId, page, pagesize, ProjectId, toexcel);
            var responses = new List<ResponseParameterConfig>();
            var sections = _levelSectionRepository.GetList(t => t.projectid == ProjectId && t.status == (int)RowState.Valid).ToList();
            foreach (var config in data.Data)
            {
                var response = Mapper<ResponseParameterConfig, ResponseParameterConfig>.Map(config);
                var sectionIds = new List<int>();
                var allSectionIds = GetParentSections(sectionIds, config.section_id);
                allSectionIds.Reverse();

                response.section_ids = allSectionIds;
                response.section_name = GetChannelSection(config.section_id, sections);
                responses.Add(response);
            }

            if (toexcel == 0)
            {
                return new PagedObjectResult(responses, data.Total, page, pagesize);
            }

            return ExportConfigList(responses);
        }

        private List<int> GetParentSections(List<int> sectionids, int parentid)
        {
            var section = _levelSectionRepository.Get(t => t.projectid == ProjectId && t.status == (int)RowState.Valid && t.id == parentid);
            if (section != null)
            {
                sectionids.Add(section.id);
                parentid = section.parentid;
                return GetParentSections(sectionids, parentid);
            }
            else
            {
                return sectionids;
            }
        }

        [HttpGet]
        private IActionResult ExportConfigList(List<ResponseParameterConfig> responses)
        {
            if (!responses.Any())
            {
                throw new BadRequestException(CommonEnum.RecordNotFound);
            }

            
            var rootDir = FileSystemHelper.GetPhysicalFolders( FileSystemHelper.CommonFileSetting.PhysicalFolder, FileSystemHelper.ExportFileName);
          
            var temporaryFileName = $"ParameterConfig_{DateTime.Now:yyyyMMddHHmmss}.xlsx";
            var fileName = Path.Combine(rootDir, temporaryFileName);

            var helper = new EpPlusExcelHelper<TrParameterConfigTemplate>();
            try
            {
                var machineYields = new List<TrParameterConfigTemplate>();
                var index = 1;
                foreach (var yield in responses)
                {
                    var machineYield = new TrParameterConfigTemplate
                    {
                        No = index,
                        Name = yield.name,
                        Attribute = yield.attribute,
                        SectionName = yield.section_name
                    };
                    machineYields.Add(machineYield);
                    index++;
                }

                helper.GenerateExcel(machineYields, fileName);
                return new ObjectResult($"{FileSystemHelper.CommonFileSetting.RequestPath}/{FileSystemHelper.ExportFileName}/{temporaryFileName}");
            }
            catch (Exception e)
            {
                Logger.WriteLineError("ExportConfigList failed, error: " + e.Message);
                throw new BadRequestException(RequestEnum.ExportFailed);
            }
            finally
            {
                helper.Dispose();
            }
        }

        [HttpPost]
        public IActionResult Add([FromBody]RequestAddParameterConfig request)
        {
            if (string.IsNullOrWhiteSpace(request.section_id))
            {
                throw new BadRequestException(RequestEnum.LevelNotFound);
            }
            if (string.IsNullOrWhiteSpace(request.name))
            {
                throw new BadRequestException(RequestEnum.NameIsEmpty);
            }
            if (string.IsNullOrWhiteSpace(request.attribute))
            {
                throw new BadRequestException(RequestEnum.ParameterError);
            }

            var entity = new SigerTrParameterConfig
            {
                section_id = request.section_id.ToInt(),
                name = request.name,
                attribute = request.attribute,
                create_time = DateTime.Now,
                creator_mid = UserId,
                projectId = ProjectId,
                status = (int)RowState.Valid
            };
            _parameterConfigRepository.Insert(entity);
            if (_unitOfWork.Commit() > 0)
            {
                return new ObjectResult(CommonEnum.Succefull);
            }
            throw new BadRequestException(CommonEnum.Fail);
        }

        [HttpPost]
        public IActionResult Update([FromBody]RequestUpdateParameterConfig request)
        {
            var entity = _parameterConfigRepository.Get(q => q.id == request.id && q.projectId == ProjectId && q.status == (int) RowState.Valid);
            if (entity == null)
            {
                throw new BadRequestException(CommonEnum.RecordNotFound);
            }
            var exist = _parameterConfigRepository.Get(q => q.id != request.id && q.projectId == ProjectId && q.status == (int)RowState.Valid && q.section_id == request.section_id.ToInt()
                && q.name == request.name && q.attribute == request.attribute);
            if (exist != null)
            {
                throw new BadRequestException(CommonEnum.RecordExits);
            }

            entity.section_id = request.section_id.ToInt();
            entity.attribute = request.attribute;
            entity.name = request.name;
            entity.create_time = DateTime.Now;
            entity.creator_mid = UserId;
            _parameterConfigRepository.Update(entity);
            if (_unitOfWork.Commit() > 0)
            {
                return new ObjectResult(CommonEnum.Succefull);
            }
            throw new BadRequestException(CommonEnum.Fail);
        }

        [HttpPost]
        public IActionResult Delete([FromBody]RequestDeleteEntities request)
        {
            if (request.ids == null || !request.ids.Any())
            {
                throw new BadRequestException(RequestEnum.ParameterError);
            }

            foreach (var id in request.ids)
            {
                var entity = _parameterConfigRepository.Get(q => q.id == id && q.projectId == ProjectId && q.status == (int)RowState.Valid);
                if (entity != null)
                {
                    entity.status = (int) RowState.Invalid;
                    _parameterConfigRepository.Update(entity);
                }
            }
            if (_unitOfWork.Commit() > 0)
            {
                return new ObjectResult(CommonEnum.Succefull);
            }
            throw new BadRequestException(CommonEnum.Fail);
        }

        [HttpGet]
        public IActionResult GetAttributes(int sectionId)
        {
            var stations = _levelSectionRepository.GetLevelSectionIds(sectionId, ProjectId);
            var attributes = _parameterConfigRepository.GetList(q =>
                  stations.Contains( q.section_id) && q.status == (int) RowState.Valid && q.projectId == ProjectId)
                .Select(m => m.attribute).Distinct().ToList();

            return new ObjectResult(attributes);
        }
    }
}