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

namespace Siger.Middlelayer.AccRepository.Repositories
{
    internal class SigerEquipmentPositionRepository : AccRepositoryBase<SigerTrEquipmentPosition>, ISigerEquipmentPosition
    {
        private readonly ApiAccDbContext accDbContext;
        public SigerEquipmentPositionRepository(ApiAccDbContext context) : base(context)
        {
            accDbContext = context;
        }

        public PagedCollectionResult<EquipmentPosition> GetPagedList(int line, int station, int position, int projectid, int page, int pagesize)
        {
            int rowstate = (int)RowState.Valid;
            var EquipmentPositions =
                accDbContext.siger_tr_position_equipment.Where(q => q.status == (int)RowState.Valid && q.projectId == projectid);
            var query = from p in EquipmentPositions
                        join m in accDbContext.siger_project_level_section
                        on new { lineid = p.Line, projectids = projectid, rowstatus = rowstate }
                        equals new { lineid = m.id, projectids = m.projectid, rowstatus = m.status }
                        into linetemp
                        from m in linetemp.DefaultIfEmpty()
                        join q in accDbContext.siger_project_level_section
                        on new { stationid = p.Station, projectids = projectid, rowstatus = rowstate }
                        equals new { stationid = q.id, projectids = q.projectid, rowstatus = q.status }
                        into stationtemp
                        from q in stationtemp.DefaultIfEmpty()
                        join po in accDbContext.siger_tr_position
                        on new { positionid = p.Position, projectids = projectid, rowstatus = rowstate }
                        equals new { positionid = po.id, projectids = po.projectId, rowstatus = po.status }
                        into postiontemp
                        from po in postiontemp.DefaultIfEmpty()
                        join u in accDbContext.siger_project_user
                        on new { uid = p.UID, rowstatus = rowstate }
                        equals new { uid = u.mid.ToString(), rowstatus = u.status }
                        into utemp
                        from u in utemp.DefaultIfEmpty()
                        select new EquipmentPosition
                        {
                            id = p.id,
                            line = p.Line,
                            line_value = m.title,
                            station = p.Station,
                            station_value = q.title,
                            position = p.Position,
                            position_value = po.Position,
                            eqid = p.EqID,
                            scriptname = p.ScriptName,
                            uid = p.UID,
                            uid_value = u.name,
                            transdatetime = p.TransDateTime.ToString(ParameterConstant.DateTimeFormat)
                        };
            Expression<Func<EquipmentPosition, bool>> Funline = f => true;
            Expression<Func<EquipmentPosition, bool>> Funstation = f => true;
            Expression<Func<EquipmentPosition, bool>> Funposition = f => true;
            if (line > 0)
                Funline = f => f.line == line;
            if (station > 0)
                Funstation = f => f.station == station;
            if (position > 0)
                Funposition = f => f.position == position;
            var predicate = Funline.And(Funstation).And(Funposition);

            var totalCount = query.Count(predicate);
            var entities = query.Where(predicate).OrderByDescending(q => q.id).Skip((page - 1) * pagesize).Take(pagesize).AsNoTracking().ToList();
            return new PagedCollectionResult<EquipmentPosition>(entities, totalCount);
        }

