using System;
using System.Linq;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Newtonsoft.Json;
using System.Linq.Expressions;

namespace FMSAdmin.Entities {
    public partial class FmsMaterial {
        public FmsMaterial() {
            FmsMaterialPurchaseOrderMaterial = new HashSet<FmsMaterialPurchaseOrderMaterial>();
            FmsMaterialPurchaseRequestMaterial = new HashSet<FmsMaterialPurchaseRequestMaterial>();
            FmsMaterialRelease = new HashSet<FmsMaterialRelease>();
            FmsMaterialStored = new HashSet<FmsMaterialStored>();
            FmsWorkResultCheckItemMaterial = new HashSet<FmsWorkResultCheckItemMaterial>();
        }

        [Display(Name = "고유번호"), Key]
        public int SiteId { get; set; }

        public int MaterialId { get; set; }
        [Display(Name = "업무분야")]
        public int BusinessFieldId { get; set; }
        [Display(Name = "자재 코드"), Required]
        [StringLength(48, ErrorMessage = "자재코드는 최대 48자까지 입력 가능합니다.")]
        public string MaterialCode { get; set; }
        [Display(Name = "자재 이름"), Required]
        [StringLength(48, ErrorMessage = "자재명은 최대 48자까지 입력 가능합니다.")]
        public string Name { get; set; }
        [Display(Name = "자재분류 대")]
        public int? FirstClassId { get; set; }
        [Display(Name = "자재분류 중")]
        public int? SecondClassId { get; set; }
        [Display(Name = "자재분류 소")]
        public int? ThirdClassId { get; set; }
        [Display(Name = "자재 위치")]
        public int? LocationId { get; set; }
        [Display(Name = "자재 타입")]
        public int? MaterialTypeId { get; set; }
        [Display(Name = "자재창고")]
        public int? WarehouseId { get; set; }
        [Display(Name = "공급업체")]
        public int? TradeCompanyId { get; set; }
        [Display(Name = "QR코드")]
        [StringLength(52, ErrorMessage = "QR코드는 최대 52자까지 입력 가능합니다.")]
        public string Rfid { get; set; }
        [Display(Name = "단위")]
        [StringLength(12, ErrorMessage = "단위는 최대 12자까지 입력 가능합니다.")]
        public string Unit { get; set; }
        [Display(Name = "내용 연수")]
        public short? DurableYears { get; set; }
        [Display(Name = "적정 재고량")]
        public short? ReasonableStockCount { get; set; }
        [Display(Name = "제조사")]
        [StringLength(40, ErrorMessage = "제조사명은 최대 40자까지 입력 가능합니다.")]
        public string Manufacturer { get; set; }
        [Display(Name = "규격")]
        [StringLength(20, ErrorMessage = "규격은 최대 20자까지 입력 가능합니다.")]
        public string Standard { get; set; }
        [Display(Name = "단가")]
        public int? FinalPrice { get; set; }
        [Display(Name = "파일 ID")]
        public int? ImageFileId { get; set; }
        [Display(Name = "비고")]
        [StringLength(512, ErrorMessage = "비고는 최대 512자까지 입력 가능합니다.")]
        public string Note { get; set; }
        [Display(Name = "단종 여부")]
        public bool? IsDiscontinued { get; set; }
        [Display(Name = "사용 유무"), Required]
        public bool IsUse { get; set; }
        [Display(Name = "재고 수량"), Required]
        public int FinalStockCount { get; set; }
        [Display(Name = "재고 금액"), Required]
        public int FinalTotalStockAmount { get; set; }

        [NotMapped]
        [Display(Name = "엑셀행번호")]
        public int ExcelRowNum { get; set; }

        [ForeignKey("SiteId")]
        public virtual CmSite CmSite { get; set; }

        [ForeignKey("BusinessFieldId")]
        public virtual CmBusinessField CmBusinessField { get; set; }
        [ForeignKey("SiteId,ImageFileId")]
        public virtual CmFile CmFile { get; set; }

