using System;

namespace Modeles
{
    /// <summary>
    /// Compte bancaire simple avec des opérations de dépôt, retrait et transfert.
    /// </summary>
    public class CompteBancaire
    {
        /// <summary>
        /// Liste contenant l'historique des transactions effectuées sur le compte bancaire. 
        /// Chaque entrée doit être du format:
        /// <Date> | <Opération> | <Montant> | Solde: <SoldeAprèsTransaction>
        /// </summary>
        public List<string> HistoriqueTransactions { get; } = new List<string>();

        /// <summary>
        /// Retourne le nombre total de transactions effectuées sur le compte bancaire, basé sur l'historique des transactions.
        /// </summary>
        public int NbTransactions
        {
            get
            {
                return HistoriqueTransactions.Count;
            }
        }

        /// <summary>
        /// Solde du compte bancaire. Ne peut pas être négatif. 
        /// Doit être modifié uniquement via les méthodes de dépôt, retrait et transfert.
        /// </summary>
        public decimal Solde { get; private set; }

        /// <summary>
        /// Constructeur du compte bancaire. Permet de définir un solde initial, qui doit être positif ou nul.
        /// </summary>
        /// <param name="pSoldeInitial">Solde initial du compte. Zéro par défaut.</param>
        /// <exception cref="ArgumentOutOfRangeException">Le solde initial ne peut pas être négatif.</exception>
        public CompteBancaire(decimal pSoldeInitial = 0m)
        {
            if (pSoldeInitial < 0m)
                throw new ArgumentOutOfRangeException(nameof(pSoldeInitial), "Le solde initial ne peut pas être négatif.");

            Solde = pSoldeInitial;
        }

        /// <summary>
        /// Dépose un montant sur le compte bancaire. Le montant doit être strictement positif.
        /// </summary>
        /// <param name="pMontant">Le montant déposé.</param>
        /// <param name="pDateDepot">La date de dépôt</param>
        /// <exception cref="ArgumentOutOfRangeException">Le montant du dépôt doit être strictement positif.</exception>
        public void Depot(decimal pMontant, DateTime pDateDepot)
        {
            if (pMontant <= 0m)
                throw new ArgumentOutOfRangeException(nameof(pMontant), "Le montant du dépôt doit être strictement positif.");

            Solde += pMontant;
            // Enregistre la transaction dans l'historique
            HistoriqueTransactions.Add($"{pDateDepot:yyyy-MM-dd HH:mm:ss} | Dépôt | {pMontant} | Solde: {Solde}");
        }

        /// <summary>
        /// Retire un montant du compte bancaire. Le montant doit être strictement positif et ne pas dépasser
        /// </summary>
        /// <param name="pMontant">Le montant retiré.</param>
        /// <param name="pDateRetrait">La date de retrait</param>
        /// <exception cref="ArgumentOutOfRangeException">Le montant du retrait doit être strictement positif.</exception>
        /// <exception cref="InvalidOperationException">Fonds insuffisants.</exception>
        public void Retrait(decimal pMontant, DateTime pDateRetrait)
        {
            if (pMontant <= 0m)
                throw new ArgumentOutOfRangeException(nameof(pMontant), "Le montant du retrait doit être strictement positif.");

            if (pMontant > Solde)
                throw new InvalidOperationException("Fonds insuffisants.");

            Solde -= pMontant;
            // Enregistre la transaction dans l'historique
            HistoriqueTransactions.Add($"{pDateRetrait:yyyy-MM-dd HH:mm:ss} | Retrait | {pMontant} | Solde: {Solde}");
        }

        /// <summary>
        /// Transfère un montant du compte bancaire vers un autre compte destination. Le montant doit être strictement positif et ne pas dépasser
        /// </summary>
        /// <param name="pDestination">Le compte destination du transfert.</param>
        /// <param name="pMontant">Le montant à transférer.</param>
        /// <param name="pDateTRabsfert">La date du transfert</param>
        /// <exception cref="ArgumentNullException">Le compte destination ne peut pas être null.</exception>
        public void TransfertVers(CompteBancaire pDestination, decimal pMontant, DateTime pDateTRabsfert)
        {
            if (pDestination is null)
                throw new ArgumentNullException(nameof(pDestination));

            // Réutilise la logique existante pour lever les mêmes exceptions
            Retrait(pMontant, pDateTRabsfert);
            pDestination.Depot(pMontant, pDateTRabsfert);
            // Enregistre la transaction dans l'historique
            HistoriqueTransactions.Add($"{pDateTRabsfert:yyyy-MM-dd HH:mm:ss} | Transfert | {pMontant} | Solde: {Solde}");
        }


    }
}
