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

namespace Siger.Middlelayer.TlmRepository.Repositories
{
    internal class ToolLifeToolTechRepository : TlmRepositoryBase<siger_project_toollife_tech_tool>, IToolLifeToolTechRepository
    {
        private readonly ApiTlmDbContext _context;
        public ToolLifeToolTechRepository(ApiTlmDbContext context) : base(context)
        {
            _context = context;
        }

        public IPagedCollectionResult<ResponseGetTechToolList> GetPagedList(int techId, string cutterNumber, int page, int pagesize,
            int toexcel, int projectId, int machine_type = 0, string tool_code = "")
        {
            var querylist = from q in _context.siger_project_toollife_tech_tool
                            join tech in _context.siger_project_toollife_technology on q.technology_id equals tech.id
                            join m in _context.siger_tr_materials on q.material_id equals m.id
                            join t in _context.siger_project_toollife_tool on q.material_id equals t.material_id
                            join c in _context.siger_project_toollife_category on t.category_id equals c.id
                            where q.status == (int)RowState.Valid && q.project_id == projectId && q.technology_id == techId
                            select new ResponseGetTechToolList
                            {
                                id = q.id,
                                remark = q.remark,
                                cutter_number = q.cutter_number,
                                down_length = q.down_length,
                                down_tolerance = q.down_tolerance,
                                flute_count = q.flute_count,
                                flute_length = q.flute_length,
                                reach_length = q.reach_length,
                                upper_tolerance = q.upper_tolerance,
                                tool_model = q.tool_model,
                                handle_model = q.handle_model,
                                //tool_modelName = "",
                                //handle_modelName = "",
                                part_no = q.part_no,
                                material_name = m.name ?? "",
                                supplier = m.supplier ?? "",
                                quantity = q.quantity,
                                category_name = c.name ?? "",
                                rated_life = q.rated_life,
                                material_id = q.material_id,
                                product_id = tech.product_id,
                                route_id = tech.route_id,
                                tool_code = q.tool_code,
                                tool_number = t.number,
                                machine_type = tech.machine_type
                            };

            Expression<Func<ResponseGetTechToolList, bool>> cutterNumberExpression = q => true;
            if (!string.IsNullOrWhiteSpace(cutterNumber))
            {
                cutterNumberExpression = q => q.cutter_number == cutterNumber;
            }
            Expression<Func<ResponseGetTechToolList, bool>> toolCodeExpression = q => true;
            if (!string.IsNullOrWhiteSpace(tool_code))
            {
                toolCodeExpression = q => q.tool_code == tool_code;
            }
            Expression<Func<ResponseGetTechToolList, bool>> machineExpression = q => true;
            if (machine_type != 0)
            {
                machineExpression = q => q.machine_type == machine_type;
            }
            var predicates = cutterNumberExpression.And(machineExpression).And(toolCodeExpression);
            if (toexcel == 0)
            {
                var totalCount = querylist.GroupBy(t => t.id).Select(t => t.FirstOrDefault()).Count(predicates);
                var entities = querylist.Where(predicates).GroupBy(t => t.id)
                    .Select(t => t.FirstOrDefault()).Skip((page - 1) * pagesize).Take(pagesize).AsNoTracking().ToList();
                return new PagedCollectionResult<ResponseGetTechToolList>(entities, totalCount);
            }
            else
            {
                var entities = querylist.Where(predicates).GroupBy(t => t.id).Select(t => t.FirstOrDefault()).AsNoTracking().ToList();
                return new PagedCollectionResult<ResponseGetTechToolList>(entities, 0);
            }
        }