        [ForeignKey("FirstClassId")]
        public virtual FmsMaterialCodeClass FmsMaterialCodeClass { get; set; }
        [ForeignKey("SecondClassId")]
        public virtual FmsMaterialCodeClass FmsMaterialCodeClass1 { get; set; }
        [ForeignKey("ThirdClassId")]
        public virtual FmsMaterialCodeClass FmsMaterialCodeClass2 { get; set; }

        [ForeignKey("SiteId,LocationId")]
        public virtual FmsMaterialCodeLocation FmsMaterialCodeLocation { get; set; }
        [ForeignKey("MaterialTypeId")]
        public virtual FmsMaterialCodeType FmsMaterialCodeType { get; set; }
        [ForeignKey("SiteId,TradeCompanyId")]
        public virtual FmsMaterialTradeCompany FmsMaterialTradeCompany { get; set; }
        [ForeignKey("SiteId,WarehouseId")]
        public virtual FmsMaterialWarehouse FmsMaterialWarehouse { get; set; }

        [JsonIgnore]
        [InverseProperty("FmsMaterial")]
        public virtual ICollection<FmsMaterialPurchaseOrderMaterial> FmsMaterialPurchaseOrderMaterial { get; set; }
        [JsonIgnore]
        [InverseProperty("FmsMaterial")]
        public virtual ICollection<FmsMaterialPurchaseRequestMaterial> FmsMaterialPurchaseRequestMaterial { get; set; }
        [JsonIgnore]
        [InverseProperty("FmsMaterial")]
        public virtual ICollection<FmsMaterialRelease> FmsMaterialRelease { get; set; }
        [JsonIgnore]
        [InverseProperty("FmsMaterial")]
        public virtual ICollection<FmsMaterialStored> FmsMaterialStored { get; set; }
        [JsonIgnore]
        [InverseProperty("FmsMaterial")]
        public virtual ICollection<FmsWorkResultCheckItemMaterial> FmsWorkResultCheckItemMaterial { get; set; }

        // LinKit 관련 표현식
        internal object AsExpandable() {
            throw new NotImplementedException();
        }
        public static Expression<Func<FmsMaterial, long>> GetStockCount =
            // (x) => x.FmsMaterialStored.Where(s => s.IsApproval == true).OrderByDescending(s => s.MaterialStoredId).FirstOrDefault().StockCount    // or .Sum(x => (long)x.StoredCount) /* 이게 맞을듯 하다... */
            (x) => x.FmsMaterialStored.Where(s => s.IsApproval == true).Sum(s => (long)s.StoredCount)
                + (x.FmsMaterialRelease.Where(r => r.IsConfirmed == true && r.AdjustmentTypeId == 2).Sum(r => (long?)r.MaterialCount) ?? 0)
                - (x.FmsMaterialRelease.Where(r => r.IsConfirmed == true && r.AdjustmentTypeId == 1).Sum(r => (long?)r.MaterialCount) ?? 0)
                - (x.FmsMaterialRelease.Where(r => r.IsConfirmed == true && r.AdjustmentTypeId == 0).Sum(r => (long?)r.MaterialCount) ?? 0);

        public static Expression<Func<FmsMaterial, long>> GetStockAmount =
            (x) => (x.FmsMaterialStored.Where(s => s.IsApproval == true).Sum(s => (long?)(s.StoredCount * s.UnitCost)) ?? 0)
                + (x.FmsMaterialRelease.Where(r => r.IsConfirmed == true && r.AdjustmentTypeId == 2).Sum(r => (long?)r.ReleaseTotalCost) ?? 0)
                - (x.FmsMaterialRelease.Where(r => r.IsConfirmed == true && r.AdjustmentTypeId == 1).Sum(r => (long?)r.ReleaseTotalCost) ?? 0)
                - (x.FmsMaterialRelease.Where(r => r.IsConfirmed == true && r.AdjustmentTypeId == 0).Sum(r => (long?)r.ReleaseTotalCost) ?? 0);

    }
}
