using System;
using System.Collections.Generic;
using System.Linq;
using UniRx;
using UnityEngine;
using UnityEngine.UI;

public class CornFieldReinforcement : MonoBehaviour
{
    public static readonly string CornFieldReinforcementDataTypeTag = "CornFieldReinforcementDataType";
    public static readonly string CornFieldReinforcementDataTag = "CornFieldReinforcementData";
    private static readonly string CornFieldResetCallbackTag = "CornFieldResetCallback";
    [SerializeField] private List<CornFieldReinforcementView> reinforcementViews;
    [SerializeField] private MachineUpgradeView machineUpgradeView;
    [SerializeField] private Button closeButton;
    
    private readonly CompositeDisposable compositeDisposable = new CompositeDisposable();

    private void Start()
    {
        compositeDisposable.AddTo(this);
        closeButton.OnClickAsObservable().Take(1).Subscribe(_ =>
        {
            LocalCacheManager.Remove(CornFieldReinforcementDataTypeTag);
            LocalCacheManager.Remove(CornFieldReinforcementDataTag);
            LocalCacheManager.Remove(CornFieldResetCallbackTag);
            TransitionManager.Instance.UnloadScene(GameScenes.Reinforcement);
        }).AddTo(this);
        SetView();
    }

    private void SetView()
    {
        compositeDisposable.Clear();
        var gameData = GameDataManager.GameData;
        var fieldData = SpreadsheetDataManager.Instance.GetBaseDataList<FieldUpgradeData>(Const.FieldUpgradeDataSheet);

        // 畑
        foreach (var view in reinforcementViews)
        {
            var upgradeType = FieldUpgradeData.PlantTypeToUpgradeType(view.LineType);
            if (gameData.PlantLineDataList.FirstOrDefault(x => x.Type == view.LineType) is PlantLineData lineData)
            {
                // Max
                if (lineData.Level == CornFieldRank.Rank3)
                {
                    view.SetMax();
                }
                else
                {
                    var nextRank = GetNextRank(lineData.Level);
                    var price = fieldData.FirstOrDefault(x => x.Type == upgradeType && x.level == (int)nextRank)?.price ?? 1;
                    view.SetButtonActive(price <= CoinManager.Instance.OwnCoin);
                    view.SetReinforcement(lineData, price);
                    // 購入ボタン
                    view.ButtonClickObserve.ThrottleFirst(TimeSpan.FromSeconds(.3f)).Subscribe(_ =>
                    {
                        LocalCacheManager.Save(CornFieldReinforcementDataTypeTag, upgradeType);
                        LocalCacheManager.Save(CornFieldReinforcementDataTag, (lineData, price, new Action(() => {
                            PurchaseField(price, view.LineType, nextRank);
                            SetView();
                            LocalCacheManager.Load<Action>(CornFieldResetCallbackTag, null)?.Invoke();
                        })));
                        TransitionManager.Instance.LoadSceneAdditive(GameScenes.ReinforcementDetail);
                    }).AddTo(compositeDisposable);
                }
            }
            else
            {
                var price = fieldData.FirstOrDefault(x => x.Type == upgradeType && x.level == (int)CornFieldRank.Rank1)?.price ?? 1;
                view.SetButtonActive(price <= CoinManager.Instance.OwnCoin);
                view.SetRelease(price);
                // 購入ボタン
                view.ButtonClickObserve.ThrottleFirst(TimeSpan.FromSeconds(.3f)).Subscribe(_ =>
                {
                    LocalCacheManager.Save(CornFieldReinforcementDataTypeTag, upgradeType);
                    LocalCacheManager.Save(CornFieldReinforcementDataTag, (lineData = null, price, new Action(() => {
                        PurchaseField(price, view.LineType, CornFieldRank.Rank1);
                        SetView();
                        LocalCacheManager.Load<Action>(CornFieldResetCallbackTag, null)?.Invoke();
                    })));
                    TransitionManager.Instance.LoadSceneAdditive(GameScenes.ReinforcementDetail);
                }).AddTo(compositeDisposable);
            }
        }
        
        // 収穫機
        // Max
        var maxLevel = fieldData.Where(x => x.Type == CornFieldUpgradeType.Machine).Max(x => x.level);
        if (gameData.MachineLevel == maxLevel)
        {
            machineUpgradeView.SetMax(maxLevel);
        }
        else
        {
            var price = fieldData.FirstOrDefault(x => x.Type == CornFieldUpgradeType.Machine && x.level == gameData.MachineLevel + 1)?.price ?? 1;
            machineUpgradeView.SetButtonActive(price <= CoinManager.Instance.OwnCoin);
            machineUpgradeView.SetData(gameData.MachineLevel, price);
            // 購入ボタン
            machineUpgradeView.ButtonClickObserve.ThrottleFirst(TimeSpan.FromSeconds(.3f)).Subscribe(_ =>
            {
                LocalCacheManager.Save(CornFieldReinforcementDataTypeTag, CornFieldUpgradeType.Machine);
                LocalCacheManager.Save(CornFieldReinforcementDataTag, (gameData.MachineLevel, price, new Action(() => {
                    PurchaseMachine(price);
                    SetView();
                    LocalCacheManager.Load<Action>(CornFieldResetCallbackTag, null)?.Invoke();
                })));
                TransitionManager.Instance.LoadSceneAdditive(GameScenes.ReinforcementDetail);
            }).AddTo(compositeDisposable);
        }
    }

    private void PurchaseField(int price, PlantLineType type, CornFieldRank nextRank)
    {
        var gameData = GameDataManager.GameData;
        if (gameData.PlantLineDataList.FirstOrDefault(x => x.Type == type) is PlantLineData lineData)
        {
            lineData.Level = nextRank;
        }
        else
        {
            gameData.PlantLineDataList.Add(new PlantLineData(type, CornFieldRank.Rank1));
        }
        CoinManager.Instance.SubCoin(price);
        gameData.Coin = CoinManager.Instance.OwnCoin;
        GameDataManager.SaveGameData();
    }
    
    private void PurchaseMachine(int price)
    {
        var gameData = GameDataManager.GameData;
        gameData.MachineLevel++;
        CoinManager.Instance.SubCoin(price);
        gameData.Coin = CoinManager.Instance.OwnCoin;
        GameDataManager.SaveGameData();
    }
    
    public static CornFieldRank GetNextRank(CornFieldRank rank)
    {
        switch (rank)
        {
            case CornFieldRank.Rank1:
                return CornFieldRank.Rank2;
            case CornFieldRank.Rank2:
                return CornFieldRank.Rank3;
            default:
                throw new ArgumentOutOfRangeException(nameof(rank), rank, null);
        }
    }

    public static void ShowDialog(Action onClose = null)
    {
        LocalCacheManager.Save(CornFieldResetCallbackTag, onClose);
        TransitionManager.Instance.LoadSceneAdditive(GameScenes.Reinforcement);
    }
}