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.AccRepository.Response;
using Siger.Middlelayer.Common;
using Siger.Middlelayer.Common.Extensions;
using Siger.Middlelayer.Log;
using Siger.Middlelayer.Repository.Data.Acc;
using Siger.Middlelayer.Repository.Extensions;
using Siger.Middlelayer.Repository.Paged;
using Siger.Middlelayer.Utility.ImportEntities;

namespace Siger.Middlelayer.AccRepository.Repositories
{
    internal class AutomationLocationRepository : AccRepositoryBase<siger_automation_location>, IAutomationLocationRepository
    {
        private ApiAccDbContext _context;
        public AutomationLocationRepository(ApiAccDbContext context) : base(context)
        {
            _context = context;
        }

        public IPagedCollectionResult<ResponseAutomationLocation> GetPagedList(int wavehouseid, IEnumerable<int> locationid, int projectid, int page, int pagesize, string toexcel)
        {
            var query = from q in _context.siger_automation_location
                        join t in _context.siger_automation_fixture_tools on q.fixturetools equals t.guid
                        join c in _context.siger_automation_fixture_tools_category on t.category equals c.guid
                        join l in _context.siger_wms_storage_location on q.location_cid equals l.id
                        join w in _context.siger_wms_storage on l.storageid equals w.id
                        join u in _context.siger_project_user on q.updator equals u.mid into uu
                        from u in uu.DefaultIfEmpty()
                        join r in _context.siger_project_beat_set on q.routeid equals r.id into rr
                        from r in rr.DefaultIfEmpty()
                        where q.projectId == projectid && q.status == (int)RowState.Valid
                        select new ResponseAutomationLocation
                        {
                            id = q.id,
                            locationid = l.id,
                            locaid = q.locationid,
                            location = l.name,
                            wavehouseid = w.id,
                            wavehouse = w.name,
                            fixturetoolid = t.id,
                            fixturetool = t.name,
                            category = c.name,
                            code = t.code,
                            specfication = t.specification,
                            fileurl = q.attachment ?? "",
                            filename = q.filename ?? "",
                            remark = q.remark,
                            updator = u.name ?? "",
                            status = q.status,
                            updatetime = q.updatetime.HasValue && q.updatetime > DateTime.MinValue ? q.updatetime.Value.ToString(ParameterConstant.DateTimeFormat) : "",
                            sn = q.sn ?? "",
                            route = r.route_name ?? "",
                            routenumber = r == null ? "" : r.route_number.ToString(),
                            cate_guid = c.guid ?? "",
                            categoryId = c == null ? 0 : c.id
                        };
            Expression<Func<ResponseAutomationLocation, bool>> wavehouseidExpression = f => true;
            if (wavehouseid > 0)
            {
                wavehouseidExpression = q => q.wavehouseid == wavehouseid;
            }
            Expression<Func<ResponseAutomationLocation, bool>> locationidExpression = f => true;
            if (locationid.Any())
            {
                locationidExpression = q => locationid.Contains(q.locationid);
            }
            var expression = wavehouseidExpression.And(locationidExpression);
            if(toexcel.ToInt() == 1)
            {
                var entities = query.Where(expression).OrderByDescending(q => q.id).AsNoTracking().ToList();
                return new PagedCollectionResult<ResponseAutomationLocation>(entities, entities.Count);
            }
            else
            {
                var entities = query.Where(expression).OrderByDescending(q => q.id).Skip((page - 1) * pagesize).Take(pagesize).AsNoTracking().ToList();
                var totalCount = query.Where(expression).Count();
                return new PagedCollectionResult<ResponseAutomationLocation>(entities, totalCount);
            }
        }

        public siger_wms_storage_location GetLocation(int id, int projectid)
        {
            return _context.siger_wms_storage_location.FirstOrDefault(q => q.id == id && q.projectId == projectid && q.status == (int)RowState.Valid);
        }

