using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using Siger.Middlelayer.AccRepository.Entities;
using Siger.Middlelayer.AccRepository.Repositories.Interface;
using Siger.Middlelayer.AccRepository.Response;
using Siger.Middlelayer.Common;
using Siger.Middlelayer.Common.Extensions;
using Siger.Middlelayer.Repository.Extensions;
using Siger.Middlelayer.Repository.Paged;
using Siger.Middlelayer.Utility.ImportEntities;

namespace Siger.Middlelayer.AccRepository.Repositories
{
    internal class SigerRoutingOutStationRepository : AccRepositoryBase<SigerTrRoutingOutStation>, ISigerRoutingOutStation
    {
        private ApiAccDbContext accDbContext;
        public SigerRoutingOutStationRepository(ApiAccDbContext context) : base(context)
        {
            accDbContext = context;
        }

        /// <summary>
        /// 导入
        /// </summary>
        /// <param name="outstations"></param>
        /// <param name="projectid"></param>
        /// <returns></returns>
        public CommonImportResult ImportRoutingOutStation(IEnumerable<RoutingOutStationTemplate> outstations, int projectid)
        {
            var routingoutstations = outstations.ToList();
            var entities = new List<SigerTrRoutingOutStation>();

            var errors = new List<string>();
            var rowIndex = 1;
            foreach (var p in routingoutstations)
            {
                rowIndex++;
                var linemodel = accDbContext.siger_project_level_section.FirstOrDefault(t => t.title == p.line && t.projectid == projectid && t.status == (int)RowState.Valid);
                var stationmodel = accDbContext.siger_project_level_section.FirstOrDefault(t => t.title == p.station && t.projectid == projectid && t.status == (int)RowState.Valid);
                var dicts1 = accDbContext.siger_tr_dict.FirstOrDefault(t => t.dval == p.status && t.status == (int)RowState.Valid && t.cat == AccDictCost.status && t.projectId == projectid);
                var dicts2 = accDbContext.siger_tr_dict.FirstOrDefault(t => t.dval == p.eventno && t.status == (int)RowState.Valid && t.cat == AccDictCostNoProjectId.eventno);
                var model = accDbContext.siger_tr_routing_outstation.FirstOrDefault(t => (t.Line.ToString() == p.line && t.Station.ToString() == p.station && t.EventNo.ToString() == p.eventno) || t.ResultStatus == p.status
                    && t.projectId == projectid && t.status == (int)RowState.Valid);

                if (linemodel == null)
                    errors.Add($"{rowIndex},{(int)RequestEnum.LineError}");
                if (stationmodel == null)
                {
                    errors.Add($"{rowIndex},{(int)RequestEnum.StationError}");
                }
                if (dicts1 == null)
                {
                    errors.Add($"{rowIndex},{(int)RequestEnum.RoutingStatusNotFind}");
                }
                if (dicts2 == null)
                {
                    errors.Add($"{rowIndex},{(int)RequestEnum.EventNoNotFind}");
                }
                var repeats = routingoutstations.Where(t => (t.line == p.line && t.station == p.station && t.eventno == p.eventno)
                    || t.status == p.status);
                if (model != null || repeats.Count() > 1)
                {
                    errors.Add($"{rowIndex},{(int)RequestEnum.DataExist}");
                }
            }

            if (errors.Any())
            {
                return new CommonImportResult(0, string.Join(";", errors));
            }

            foreach (var item in outstations)
            {
                var linemodel = accDbContext.siger_project_level_section.FirstOrDefault(t => t.title == item.line && t.projectid == projectid && t.status == (int)RowState.Valid);
                var stationmodel = accDbContext.siger_project_level_section.FirstOrDefault(t => t.title == item.station && t.projectid == projectid && t.status == (int)RowState.Valid);
                var dicts1 = accDbContext.siger_tr_dict.FirstOrDefault(t => t.dval == item.status && t.status == (int)RowState.Valid && t.cat == AccDictCost.status && t.projectId == projectid);
                var dicts2 = accDbContext.siger_tr_dict.FirstOrDefault(t => t.dval == item.eventno && t.status == (int)RowState.Valid && t.cat == AccDictCostNoProjectId.eventno);
                if (linemodel != null && stationmodel != null && dicts1 != null && dicts2 != null)
                {
                    var outstation = new SigerTrRoutingOutStation
                    {
                        projectId = projectid,
                        Line = linemodel.id,
                        Station = stationmodel.id,
                        ResultStatus = dicts1.dkey ?? "",
                        EventNo = dicts2.dkey.ToInt()
                    };
                    entities.Add(outstation);
                }
            }
            try
            {
                accDbContext.siger_tr_routing_outstation.AddRange(entities);
                accDbContext.SaveChanges();
                return new CommonImportResult(1, "1");
            }
            catch
            {
                throw;
            }
        }

        public SigerTrRoutingOutStation GetResultStatusBySection(int section, int pid)
        {
            var query = accDbContext.siger_tr_routing_outstation.Where(f => f.status == (int)RowState.Valid && f.projectId.Equals(pid) && f.Station.Equals(section));
            return query.FirstOrDefault();
        }
        public SigerTrRoutingOutStation GetSectionByResultStatus(string resultStatus, int pid)
        {
            var query = accDbContext.siger_tr_routing_outstation.Where(f => f.status == (int)RowState.Valid && f.projectId.Equals(pid) && f.ResultStatus.Equals(resultStatus));
            return query.FirstOrDefault();
        }

        public IPagedCollectionResult<ResponseRoutingOutStation> GetRoutingOutStationPage(int projectId,int line, int station, int eventno, string status, int page = 1, int pagesize = 10)
        {
            Expression<Func<ResponseRoutingOutStation, bool>> Funcat = f => true;
            Expression<Func<ResponseRoutingOutStation, bool>> Funkey = f => true;
            Expression<Func<ResponseRoutingOutStation, bool>> Funline = f => true;
            Expression<Func<ResponseRoutingOutStation, bool>> Funeventno = f => true;
            Expression<Func<ResponseRoutingOutStation, bool>> Funstatus = f => true;
            if (line != 0)
                Funline = f => f.line == line;
            if (station != 0)
                Funkey = f => f.station == station;
            if (eventno != 0)
                Funeventno = f => f.eventno == eventno;
            if (!string.IsNullOrEmpty(status) && status != "0")
                Funstatus = f => f.status_value == status;

            var query = from u in accDbContext.siger_tr_routing_outstation
                        join e in accDbContext.siger_tr_routing_eventno on u.EventNo equals e.EventNo
                        join l in accDbContext.siger_project_level_section on u.Line equals l.id
                        join s in accDbContext.siger_project_level_section on u.Station equals s.id
                        where u.projectId == projectId && u.status == (int)RowState.Valid
                        select new ResponseRoutingOutStation
                        {
                             id=u.id,
                             line=u.Line,
                             line_value=l.title,
                             station=u.Station,
                             station_value=s.title,
                             eventno=e.EventNo,
                             eventno_value=e.Descr,
                             status_value=u.ResultStatus
                        };

            var predicate = Funcat.And(Funkey).And(Funline).And(Funeventno).And(Funstatus);
            var total = query.Count(predicate);
            var data = query.Where(predicate).Skip((page - 1) * pagesize).Take(pagesize).ToList();
            return new PagedCollectionResult<ResponseRoutingOutStation>(data, total);
        }
    }
}
