Scripts/Managers/InvestmentManager.cs
using System;
using Milaine.Interfaces;

namespace Milaine.Managers;

public struct Portfolio(int wallet = 0, float investment = 0, float profit = 0, int shares = 0) {
  public int wallet = wallet;
  public float investment = investment;
  public float profit = profit;
  public int shares = shares;
}

public sealed class InvestmentManager : Component, IManager {
  public const float DEFAULT_PERFORMANCE = 1.0f;

  [Property, Title("DayNightManager")]
  [Feature("Managers")]
  public DayNightManager DayNightManagerInstance { get; set; }

  [Property]
  [Feature("General")]
  public bool IsDayEnded { get; set; } = false;

  [Property]
  [Feature("General"), Group("Digital")]
  public int Wallet { get; set; } = 0;

  [Property]
  [Feature("General"), Group("Digital")]
  public float Investment { get; set; } = 0;

  [Property]
  [Feature("General"), Group("Digital")]
  public float Profit { get; set; } = 0;

  [Property]
  [Feature("General"), Group("Digital")]
  public int Shares { get; set; } = 0;

  public Action<Portfolio> OnChange { get; set; }

  private float performance = DEFAULT_PERFORMANCE;
  private float acc = 0f;
  private float multiplierDeposit = 1.0f;
  private bool isAvailablePerformanceWallet = false;
  private int performanceWallet = (int)DEFAULT_PERFORMANCE;

  private float accDividends = 0f;
  private bool isActivatedDividends = false;
  private float multiplierDividends = 0.0f;

  private int walletPasive = 0;

  public float Total {
    get => Wallet + Investment;
  }


  public int WalletPasive {
    get => walletPasive;
  }

  protected override void OnStart() {
    DayNightManagerInstance.OnStartDay += DayStartSubscription;
    DayNightManagerInstance.OnEndDay += DayNightSubscription;
  }

  protected override void OnDestroy() {
    DayNightManagerInstance.OnStartDay -= DayStartSubscription;
    DayNightManagerInstance.OnEndDay -= DayNightSubscription;
  }

  protected override void OnUpdate() {
    if (IsDayEnded) {
      return;
    }

    acc += Time.Delta;

    if (acc >= 1.0f) {
      if (Investment != 0f) {
        Profit += performance;
        Investment += performance;
      }

      if (isAvailablePerformanceWallet) {
        Wallet += performanceWallet;
        walletPasive += performanceWallet;
      }


      acc = 0;
    }

    accDividends += Time.Delta;

    if (accDividends >= 5.0f && isActivatedDividends) {
      Wallet += (Investment * multiplierDividends).CeilToInt();
      accDividends = 0;
    }
  }

  public void Deposit(int dollars) {
    Wallet += (multiplierDeposit * dollars).CeilToInt();
    OnChange?.Invoke(new Portfolio { wallet = Wallet, investment = Investment, profit = Profit, shares = Shares });
  }

  public void Invest() {
    Investment += Wallet;
    Wallet = 0;
    OnChange?.Invoke(new Portfolio { wallet = Wallet, investment = Investment, profit = Profit, shares = Shares });
  }

  private void DayNightSubscription() {
    IsDayEnded = true;
  }

  private void DayStartSubscription() {
    IsDayEnded = false;
    Profit = 0;
    walletPasive = 0;
  }

  public void ImprovePerformance(float amount) {
    performance += amount;
  }

  public void ImproveWallet(float amount) {
    ImproveWallet((int)amount);
  }

  private void ImproveWallet(int amount) {
    if (!isAvailablePerformanceWallet) {
      isAvailablePerformanceWallet = true;
    }

    performanceWallet = amount;
  }

  public void ImproveDeposit(float amount) {
    multiplierDeposit = amount;
  }

  public void ImproveDividends(float amount) {
    if (!isActivatedDividends) {
      isActivatedDividends = true;
    }

    multiplierDividends = amount;
  }

  public void Restart() {
    // reset all stats (wallet, profit, investment, days)
    performance = DEFAULT_PERFORMANCE;
    multiplierDeposit = 1.0f;
    isActivatedDividends = false;
    multiplierDividends = 0.0f;
    isAvailablePerformanceWallet = false;
    performanceWallet = (int)DEFAULT_PERFORMANCE;
    walletPasive = 0;
    Wallet = 0;
    Investment = 0f;
    Profit = 0;
    Shares = 0;
  }
}