        public IEnumerable<siger_wms_storage_location> GetLocationList(int projectid)
        {
            return _context.siger_wms_storage_location.Where(q => q.projectId == projectid && q.status == (int)RowState.Valid);
        }

        public IEnumerable<ResponseAutomationLocationList> GetDataList(int projectid)
        {
            var query = from q in _context.siger_automation_location
                        join t in _context.siger_automation_fixture_tools on q.fixturetools equals t.guid
                        join c in _context.siger_automation_fixture_tools_category on t.category equals c.guid
                        join l in _context.siger_wms_storage_location on q.location_cid equals l.id
                        join w in _context.siger_wms_storage on l.storageid equals w.id
                        where q.projectId == projectid && q.status == (int)RowState.Valid
                        select new ResponseAutomationLocationList
                        {
                            id = q.id,
                            fixtureguid = t.guid,
                            locationid = l.locationid,
                            location = l.realname,
                            locationcode = l.serial_number,
                            wavehouseid = w.id,
                            wavehouse = w.name,
                            wavehousecode = w.serial_number,
                            fixturetoolid = t.id,
                            code = t.code,
                            name = t.name,
                            materialsn = q.sn ?? "",
                            categoryid = c == null ? 0 : c.id
                        };
            var entities = query.AsNoTracking().ToList();
            return entities;
        }

        public CommonImportResult ImportData(IEnumerable<AutomationLocationTemplate> list, int projectid, int userid)
        {
            var errors = new List<string>();
            var rowIndex = 1;

            var entities = new List<siger_automation_location>();
            foreach (var item in list)
            {
                rowIndex++;

                if (string.IsNullOrEmpty(item.LocationId) || string.IsNullOrEmpty(item.FixtureTool))
                {
                    errors.Add($"{rowIndex},{(int)RequestEnum.ParameterMiss}");
                }
                var fixturetool = _context.siger_automation_fixture_tools.FirstOrDefault(q => q.code == item.FixtureTool && q.projectId == projectid);
                if (fixturetool == null)
                {
                    errors.Add($"{rowIndex},{(int)RequestEnum.FixtureToolNotFound}");
                }
                var warehouse = _context.siger_wms_storage.FirstOrDefault(q => q.status == (int)RowState.Valid && q.projectId == projectid && q.name == item.Warehouse);
                if(warehouse == null)
                {
                    errors.Add($"{rowIndex},{(int)RequestEnum.WaveHouseIDNotExist}");
                }
                var location = _context.siger_wms_storage_location.FirstOrDefault(q => q.locationid == item.LocationId.ToInt() && q.storageid == warehouse.id && q.projectId == projectid && q.status == (int)RowState.Valid);
                if (location == null || item.LocationId.ToInt() <= 0)
                {
                    errors.Add($"{rowIndex},{(int)RequestEnum.LocationNull}");
                }
                var exsit = _context.siger_automation_location.FirstOrDefault(q => q.projectId == projectid && q.status == (int)RowState.Valid &&
                    (q.fixturetools == fixturetool.guid || q.locationid == item.LocationId.ToInt()));
                if (exsit != null)
                {
                    errors.Add($"{rowIndex},{(int)RequestEnum.DataExist}");
                }
                if (list.Count(q => q.FixtureTool == item.FixtureTool || q.LocationId == item.LocationId) > 1)
                {
                    errors.Add($"{rowIndex},{(int)RequestEnum.DataExist}");
                }

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

                var entity = new siger_automation_location
                {
                    guid = Guid.NewGuid().ToString(),
                    locationid = location.id,
                    fixturetools = fixturetool.guid,
                    attachment = "",
                    filename = "",
                    remark = item.Remark,
                    projectId = projectid,
                    updatetime = DateTime.Now,
                    updator = userid,
                };
                entities.Add(entity);
            }

            try
            {
                _context.siger_automation_location.AddRange(entities);
                _context.SaveChanges();
                return new CommonImportResult(1, "1");
            }
            catch (Exception e)
            {
                Logger.WriteLineError(e.Message);
                throw;
            }            
        }
    }
}
