using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace Fast.Models;

public class SosItem
{
    [Display(Name = "Supply CP", Description = "100")] public string SupplyCounterparty { get; set; } = "";
    [Display(Name = "Ownership", Description = "100")] public string Ownership { get; set; } = "";
    [Display(Name = "Source Meter", Description = "100")] public string SourceMeter { get; set; } = "";
    [Display(Name = "Receipt Meter", Description = "100")] public string ReceiptMeter { get; set; } = "";
    [Display(Name = "Receipt Point", Description = "100")] public string ReceiptPoint { get; set; } = "";
    [Display(Name = "PTR Contract", Description = "100")] public int? PtrContractId { get; set; }
    [Display(Name = "Supply Ticket", Description = "100")] public string SupplyTicket { get; set; } = "";
    [Display(Name = "Source Ticket", Description = "100")] public string SourceTicket { get; set; } = "";
    [Display(Name = "Activity #", Description = "100")] public string ActivityNum { get; set; } = "";
    [Display(Name = "Notes", Description = "100")] public string Notes { get; set; } = "";
    [Display(Name = "Source Notes", Description = "100")] public string SourceNotes { get; set; } = "";
    [Display(Name = "Deal Volume", Description = "100")] public double DealVolume { get; set; }
    [NotMapped][Display(Name = "Unsch'd Volume", Description = "100")] public double UnscheduledVolume { get; set; }
    [NotMapped][Display(Name = "Total Receipt Volume", Description = "100")] public double TotalReceiptVol { get; set; }
    [NotMapped][Display(Name = "Nom Receipt Volume", Description = "100")] public double NomReceiptVol { get; set; }
    [NotMapped][Display(Name = "Ptr Receipt Volume", Description = "100")] public double PtrReceiptVol { get; set; }
    [NotMapped][Display(Name = "Nom Fuel %", Description = "100")] public double NomFuelPercent { get; set; }
    [NotMapped][Display(Name = "Nom Fuel Amount", Description = "100")] public double NomFuelAmount { get; set; }
    [NotMapped][Display(Name = "PTR Fuel %", Description = "100")] public double PtrFuelPercent { get; set; }
    [NotMapped][Display(Name = "PTR Fuel Amount", Description = "100")] public double PtrFuelAmount { get; set; }
    [Display(Name = "PTR %", Description = "100")] public double? PtrPercent { get; set; }
    [NotMapped][Display(Name = "PTR Amount", Description = "100")] public double PtrAmount { get; set; }
    [NotMapped][Display(Name = "Del. Volume Market Deal Vol", Description = "100")] public double DeliveryVol { get; set; }
    [NotMapped][Display(Name = "Cumulative Receipt Volume", Description = "100")] public double CumReceiptVol { get; set; }
    [Display(Name = "P/L Contract", Description = "100")] public int? PipeContractId { get; set; }
    [Display(Name = "Deal Type", Description = "100")] public string DealType { get; set; } = "";
    [Display(Name = "Delivery Point", Description = "100")] public string DeliveryPoint { get; set; } = "";
    [Display(Name = "PTR Delivery Meter", Description = "100")] public int? PtrDeliveryMeterId { get; set; }
    [NotMapped] public int? TransferSumVol { get; set; }
    [NotMapped] public List<SosNom> Noms { get; set; } = new();
    [NotMapped] public HashSet<string> ModifiedProps { get; set; } = new();
    [NotMapped] public string Guid { get; set; } = System.Guid.NewGuid().ToString("N")[..8];
    [NotMapped] public double OtherUnscheduledVol { get; set; }
    [NotMapped] public double OtherCumReceiptVol { get; set; }
    public int? SupplyNomId { get; set; }
    public int? DealId { get; set; }
    public int? ReceiptPointId { get; set; }
    public int? ReceiptMeterId { get; set; }
    public int? TransferDealId { get; set; }
    public int? SourceMeterId { get; set; }
    [NotMapped] public List<int> SourceMeterIds { get; set; } = new();
    public int? SupplyCounterpartyId { get; set; }
    [NotMapped] public bool IsManualPtr { get; set; }
    public double? SourceDealVolume { get; set; }
    public bool IsEnteredFromSos { get; set; }
    public bool IsHidden { get; set; }
    public bool IsTransferToTransfer { get; set; }
    [NotMapped] public bool IsSupplyClone { get; set; }
    public DateTime? CreatedTime { get; set; }
    public DateTime? SavedTime { get; set; }
    public int? SourceDealProduct { get; set; }

    public bool HasSupplyChanges()
    {
        var hasChanges = this.ModifiedProps.Count > 0;
        return hasChanges;
    }

    public bool HasNomChanges()
    {
        var hasChanges = Noms.Any(n => n.IsModified);
        return hasChanges;
    }

