using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.EntityFrameworkCore;
using Siger.Middlelayer.CncRepository.Entities;
using Siger.Middlelayer.CncRepository.Repositories.Interface;
using Siger.Middlelayer.CncRepository.Request;
using Siger.Middlelayer.CncRepository.Response;
using Siger.Middlelayer.Common;
using Siger.Middlelayer.Common.Helpers;
using Siger.Middlelayer.Common.ModuleEnum;
using Siger.Middlelayer.Repository.Response;

namespace Siger.Middlelayer.CncRepository.Repositories
{
    internal class ProduceScheduleRepository :  CncRepositoryBase<siger_project_produce_schedule>, IProduceScheduleRepository
    {
        private readonly ApiCncDbContext _context;
        public ProduceScheduleRepository(ApiCncDbContext context) : base(context)
        {
            _context = context;
        }

        public IEnumerable<ResponseGetProductRouteInfo> GetRoutes(int productId, int levelId, int projectId)
        {
            var queryList = from q in _context.siger_project_product_route
                            join s in _context.siger_project_level_section on q.sectionId equals s.id
                            where q.projectId == projectId && q.status == (int)RowState.Valid
                                  && s.status == (int)RowState.Valid
                                  && q.projectId == projectId && q.productId == productId && q.levelId == levelId
                            select new ResponseGetProductRouteInfo
                            {
                                sectionid = q.sectionId,
                                serialnumber = q.serialNumber,
                                sectionname = s.title
                            };
            return queryList.AsNoTracking().ToList();
        }

        public IEnumerable<ResponseGetCrashList> GetCrashLists(int sectionId, int projectId)
        {
            var sectionIds = GetLevelSectionIds(sectionId, projectId);

            var query = from q in _context.siger_project_produce_schedule
                join pd in _context.siger_project_product_plan_detail on q.plandetail_id equals pd.id
                join p in _context.siger_project_product_plan on pd.planId equals p.id
                where p.projectid == projectId && sectionIds.Contains(q.sectionId) &&
                      (p.status == (int) PlanProcess.HasPlan || p.status == (int) PlanProcess.Producing)
                      && q.status == (int)RowState.Valid && pd.status == (int)RowState.Valid 
                select new ResponseGetCrashList
                {
                    code = p.code,
                    orderNumber = pd.orderNumber,
                    sectionId = q.sectionId,
                    productName = p.product_name,
                    startTime = q.startTime,
                    endTime = q.endTime,
                    planId = p.id,
                    delivery_time = p.delivery_time
                };
            return query.AsEnumerable();
        }

        public IEnumerable<GetMachineGanteInfo> GetMachineGante(int sectionId, int projectId)
        {
            var sectionIds = GetLevelSectionIds(sectionId, projectId);

            var query = from q in _context.siger_project_produce_schedule
                join pd in _context.siger_project_product_plan_detail on q.plandetail_id equals pd.id
                join p in _context.siger_project_product_plan on pd.planId equals p.id
                where p.projectid == projectId && sectionIds.Contains(q.sectionId) && q.status == (int)RowState.Valid &&
                      pd.status == (int)RowState.Valid &&
                      (p.status == (int)PlanProcess.HasPlan || p.status == (int)PlanProcess.Producing)
                select new GetMachineGanteInfo
                {
                    id = q.id,
                    orderNumber = pd.orderNumber,
                    startTime = q.startTime,
                    endTime = q.endTime,
                    sectionId = q.sectionId,
                    okNumber = pd.ok_number,
                    nokNumber = pd.nok_number,
                    quanlity = pd.quantity,
                    productName = p.product_name,
                    code = p.code
                };
            return query.AsEnumerable();
        }

        public bool AddChangLingSchedule(RequestChanglingAddSchedule request, siger_project_product_plan plan, int projectId)
        {
            var orderNumbers = request.orders.Select(m => m.orderNumber).Distinct();
            foreach (var orderNumber in orderNumbers)
            {
                var detail = request.orders.First(m => m.orderNumber == orderNumber);
                var sectionStartTime = request.orders.Where(m => m.orderNumber == orderNumber).OrderBy(m => DateTime.Parse(m.startTime)).First();
                var sectionEndTime = request.orders.Where(m => m.orderNumber == orderNumber).OrderByDescending(m => DateTime.Parse(m.endTime)).First();
                var planDetail = new siger_project_product_plan_detail
                {
                    addTime = DateTime.Now,
                    levelId = 0,
                    startTime = UnixTimeHelper.GetUnixByShortDate(sectionStartTime.startTime),
                    endTime = UnixTimeHelper.GetUnixByShortDate(sectionEndTime.endTime),
                    orderNumber = orderNumber,
                    planId = request.planId,
                    projectId = projectId,
                    quantity = detail.count,
                };
                _context.siger_project_product_plan_detail.Add(planDetail);
                if (_context.SaveChanges() <= 0)
                {
                    return false;
                }

                var schedules = request.orders.Where(m => m.orderNumber == orderNumber);
                foreach (var schedule in schedules)
                {
                    var entity = new siger_project_produce_schedule
                    {
                        addTime = DateTime.Now,
                        endTime = UnixTimeHelper.GetUnixByShortDate(schedule.endTime),
                        projectId = projectId,
                        sectionId = schedule.machine_id,
                        startTime = UnixTimeHelper.GetUnixByShortDate(schedule.startTime),
                        plandetail_id = planDetail.id,
                        cycle_time = schedule.cycleTime,
                        route_name = schedule.route_name,
                        remark = schedule.remark
                    };
                    _context.siger_project_produce_schedule.Add(entity);
                }
            }

            if (plan != null)
            {
                plan.status = (int)PlanProcess.HasPlan;
                _context.siger_project_product_plan.Update(plan);
            }

            if (_context.SaveChanges() <= 0)
            {
                return false;
            }
            return true;
        }

        public IEnumerable<ResponsePlanJob> GetResponsePlanJob(int planId, int projectId)
        {
            var query = from q in _context.siger_project_produce_schedule
                join d in _context.siger_project_product_plan_detail on q.plandetail_id equals d.id
                join p in _context.siger_project_product_plan on d.planId equals p.id
                where p.id == planId && q.projectId == projectId && q.status == (int)RowState.Valid
                select new ResponsePlanJob
                {
                    planDetailId = d.id,
                    quanlity = d.quantity,
                    route_name = q.route_name,
                    order_number = d.orderNumber
                };
            return query.AsEnumerable();
        }
    }
}
