using System.Collections.Generic;
using System.Linq;
using Siger.Middlelayer.Common;
using Siger.Middlelayer.Common.ModuleEnum;
using Siger.Middlelayer.Repository.Data;
using Siger.Middlelayer.Repository.Entities;
using Siger.Middlelayer.Repository.Repositories.Interface;
using Siger.Middlelayer.Repository.Response;

namespace Siger.Middlelayer.Repository.Repositories
{
    internal class SigerProjectLevelSectionMachineRepository : ApiConfigRepositoryBase<siger_project_level_section_machine>, ISigerProjectLevelSectionMachineRepository
    {
        private readonly ApiConfigDbContext _context;
        public SigerProjectLevelSectionMachineRepository(ApiConfigDbContext context) : base(context)
        {
            _context = context;
        }

        public ResponseGetSectionMachine GetSectionMachine(int projectId, int sectionid)
        {
            var data = (from section in _context.siger_project_machine_attribution
                        join machine in _context.siger_project_machine on section.machine equals machine.id
                        where section.station == sectionid && machine.status == (int)RowState.Valid && machine.status == (int)RowState.Valid &&
                              machine.projectid == projectId
                        select new ResponseGetSectionMachine
                        {
                            id = machine.id,
                            title = machine.title
                        }
                           ).FirstOrDefault();

            return data;
        }

        public IEnumerable<ResponseIdName> GetStations(int projectId)
        {
            var sections = from section in _context.siger_project_machine_attribution
                           join sec in _context.siger_project_level_section on section.station equals sec.id
                           where sec.status == (int)RowState.Valid && sec.status == (int)RowState.Valid &&
                                 sec.projectid == projectId
                           select sec;

            var parentSectionIds = sections.Select(m => m.parentid).Distinct();
            var result = new List<ResponseIdName>();
            foreach (var sectionId in parentSectionIds)
            {
                var sec = _context.siger_project_level_section.FirstOrDefault(q => q.id == sectionId);
                if (sec != null)
                {
                    result.Add(new ResponseIdName
                    {
                        id = sec.id,
                        name = sec.title
                    });
                }
            }

            return result;
        }

        public IEnumerable<siger_project_level_section> GetLastSection(int projectId)
        {
            var lastLevels = _context.siger_project_level.Where(q => q.projectid == projectId && q.status == (int)RowState.Valid).ToList();
            if (!lastLevels.Any())
            {
                return new List<siger_project_level_section>();
            }
            var maxId = lastLevels.Max(q => q.id);
            var query = _context.siger_project_level_section.Where(q => q.levelid == maxId && q.projectid == projectId && q.status == (int)RowState.Valid);

            return query.AsEnumerable();
        }

        public int GetSecondLevelId(int projectId)
        {
            var levelids = _context.siger_project_level.Where(q => q.projectid == projectId  && q.status == (int)RowState.Valid)
                .OrderByDescending(m => m.id).Select(q => q.id).ToList();
            if (levelids.Count >= 2)
            {
                return levelids[1];
            }
            if (levelids.Count == 1)
            {
                return levelids[0];
            }
            return 0;
        }


        public IEnumerable<MachinSectionInfo> GetMachinSectionInfos(IEnumerable<int> machineIds, int projectId)
        {
            var query = from sm in _context.siger_project_machine_attribution
                        join ts in _context.siger_project_level_section on sm.station equals ts.id
                        join s in _context.siger_project_level_section on ts.parentid equals s.id
                        where sm.status == (int)RowState.Valid && ts.status == (int)RowState.Valid &&
                              s.status == (int)RowState.Valid && ts.projectid == projectId
                              && machineIds.Contains(sm.machine)
                        select new MachinSectionInfo
                        {
                            id = s.id,
                            machineId = sm.machine,
                            section_name = s.title,
                            station_name = ts.title
                        };
            return query.AsEnumerable();
        }

        public IEnumerable<siger_project_station> GetGroupStationsByUserId(int userId, int time)
        {
            var query = _context.siger_project_station.Where(t => t.status == (int)RowState.Valid && t.starttime < time && t.endtime > time);
            var querys = from p in query
                         join q in _context.siger_project_user_group
                         on p.groupid equals q.groupid
                         where q.mid == userId
                         select p;
            return querys;
        }

        public IEnumerable<siger_project_level_section> GetSectionTreeBySectionIds(IEnumerable<int> sectionIds, int projectId)
        {
            if (!sectionIds.Any())
            {
                return new List<siger_project_level_section>();
            }

            var sections = new List<siger_project_level_section>();
            foreach (var p in sectionIds)
            {
                var section = _context.siger_project_level_section.FirstOrDefault(t => t.id == p && t.status == (int)RowState.Valid && t.projectid == projectId);
                if (section != null)
                {
                    sections.Add(section);
                }
                sections.AddRange(GetParentSelfLevelSections(p, projectId));
                //sections.AddRange(GetSonLevelSections(p, projectId).ToList());
            }
            sections = sections.GroupBy(t => t.id).Select(t => t.FirstOrDefault()).ToList();
            return sections;
        }

        public IEnumerable<ResponseIdName> GetNCStations(int projectId)
        {
            var sections = from section in _context.siger_project_machine_attribution
                           join sec in _context.siger_project_level_section on section.station equals sec.id
                           join m in _context.siger_project_machine on section.machine equals m.id
                           where sec.status == (int)RowState.Valid && sec.status == (int)RowState.Valid &&
                                 sec.projectid == projectId && m.category == (int)MachineCategory.NC
                           select sec;

            var parentSectionIds = sections.Select(m => m.parentid).Distinct();
            var result = new List<ResponseIdName>();
            foreach (var sectionId in parentSectionIds)
            {
                var sec = _context.siger_project_level_section.FirstOrDefault(q => q.id == sectionId);
                if (sec != null)
                {
                    result.Add(new ResponseIdName
                    {
                        id = sec.id,
                        name = sec.title
                    });
                }
            }

            return result;
        }

        public ResponseGetSectionMachine GetNCSectionMachine(int projectId, int sectionid)
        {
            var data = (from section in _context.siger_project_machine_attribution
                        join machine in _context.siger_project_machine on section.machine equals machine.id
                        where section.station == sectionid && machine.status == (int)RowState.Valid && machine.status == (int)RowState.Valid &&
                              machine.projectid == projectId && machine.category == (int)MachineCategory.NC
                        select new ResponseGetSectionMachine
                        {
                            id = machine.id,
                            title = machine.title
                        }
                ).FirstOrDefault();

            return data;
        }
    }
}