    public override string ToString()
    {
        return $"SupplyCounterparty: {SupplyCounterparty}, Ownership: {Ownership}, SourceMeter: {SourceMeter}, ReceiptMeter: {ReceiptMeter}, " +
               $"ReceiptPoint: {ReceiptPoint}, PtrContractId: {PtrContractId}, SupplyTicket: {SupplyTicket}, SourceTicket: {SourceTicket}, " +
               $"ActivityNum: {ActivityNum}, Notes: {Notes}, SourceNotes: {SourceNotes}, DealVolume: {DealVolume}, UnscheduledVolume: {UnscheduledVolume}, " +
               $"TotalReceiptVol: {TotalReceiptVol}, NomReceiptVol: {NomReceiptVol}, PtrReceiptVol: {PtrReceiptVol}, NomFuelPercent: {NomFuelPercent}, " +
               $"NomFuelAmount: {NomFuelAmount}, PtrFuelPercent: {PtrFuelPercent}, PtrFuelAmount: {PtrFuelAmount}, PtrPercent: {PtrPercent}, " +
               $"PtrAmount: {PtrAmount}, DeliveryVol: {DeliveryVol}, CumReceiptVol: {CumReceiptVol}, PipeContractId: {PipeContractId}, DealType: {DealType}, " +
               $"DeliveryPoint: {DeliveryPoint}, PtrDeliveryMeterId: {PtrDeliveryMeterId}, TransferSumVol: {TransferSumVol}, Noms: {string.Join(", ", Noms)}, " +
               $"ModifiedProps: {string.Join(", ", ModifiedProps)}, Guid: {Guid}, OtherUnscheduledVol: {OtherUnscheduledVol}, OtherCumReceiptVol: {OtherCumReceiptVol}, " +
               $"SupplyNomId: {SupplyNomId}, DealId: {DealId}, ReceiptPointId: {ReceiptPointId}, ReceiptMeterId: {ReceiptMeterId}, TransferDealId: {TransferDealId}, " +
               $"SourceMeterId: {SourceMeterId}, SourceMeterIds: {string.Join(", ", SourceMeterIds)}, SupplyCounterpartyId: {SupplyCounterpartyId}, IsManualPtr: {IsManualPtr}, " +
               $"SourceDealVolume: {SourceDealVolume}, IsEnteredFromSos: {IsEnteredFromSos}, IsHidden: {IsHidden}, IsTransferToTransfer: {IsTransferToTransfer}, " +
               $"IsSupplyClone: {IsSupplyClone}, CreatedTime: {CreatedTime}, SavedTime: {SavedTime}, SourceDealProduct: {SourceDealProduct}";
    }

    public override bool Equals(object? obj)
    {
        if (obj == null || GetType() != obj.GetType())
            return false;

        var other = (SosItem)obj;
        return SupplyCounterparty == other.SupplyCounterparty
            && Ownership == other.Ownership
            && SourceMeter == other.SourceMeter
            && ReceiptMeter == other.ReceiptMeter
            && ReceiptPoint == other.ReceiptPoint
            && PtrContractId == other.PtrContractId
            && SupplyTicket == other.SupplyTicket
            && SourceTicket == other.SourceTicket
            && ActivityNum == other.ActivityNum
            && Notes == other.Notes
            && SourceNotes == other.SourceNotes
            && DealVolume == other.DealVolume
            && UnscheduledVolume == other.UnscheduledVolume
            && TotalReceiptVol == other.TotalReceiptVol
            && NomReceiptVol == other.NomReceiptVol
            && PtrReceiptVol == other.PtrReceiptVol
            && NomFuelPercent == other.NomFuelPercent
            && NomFuelAmount == other.NomFuelAmount
            && PtrFuelPercent == other.PtrFuelPercent
            && PtrFuelAmount == other.PtrFuelAmount
            && PtrPercent == other.PtrPercent
            && PtrAmount == other.PtrAmount
            && DeliveryVol == other.DeliveryVol
            && CumReceiptVol == other.CumReceiptVol
            && PipeContractId == other.PipeContractId
            && DealType == other.DealType
            && DeliveryPoint == other.DeliveryPoint
            && PtrDeliveryMeterId == other.PtrDeliveryMeterId
            && TransferSumVol == other.TransferSumVol
            && Noms.SequenceEqual(other.Noms)
            && ModifiedProps.SetEquals(other.ModifiedProps)
            // && Guid == other.Guid // Exclude Guid from comparison
            && OtherUnscheduledVol == other.OtherUnscheduledVol
            && OtherCumReceiptVol == other.OtherCumReceiptVol
            && SupplyNomId == other.SupplyNomId
            && DealId == other.DealId
            && ReceiptPointId == other.ReceiptPointId
            && ReceiptMeterId == other.ReceiptMeterId
            && TransferDealId == other.TransferDealId
            && SourceMeterId == other.SourceMeterId
            && SourceMeterIds.SequenceEqual(other.SourceMeterIds)
            && SupplyCounterpartyId == other.SupplyCounterpartyId
            && IsManualPtr == other.IsManualPtr
            && SourceDealVolume == other.SourceDealVolume
            && IsEnteredFromSos == other.IsEnteredFromSos
            && IsHidden == other.IsHidden
            && IsTransferToTransfer == other.IsTransferToTransfer
            && IsSupplyClone == other.IsSupplyClone
            && CreatedTime == other.CreatedTime
            && SavedTime == other.SavedTime
            && SourceDealProduct == other.SourceDealProduct;
    }

    public override int GetHashCode()
    {
        return HashCode.Combine(
            HashCode.Combine(SupplyCounterparty, Ownership, SourceMeter, ReceiptMeter, ReceiptPoint, PtrContractId, SupplyTicket, SourceTicket),
            HashCode.Combine(ActivityNum, Notes, SourceNotes, DealVolume, UnscheduledVolume, TotalReceiptVol, NomReceiptVol, PtrReceiptVol),
            HashCode.Combine(NomFuelPercent, NomFuelAmount, PtrFuelPercent, PtrFuelAmount, PtrPercent, PtrAmount, DeliveryVol, CumReceiptVol),
            HashCode.Combine(PipeContractId, DealType, DeliveryPoint, PtrDeliveryMeterId, TransferSumVol, Noms, ModifiedProps, OtherUnscheduledVol),
            // Guid, // Exclude Guid from hash code calculation
            HashCode.Combine(OtherCumReceiptVol, SourceMeterIds, SupplyCounterpartyId, IsManualPtr, SourceDealVolume, IsEnteredFromSos, IsHidden, IsTransferToTransfer),
            HashCode.Combine(IsSupplyClone, CreatedTime, SavedTime, SourceDealProduct)
        );
    }

}
