using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Domain.Entities.Members;

namespace Domain.Entities.Donations;

public class Donation
{
    [ForeignKey(nameof(SponsorMemberID))]
    public virtual Member? Sponsor { get; private set; }

    [ForeignKey(nameof(ReceiverMemberID))]
    public virtual Member? Receiver { get; private set; }

    [ForeignKey(nameof(ChannelID))]
    public virtual Channel? Channel { get; private set; }

    [ForeignKey(nameof(CrewSessionID))]
    public virtual CrewSession? CrewSession { get; private set; }

    [ForeignKey(nameof(CrewMemberID))]
    public virtual CrewMember? CrewMember { get; private set; }

    public virtual DonationAlert? DonationAlert { get; private set; }

    [Key]
    public int ID { get; private set; }

    public int SponsorMemberID { get; private set; }

    public int ReceiverMemberID { get; private set; }

    public int ChannelID { get; private set; }

    public int? CrewSessionID { get; private set; }

    public int? CrewMemberID { get; private set; }

    public int Amount { get; private set; }

    public decimal FeeRate { get; private set; }

    public int FeeAmount { get; private set; }

    public int NetAmount { get; private set; }

    public string? Message { get; private set; }

    public string SendName { get; private set; } = default!;

    public bool IsTest { get; private set; }

    public DateTime CreatedAt { get; private set; } = DateTime.UtcNow;

    private Donation() { }

    public static Donation Create(
        int sponsorMemberID,
        int receiverMemberID,
        int channelID,
        int amount,
        decimal feeRate,
        string? message,
        string sendName,
        int? crewSessionID = null,
        int? crewMemberID = null,
        bool isTest = false
    )
    {
        if (amount <= 0)
        {
            throw new ArgumentOutOfRangeException(nameof(amount));
        }

        if (feeRate < 0 || feeRate > 100)
        {
            throw new ArgumentOutOfRangeException(nameof(feeRate));
        }

        if (string.IsNullOrWhiteSpace(sendName))
        {
            throw new ArgumentException("SendName is required.", nameof(sendName));
        }

        var feeAmount = (int)Math.Floor(amount * feeRate / 100m);
        var netAmount = amount - feeAmount;

        return new Donation
        {
            SponsorMemberID = sponsorMemberID,
            ReceiverMemberID = receiverMemberID,
            ChannelID = channelID,
            Amount = amount,
            FeeRate = feeRate,
            FeeAmount = feeAmount,
            NetAmount = netAmount,
            Message = message,
            SendName = sendName,
            CrewSessionID = crewSessionID,
            CrewMemberID = crewMemberID,
            IsTest = isTest
        };
    }
}