using Elwig.Helpers;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;

namespace Elwig.Models.Entities {
    [Table("season"), PrimaryKey("Year")]
    public class Season {
        [Column("year")]
        public int Year { get; set; }

        [Column("currency")]
        public required string CurrencyCode { get; set; }

        [Column("precision")]
        public byte Precision { get; set; }

        [Column("max_kg_per_ha")]
        public int MaxKgPerHa { get; set; }

        [Column("vat_normal")]
        public double VatNormal { get; set; }

        [Column("vat_flatrate")]
        public double VatFlatrate { get; set; }

        [Column("min_kg_per_bs")]
        public int MinKgPerBusinessShare { get; set; }

        [Column("max_kg_per_bs")]
        public int MaxKgPerBusinessShare { get; set; }

        [Column("penalty_per_kg")]
        public long? PenaltyPerKgValue { get; set; }
        [NotMapped]
        public decimal? PenaltyPerKg {
            get => PenaltyPerKgValue != null ? DecFromDb(PenaltyPerKgValue.Value) : null;
            set => PenaltyPerKgValue = value != null ? DecToDb(value.Value) : null;
        }

        [Column("penalty_amount")]
        public long? PenaltyAmoutValue { get; set; }
        [NotMapped]
        public decimal? PenaltyAmount {
            get => PenaltyAmoutValue != null ? DecFromDb(PenaltyAmoutValue.Value) : null;
            set => PenaltyAmoutValue = value != null ? DecToDb(value.Value) : null;
        }

        [Column("penalty_none")]
        public long? PenaltyNoneValue { get; set; }
        [NotMapped]
        public decimal? PenaltyNone {
            get => PenaltyNoneValue != null ? DecFromDb(PenaltyNoneValue.Value) : null;
            set => PenaltyNoneValue = value != null ? DecToDb(value.Value) : null;
        }

        [Column("penalty_per_bs_amount")]
        public long? PenaltyPerBsAmountValue { get; set; }
        [NotMapped]
        public decimal? PenaltyPerBsAmount {
            get => PenaltyPerBsAmountValue != null ? DecFromDb(PenaltyPerBsAmountValue.Value) : null;
            set => PenaltyPerBsAmountValue = value != null ? DecToDb(value.Value) : null;
        }

        [Column("penalty_per_bs_none")]
        public long? PenaltyPerBsNoneValue { get; set; }
        [NotMapped]
        public decimal? PenaltyPerBsNone {
            get => PenaltyPerBsNoneValue != null ? DecFromDb(PenaltyPerBsNoneValue.Value) : null;
            set => PenaltyPerBsNoneValue = value != null ? DecToDb(value.Value) : null;
        }

        [Column("bs_value")]
        public long? BusinessShareValueValue { get; set; }
        [NotMapped]
        public decimal? BusinessShareValue {
            get => BusinessShareValueValue != null ? DecFromDb(BusinessShareValueValue.Value) : null;
            set => BusinessShareValueValue = value != null ? DecToDb(value.Value) : null;
        }

        [Column("start_date")]
        public string? StartDateString { get; set; }
        [NotMapped]
        public DateOnly? StartDate {
            get => StartDateString != null ? DateOnly.ParseExact(StartDateString, "yyyy-MM-dd") : null;
            set => StartDateString = value?.ToString("yyyy-MM-dd");
        }

        [Column("end_date")]
        public string? EndDateString { get; set; }
        [NotMapped]
        public DateOnly? EndDate {
            get => EndDateString != null ? DateOnly.ParseExact(EndDateString, "yyyy-MM-dd") : null;
            set => EndDateString = value?.ToString("yyyy-MM-dd");
        }

        [Column("calc_mode")]
        public int CalcMode { get; set; }
        [NotMapped]
        public bool Billing_HonorGebunden {
            get => (CalcMode & 0x1) != 0;
            set => CalcMode = value ? CalcMode | 0x1 : CalcMode & ~0x1;
        }
        [NotMapped]
        public bool Billing_AllowAttrsIntoLower {
            get => (CalcMode & 0x4) != 0;
            set => CalcMode = value ? CalcMode | 0x4 : CalcMode & ~0x4;
        }
        [NotMapped]
        public bool Billing_AvoidUnderDeliveries {
            get => (CalcMode & 0x2) != 0;
            set => CalcMode = value ? CalcMode | 0x2 : CalcMode & ~0x2;
        }

        [ForeignKey("CurrencyCode")]
        public virtual Currency Currency { get; private set; } = null!;

        [InverseProperty(nameof(Modifier.Season))]
        public virtual ICollection<Modifier> Modifiers { get; private set; } = null!;

        [InverseProperty(nameof(PaymentVar.Season))]
        public virtual ICollection<PaymentVar> PaymentVariants { get; private set; } = null!;

        [InverseProperty(nameof(Delivery.Season))]
        public virtual ICollection<Delivery> Deliveries { get; private set; } = null!;

        public decimal DecFromDb(long value) {
            return Utils.DecFromDb(value, Precision);
        }

        public long DecToDb(decimal value) {
            return Utils.DecToDb(value, Precision);
        }
    }
}