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

namespace Siger.Middlelayer.ToolRepository.Repositories
{
    internal class SigerProjectToolRepository : ApiToolRepositoryBase<SigerProjectTool>, ISigerProjectToolRepository
    {
        ApiToolDbContext context;
        public SigerProjectToolRepository(ApiToolDbContext context) : base(context)
        {
            this.context = context;
        }

        public List<SigerProjectTool> GetList(int projectId, string toolName, string brand, string supplier, 
            double? priceStart, double? priceEnd, int? toExcel, int page, int pageSize, out int totolCount)
        {
            var list = context.siger_project_tool.Where(f => f.status == (int)RowState.Valid && f.projectid == projectId);
            if (null != priceStart && null != priceEnd && priceEnd < priceStart)
            {
                throw new BadRequestException(ToolEnum.PriceRangeError);
            }
            Expression<Func<SigerProjectTool, bool>> toolNameEx = f => true;
            Expression<Func<SigerProjectTool, bool>> brandEx = f => true;
            Expression<Func<SigerProjectTool, bool>> supplierEx = f => true;
            Expression<Func<SigerProjectTool, bool>> startEx = f => true;
            Expression<Func<SigerProjectTool, bool>> endEx = f => true;
            if (!string.IsNullOrEmpty(toolName) && toolName != "0")
            {
                toolNameEx = f => f.name == toolName;
            }
            if (!string.IsNullOrEmpty(brand) && brand != "0")
            {
                brandEx = f => f.brand == brand;
            }
            if (!string.IsNullOrEmpty(supplier) && supplier != "0")
            {
                supplierEx = f => f.supplier == supplier;
            }
            if (null != priceStart)
            {
                startEx = f => f.unitprice >= priceStart;
            }
            if (null != priceEnd)
            {
                endEx = f => f.unitprice <= priceEnd;
            }
            var predicate = toolNameEx.And(brandEx).And(supplierEx).And(startEx).And(endEx);
            var data = list.Where(predicate);
            totolCount = data.Count();
            if (toExcel != null)
            {
                return data.ToList();
            }
            var result = data.Skip((page - 1) * pageSize).Take(pageSize).AsNoTracking().ToList();
            
            return result;
        }

        public ResponseDropDownList GetDropDownList(int projectID, string toolName = null, string brand = null)
        {
            var tmp = context.siger_project_tool.Where(f => f.status == (int)RowState.Valid && f.projectid == projectID).Select(f => new { f.name, f.brand, f.supplier });
            if (!string.IsNullOrEmpty(toolName))
            {
                tmp = tmp.Where(f => f.name == toolName);
            }
            if (!string.IsNullOrEmpty(brand))
            {
                tmp = tmp.Where(f => f.brand == brand);
            }
            var list = tmp.ToList();
            var result = new ResponseDropDownList();
            if (list.Count == 0)
            {
                return new ResponseDropDownList();
            }
            if (toolName == null)
            {
                var names = list.Select(f => f.name).Where(f=>!string.IsNullOrEmpty(f)).Distinct();
                foreach (var item in names)
                {
                    result.names.Add(item);
                }
            }
            if(brand==null)
            {
                var brands = list.Select(f => f.brand).Where(f => !string.IsNullOrEmpty(f)).Distinct();
                foreach (var item in brands)
                {
                    result.brands.Add(item);
                }
            }
            var suppliers = list.Select(f => f.supplier).Where(f => !string.IsNullOrEmpty(f)).Distinct();
            foreach (var item in suppliers)
            {
                result.suppliers.Add(item);
            }
            return result;
        }

        public List<string> GetToolSupplierDropDownList(int projectID)
        {
            var tmp = context.siger_project_tool.Where(f => f.status == (int)RowState.Valid && f.projectid == projectID).Select(f=>f.name).Distinct().ToList();
            if (tmp.Count == 0)
            {
                return new List<string>();
            }
            return tmp;
        }

        public CommonImportResult ImportTools(IEnumerable<ToolSupplierList> tools, int projectId)
        {
            var errors = new List<string>();
            var rowIndex = 1;
            foreach (var toolEntity in tools)
            {
                rowIndex++;
                if (string.IsNullOrEmpty(toolEntity.Name) || string.IsNullOrEmpty(toolEntity.DrawingCode))
                {
                    errors.Add($"{rowIndex},{(int)RequestEnum.ParameterMiss}");
                }
                var entity = context.siger_project_tool.FirstOrDefault(q => q.drawingcode == toolEntity.DrawingCode && q.status == (int)RowState.Valid);
                if (entity != null)
                {
                    errors.Add($"{rowIndex},{(int)RequestEnum.DrawingCodeHasExist}");
                }
            }
            if (errors.Any())
            {
                return new CommonImportResult(0, string.Join(";", errors));
            }

            foreach (var toolEntity in tools)
            {
                float? price = null;
                if (!string.IsNullOrEmpty(toolEntity.UnitPrice))
                {
                    var result = float.TryParse(toolEntity.UnitPrice, out var pc);
                    if (result)
                    {
                        price = pc;
                    }
                }
                var record = new SigerProjectTool
                {
                    projectid = projectId,
                    name = toolEntity.Name,
                    spec = toolEntity.Spec,
                    brand = toolEntity.Brand,
                    material = toolEntity.Material,
                    hardness = toolEntity.Hardness,
                    drawingcode = toolEntity.DrawingCode,
                    supplier = toolEntity.Supplier,
                    suppliercode = toolEntity.SupplierCode,
                    unitprice = price,
                    description = toolEntity.Description,
                    status = (int)RowState.Valid
                };
                context.siger_project_tool.Add(record);
                context.SaveChanges();
            }

            return new CommonImportResult(1, "1");
        }

        public IEnumerable getAllUserByCurrentUserProjectId(int projectId)
        {
            var user = context.siger_project_user.FirstOrDefault(f => f.projectid == projectId && f.status == (int)RowState.Valid);
            if (user == null)
            {
                //throw new BadRequestException(CommonEnum.RecordNotFound);
                return null;
            }
            var res2 = context.siger_project_user.Where(f => f.projectid == projectId && f.status == (int)RowState.Valid).
                                                   Select(f => new ResponseAllUserByCurrentUserProjectId
                                                   {
                                                       id = f.id,
                                                       mid = f.mid,
                                                       name = f.name,
                                                       work_code = f.work_code
                                                   });
            if (!res2.Any())
            {
                //throw new BadRequestException(CommonEnum.RecordNotFound);
                return null;
            }
            else
            {
                return res2;
            }
        }

        public IEnumerable<SigerProjectTool> getlistToolByProject(int projectID)
        {
            return context.siger_project_tool.Where(f => f.projectid == projectID && f.status == (int)RowState.Valid);

        }
    }
}