        public CommonImportResult ImportTechnology(IEnumerable<TechToolList> techs, int projectid, int userId)
        {
            var errors = new List<string>();
            var entities = new List<siger_project_toollife_tech_tool>();
            var rowIndex = 1;

            foreach (var tech in techs)
            {
                var product = _context.siger_project_product.FirstOrDefault(q =>
                    q.name == tech.ProductName && q.status == (int)RowState.Valid && q.projectid == projectid);
                if (product == null)
                {
                    errors.Add($"{rowIndex},{Convert.ToString((int)RequestEnum.ProductNotFound)}");
                }
                var route = _context.siger_project_product_route.FirstOrDefault(q =>
                    q.name == tech.Route && q.status == (int)RowState.Valid && q.projectId == projectid);
                if (route == null)
                {
                    errors.Add($"{rowIndex},{Convert.ToString((int)RequestEnum.RouteNotFound)}");
                }
                var material = _context.siger_tr_materials.FirstOrDefault(q =>
                    q.pn == tech.PartNo && q.projectId == projectid && q.status == (int)RowState.Valid);
                if (material == null)
                {
                    errors.Add($"{rowIndex},{Convert.ToString((int)RequestEnum.MaterialNotExist)}");
                    continue;
                }
                var tool = _context.siger_project_toollife_tool.FirstOrDefault(f => f.project_id == projectid && f.status != 0
                  && f.material_id == material.id);
                if (material == null)
                {
                    errors.Add($"{rowIndex},{Convert.ToString((int)RequestEnum.MaterialNotExist)}");
                    continue;
                }
                if (string.IsNullOrEmpty(tech.ToolCode))
                {
                    errors.Add($"{rowIndex},{Convert.ToString((int)TlmEnum.ToolCodeNotFound)}");
                    continue;
                }
                var config = _context.ProjectToollifeToolConfigEntities.Where(f => f.Projectid == projectid && f.Status != 0 && f.Code == tech.ToolCode).AsNoTracking().ToList();
                if (!config.Any(f => f.ToolId == tool.id))
                {
                    errors.Add($"{rowIndex},{Convert.ToString((int)TlmEnum.ToolCodeNotFound)}");
                    continue;
                }
            }
            if (errors.Any())
            {
                return new CommonImportResult(0, string.Join(";", errors));
            }
            foreach (var tech in techs)
            {
                var product = _context.siger_project_product.FirstOrDefault(q =>
                   q.name == tech.ProductName && q.status == (int)RowState.Valid && q.projectid == projectid);
                var route = _context.siger_project_product_route.FirstOrDefault(q =>
                    q.name == tech.Route && q.status == (int)RowState.Valid && q.projectId == projectid);
                var material = _context.siger_tr_materials.FirstOrDefault(q =>
                    q.pn == tech.PartNo && q.projectId == projectid && q.status == (int)RowState.Valid);
                var technology = _context.siger_project_toollife_technology.FirstOrDefault(q =>
                    q.product_id == product.id && q.route_id == route.id && q.status == (int)RowState.Valid
                            && q.project_id == projectid);
                if (technology == null)
                {
                    errors.Add($"{rowIndex},{Convert.ToString((int)RequestEnum.TechnologyNotFound)}");
                }

                if (errors.Any())
                {
                    return new CommonImportResult(0, string.Join(";", errors));
                }
                var entity = new siger_project_toollife_tech_tool
                {
                    cutter_number = tech.CutterNumber,
                    down_tolerance = tech.DownTolerance,
                    reach_length = tech.ReachLength,
                    upper_tolerance = tech.UpperTolerance,
                    remark = tech.Remark.ToStr(),
                    project_id = projectid,
                    technology_id = technology.id,
                    part_no = material.pn,
                    quantity = tech.Quantity.ToInt(),
                    rated_life = tech.RatedLife,
                    material_id = material.id,
                    tool_code = tech.ToolCode
                };
                entities.Add(entity);
            }

            try
            {
                _context.siger_project_toollife_tech_tool.AddRange(entities);
                _context.SaveChanges();
                return new CommonImportResult(1, "1");
            }
            catch
            {
                throw;
            }
        }

        public IEnumerable<ResponseGetTechToolList> GetDataList(int techId, string cutterNumber, int projectId)
        {
            var querylist = from q in _context.siger_project_toollife_tech_tool
                            join tech in _context.siger_project_toollife_technology on q.technology_id equals tech.id
                            join m in _context.siger_tr_materials on q.material_id equals m.id
                            join t in _context.siger_project_toollife_tool on q.material_id equals t.material_id
                            join c in _context.siger_project_toollife_category on t.category_id equals c.id
                            where q.status == (int)RowState.Valid && q.project_id == projectId && q.technology_id == techId
                            select new ResponseGetTechToolList
                            {
                                id = q.id,
                                remark = q.remark,
                                cutter_number = q.cutter_number,
                                down_length = q.down_length,
                                down_tolerance = q.down_tolerance,
                                flute_count = q.flute_count,
                                flute_length = q.flute_length,
                                reach_length = q.reach_length,
                                upper_tolerance = q.upper_tolerance,
                                tool_model = q.tool_model,
                                handle_model = q.handle_model,

                                part_no = q.part_no,
                                material_name = m.name ?? "",
                                supplier = m.supplier ?? "",
                                quantity = q.quantity,
                                category_name = c.name ?? "",
                                rated_life = q.rated_life,
                                material_id = q.material_id
                            };

            Expression<Func<ResponseGetTechToolList, bool>> cutterNumberExpression = q => true;
            if (!string.IsNullOrWhiteSpace(cutterNumber))
            {
                cutterNumberExpression = q => q.cutter_number == cutterNumber;
            }
            var entities = querylist.Where(cutterNumberExpression).AsNoTracking().ToList();
            return entities;
        }

        public IEnumerable<ResponseGetToolCategory> GetToolCategories(int techId, int projectId)
        {
            var querylist = from q in _context.siger_project_toollife_tech_tool
                            join m in _context.siger_tr_materials on q.material_id equals m.id
                            where q.status == (int)RowState.Valid && q.project_id == projectId && q.technology_id == techId
                            select new ResponseGetToolCategory
                            {
                                code = q.part_no,
                                name = m.name ?? "",
                                count = q.quantity,
                            };
            return querylist.AsEnumerable();
        }
    }
}
