using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Text;

using FMSAdmin.Data;
using FMSAdmin.Helpers;
using FMSAdmin.Entities;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using FMSAdmin.Models;

namespace FMSAdmin.Services {
    public class MaterialStoredService {
        private readonly ILogger<MaterialStoredService> _logger;
        private readonly FMSContext _context;
        private readonly StorageHelper _storage;

        public MaterialStoredService(
            ILogger<MaterialStoredService> logger,
            FMSContext context,
            StorageHelper storage) {
            _logger = logger;
            _context = context;
            _storage = storage;
        }

        public void Create(FmsMaterialStored data) {
            using (var transaction = _context.Database.BeginTransaction()) {
                foreach (var item in data.MaterialStoredList) {
                    FmsMaterialStored storedItem = new FmsMaterialStored() {
                        SiteId = data.SiteId,
                        BusinessFieldId = data.BusinessFieldId,
                        StoredUserId = data.StoredUserId,
                        StoredDate = DateTime.Now,
                        PurchaseOrderId = data.PurchaseOrderId,
                        WarehouseId = data.WarehouseId,
                        MaterialId = item.MaterialId,
                        StoredCount = item.StoredCount,
                        RemainStoredCount = item.StoredCount,   // 입고등록시 RemainStoredCount 에 입고수량 넣어야함 (출고시 RemainStoredCount 이용해서 출고함)
                        UnitCost = item.UnitCost,
                        StockCount = 0,
                        Note = data.Note,
                        IsApproval = false,
                        LocationInWarehouse = data.LocationInWarehouse,
                    };
                    storedItem.StoredUserId = data.StoredUserId;

                    //해당 material 의 최신 입고 정보
                    var lastStoredItem = _context.FmsMaterialStored.Where(x => x.SiteId == data.SiteId && x.MaterialId == item.MaterialId).OrderByDescending(x => x.MaterialStoredId).FirstOrDefault();
                    //재고정보 업데이트
                    if (lastStoredItem != null) {
                        storedItem.StockCount += (lastStoredItem.StockCount + item.StoredCount);
                    } else {
                        storedItem.StockCount = item.StoredCount;
                    }

                    //자동승인
                    if (_context.SiteConfig.Single().UseMaterialStoredAutoApproval) {
                        storedItem.ApprovalUserId = data.StoredUserId;
                        storedItem.ApprovalDate = DateTime.Now;
                        storedItem.IsApproval = true;
                    }
                    _context.FmsMaterialStored.Add(storedItem);
                }
                _context.SaveChanges();

                // 발주요청과 입고를 비교하여 모두 입고되었다면 상태 변경
                var storedMaterialList = _context.FmsMaterialStored.Where(x => x.SiteId == data.SiteId && x.PurchaseOrderId == data.PurchaseOrderId).ToList();
                var orderdMaterialList = _context.FmsMaterialPurchaseOrderMaterial.Where(x => x.SiteId == data.SiteId && x.PurchaseOrderId == data.PurchaseOrderId).ToList();

                bool bAllStored = false;
                foreach (var order in orderdMaterialList) {
                    int storedCount = storedMaterialList.Where(x => x.MaterialId == order.MaterialId).Sum(x => x.StoredCount);

                    if (order.MaterialCount > storedCount) {
                        bAllStored = false;
                        break;
                    } else {
                        bAllStored = true;
                    }
                }
                if (bAllStored) {
                    var requestId = _context.FmsMaterialPurchaseOrder.Where(x => x.SiteId == data.SiteId && x.PurchaseOrderId == data.PurchaseOrderId).Select(x => x.PurchaseRequestId).FirstOrDefault();
                    var materialRequiest = _context.FmsMaterialPurchaseRequest.Where(x => x.SiteId == data.SiteId && x.PurchaseRequestId == requestId).FirstOrDefault();
                    if (materialRequiest != null) {
                        if (_context.SiteConfig.Single().UseMaterialStoredAutoApproval) {
                            materialRequiest.ProgressId = 5;      //입고승인
                        } else {
                            materialRequiest.ProgressId = 4;      //자재입고
                        }
                        _context.FmsMaterialPurchaseRequest.Update(materialRequiest);
                        _context.SaveChanges();
                    }
                }

                transaction.Commit();
            }

        }

        public IQueryable<FmsMaterialStored> GetAll() {
            var query = _context.FmsMaterialStored/*.AsNoTracking()*/;
            return query;
        }

        public FmsMaterialStored Get(int id, int siteId) {
            var data = _context.FmsMaterialStored.Single(x => x.MaterialStoredId == id && x.SiteId == siteId);
            return data;
        }

        public IQueryable<FmsMaterialStored> Gets(int id, int siteId) {
            var data = _context.FmsMaterialStored.Where(x => x.MaterialStoredId == id && x.SiteId == siteId);
            return data;
        }

        public void Delete(int id, int siteId) {
            var data = _context.FmsMaterialStored.First(x => x.MaterialStoredId == id && x.SiteId == siteId);
            _context.FmsMaterialStored.Remove(data);
            _context.SaveChanges();
        }

        public void Approval(string userId, FmsMaterialStored data) {
            var persist = _context.FmsMaterialStored
                        .Where(x => x.MaterialStoredId == data.MaterialStoredId && x.SiteId == data.SiteId).FirstOrDefault();
            if (persist == null) {
                throw new ServiceException("정보를 찾을 수 없습니다.");
            }

            using (var transaction = _context.Database.BeginTransaction()) {
                var order = _context.FmsMaterialPurchaseOrder.Where(x => x.SiteId == persist.SiteId && x.BusinessFieldId == persist.BusinessFieldId && x.PurchaseOrderId == persist.PurchaseOrderId).FirstOrDefault();
                if (order != null) {
                    persist.ApprovalUserId = userId;
                    persist.ApprovalDate = DateTime.Now;
                    persist.IsApproval = true;
                }
                _context.FmsMaterialStored.Update(persist);

                // 발주요청과 입고를 비교하여 모두 입고되었다면 상태 변경
                bool bAllMaterialStored = false;
                foreach (var orderMaterial in order.FmsMaterialPurchaseOrderMaterial) {
                    var notApprovedItem = order.FmsMaterialStored.Where(x => x.SiteId == orderMaterial.SiteId && x.IsApproval == false).FirstOrDefault();
                    if (notApprovedItem != null) {
                        bAllMaterialStored = false;
                        break;
                    }

                    int storedCount = order.FmsMaterialStored.Where(x => x.SiteId == orderMaterial.SiteId && x.MaterialId == orderMaterial.MaterialId).Sum(x => x.StoredCount);
                    if (orderMaterial.MaterialCount > storedCount) {
                        bAllMaterialStored = false;
                        break;
                    } else {
                        bAllMaterialStored = true;
                    }
                }
                if (bAllMaterialStored) {
                    order.FmsMaterialPurchaseRequest.ProgressId = 5;    //입고승인
                    _context.FmsMaterialPurchaseOrder.Update(order);
                }
                _context.SaveChanges();

                transaction.Commit();
            }
        }

        public void ApprovalEach(int siteId, int id, string userId) {
            var persist = _context.FmsMaterialStored.Where(x => x.MaterialStoredId == id && x.SiteId == siteId).FirstOrDefault();
            if (persist == null) {
                throw new ServiceException("정보를 찾을 수 없습니다.");
            }

            Approval(userId, persist);
        }
    }
}