        public IEnumerable<EquipmentPosition> GetDataList(int line, int station, int position, int projectid)
        {
            int rowstate = (int)RowState.Valid;
            var EquipmentPositions =
                accDbContext.siger_tr_position_equipment.Where(q => q.status == (int)RowState.Valid && q.projectId == projectid);
            var query = from p in EquipmentPositions
                        join m in accDbContext.siger_project_level_section
                        on new { lineid = p.Line, projectids = projectid, rowstatus = rowstate }
                        equals new { lineid = m.id, projectids = m.projectid, rowstatus = m.status }
                        into linetemp
                        from m in linetemp.DefaultIfEmpty()
                        join q in accDbContext.siger_project_level_section
                        on new { stationid = p.Station, projectids = projectid, rowstatus = rowstate }
                        equals new { stationid = q.id, projectids = q.projectid, rowstatus = q.status }
                        into stationtemp
                        from q in stationtemp.DefaultIfEmpty()
                        join po in accDbContext.siger_tr_position
                        on new { positionid = p.Position, projectids = projectid, rowstatus = rowstate }
                        equals new { positionid = po.id, projectids = po.projectId, rowstatus = po.status }
                        into postiontemp
                        from po in postiontemp.DefaultIfEmpty()
                        join u in accDbContext.siger_project_user
                        on new { uid = p.UID, rowstatus = rowstate }
                        equals new { uid = u.mid.ToString(), rowstatus = u.status }
                        into utemp
                        from u in utemp.DefaultIfEmpty()
                        select new EquipmentPosition
                        {
                            id = p.id,
                            line = p.Line,
                            line_value = m.title,
                            station = p.Station,
                            station_value = q.title,
                            position = p.Position,
                            position_value = po.Position,
                            eqid = p.EqID,
                            scriptname = p.ScriptName,
                            uid = p.UID,
                            uid_value = u.name,
                            transdatetime = p.TransDateTime.ToString(ParameterConstant.DateTimeFormat)
                        };
            Expression<Func<EquipmentPosition, bool>> Funline = f => true;
            Expression<Func<EquipmentPosition, bool>> Funstation = f => true;
            Expression<Func<EquipmentPosition, bool>> Funposition = f => true;
            if (line > 0)
                Funline = f => f.line == line;
            if (station > 0)
                Funstation = f => f.station == station;
            if (position > 0)
                Funposition = f => f.position == position;
            var predicate = Funline.And(Funstation).And(Funposition);

            var entities = query.Where(predicate).OrderByDescending(q => q.id).AsNoTracking().ToList();
            return entities;
        }

        public CommonImportResult ImportEquipmentPosition(IEnumerable<EquipmentPositionTemplate> eps, int projectid, int uid)
        {
            var errors = new List<string>();
            var rowIndex = 1;
            foreach (var p in eps)
            {
                rowIndex++;
                var lines = accDbContext.siger_project_level_section.SingleOrDefault(t => t.title == p.line && t.status == (int)RowState.Valid && t.projectid == projectid);
                var stations = accDbContext.siger_project_level_section.SingleOrDefault(t => t.title == p.station && t.status == (int)RowState.Valid && t.projectid == projectid);
                var positions = accDbContext.siger_tr_position.SingleOrDefault(t => t.Position == p.position && t.status == (int)RowState.Valid);

                if (lines == null)
                    errors.Add($"{rowIndex},{(int)RequestEnum.LineError}");
                if (stations == null)
                    errors.Add($"{rowIndex},{(int)RequestEnum.StationError}");
                if (positions == null)
                    errors.Add($"{rowIndex},{(int)RequestEnum.PositionError}");
            }
            if (errors.Any())
            {
                return new CommonImportResult(0, string.Join(";", errors));
            }

            var entities = new List<SigerTrEquipmentPosition>();

            foreach (var p in eps)
            {
                var lines = accDbContext.siger_project_level_section.SingleOrDefault(t => t.title == p.line && t.status == (int)RowState.Valid && t.projectid == projectid);
                var stations = accDbContext.siger_project_level_section.SingleOrDefault(t => t.title == p.station && t.status == (int)RowState.Valid && t.projectid == projectid);
                var positions = accDbContext.siger_tr_position.SingleOrDefault(t => t.Position == p.position && t.status == (int)RowState.Valid);
                if (lines != null && stations != null && positions != null)
                {
                    var psEntity = new SigerTrEquipmentPosition
                    {
                        Line = lines.id,
                        Station = stations.id,
                        Position = positions.id,
                        EqID = p.eqid ?? "",
                        ScriptName = p.scriptname ?? "",
                        UID = uid.ToString(),
                        TransDateTime = DateTime.Now,
                        projectId = projectid
                    };
                    entities.Add(psEntity);
                }
            }
            try
            {
                accDbContext.siger_tr_position_equipment.AddRange(entities);
                accDbContext.SaveChanges();
                return new CommonImportResult(1, "1");
            }
            catch
            {
                throw;
            }
        }
    }
}
