using D2D;
using D2D.Core;
using D2D.Utilities;
using Sirenix.OdinInspector;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using static D2D.Utilities.CommonGameplayFacade;

public class GameProgress : GameStateMachineUser
{
    [SerializeField] private LevelSO[] levels;
    [SerializeField] private Vector2 levelUpTimeRange;
    [SerializeField] private Button[] levelButtons;  // Array for buttons
    [SerializeField] private Text[] levelTexts;      // Array for corresponding Text objects

    private float XPforLevelUp;
    private float totalXP;
    private float needToFinish;
    private int level = 0;
    private Dictionary<int, float> xpToLevelUps = new();
    private XPPicker xpPicker;
    public Action<int> OnLevelUp;
    private float levelTime;
    private float timeForLevelUp;
    private float levelUpTimer;
    private bool isStarted = false;
    private bool isFinished = false;
    private LevelSO _levelSO;
    public GameObject levelmenu;
    public float GetValueForFinish() => totalXP / needToFinish;
    public float GetValueForTimeFinish() => levelTime / _levelSO.TotalDuration;
    public float GetValueForLevelUP() => XPforLevelUp / xpToLevelUps[level];
    public float GetValueForLevelUPTime() => levelUpTimer / timeForLevelUp;

    private void Awake()
    {
        _levelSO = levels[0];  // Default to level 0 at start
        _gameProgress = this;

        xpPicker = _xpPicker;
        var multiplier = Mathf.Pow(_gameData.baseXPMultiplier, _db.PassedLevels.Value);
        timeForLevelUp = levelUpTimeRange.RandomFloat();

        if (_db.PassedLevels.Value >= 4) multiplier *= 1.5f;
        if (_db.PassedLevels.Value >= 5) multiplier *= 1.2f;
        if (_db.PassedLevels.Value >= 6) multiplier *= 1.2f;
        if (_db.PassedLevels.Value >= 8) multiplier += 1;

        for (int i = 0; i < LevelSO.LevelUps; i++)
        {
            var xpToLevelUp = _levelSO.BaseXPToLevelUp * multiplier + (i * _levelSO.StepXPOnLevelUp * multiplier);
            needToFinish += xpToLevelUp;
            xpToLevelUps.Add(i, xpToLevelUp);
        }

        // Assign button click events
        for (int i = 0; i < levelButtons.Length; i++)
        {
            int index = i;  // Capture the index to use it in the button's callback
            levelButtons[i].onClick.AddListener(() => SetLevel(index));
            
        }
    }

    // Method to set the level based on the button clicked
    public void SetLevel(int index)
    {
        if (index >= 0 && index < levels.Length)
        {
            _levelSO = levels[index];  // Set the corresponding level
            Debug.Log("Level changed to: " + index);

            // Deactivate all Texts, then activate the one corresponding to the index
            for (int i = 0; i < levelTexts.Length; i++)
            {
                levelTexts[i].gameObject.SetActive(i == index);
            }
        }
    }

    protected override void OnGameRun()
    {
        isStarted = true;
    }

    protected override void OnGameFinish()
    {
        isFinished = true;
    }

    private void Update()
    {
        if (isStarted && !isFinished)
        {
            levelTime += Time.deltaTime;
            levelUpTimer += Time.deltaTime;

            if (levelUpTimer >= timeForLevelUp)
            {
                levelUpTimer = 0;
                LevelUp();
            }

            if (levelTime >= _levelSO.TotalDuration)
            {
                _stateMachine.Push(new WinState());
            }
        }
    }

    private void CheckForLevelUp(float xp)
    {
        if (level + 1 >= LevelSO.LevelUps)
        {
            return;
        }

        XPforLevelUp += xp;

        if (xpToLevelUps[level] <= XPforLevelUp)
        {
            XPforLevelUp = 0;
            level++;

            _audioManager.PlayOneShot(_gameData.spawnClip, 0.4f);

            OnLevelUp?.Invoke(level);
        }
    }

    [Button]
    public void LevelUp()
    {
        XPforLevelUp = 0;
        _audioManager.PlayOneShot(_gameData.spawnClip, 0.4f);
        OnLevelUp?.Invoke(level);
    }

    private void CheckForFinish(float xp)
    {
        totalXP += xp;

        if (totalXP >= needToFinish)
        {
            _stateMachine.Push(new WinState());
        }
    }
    public void levelmenudeactive()
    {
        levelmenu.SetActive(false);
    }
}