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

namespace MyGame.Scenes.Main.Scripts
{
    public class AutoCookCompleteView : MonoBehaviour
    {
        private static readonly string CallbackTag = "AutoCookCompleteViewCallback";
        private static readonly int OpenTrigger = Animator.StringToHash("OpenTrigger");
        private static readonly int CloseTrigger = Animator.StringToHash("CloseTrigger");

        [SerializeField] private Animator backgroundAnimator;
        [SerializeField] private Button closeButton;
        [SerializeField] private Button getButton;

        [SerializeField] private AutoCookPopcornView[] popcorns;
        private void Start()
        {
            var gameData = GameDataManager.GameData;
            var autoCookDataList = SpreadsheetDataManager.Instance.GetBaseDataList<AutoCookData>(Const.AutoCookDataSheet);
            var autoCookData = autoCookDataList.First(data => data.level == gameData.AutoCookLevel);
            
            // アイテムのリスト生成
            var productList = SpreadsheetDataManager.Instance.GetBaseDataList<ProductData>(Const.ProductDataSheet);
            var productCount = Mathf.CeilToInt((float)autoCookData.earnCount / Const.TankCapacity);
            var earnIds = gameData.AutoCookProducts.Take(productCount).ToArray();
            var earnProductArray = productList
                .Where(data => earnIds.Contains(data.id))
                .Select(data => new ProductData(data, 1){volume = Const.TankCapacity})
                .ToArray();
            var lastProductAmount = autoCookData.earnCount % Const.TankCapacity;
            if (lastProductAmount == 0)
            {
                lastProductAmount = Const.TankCapacity;
            }
            // リストの最後のポップコーン数を上書き
            earnProductArray.Last().volume = lastProductAmount;
            
            // タンクの空き確認
            var emptyTankCount = gameData.StorageTanks.Count(tank => tank.IsEmpty);
            var discardProductList = new List<ProductData>();
            
            // 価格が高い順に破棄対象にする
            foreach (var productData in earnProductArray.OrderBy(data => data.price))
            {
                if (productData.volume == Const.TankCapacity)
                {
                    if (emptyTankCount > 0)
                    {
                        emptyTankCount--;
                        continue;
                    }
                    discardProductList.Add(productData);
                }
                else
                {
                    // 空以外の補充可能な空きがあるタンクを優先して判定する
                    if (gameData.StorageTanks.Exists(data => !data.IsEmpty && data.FlavorId == productData.id && data.Capacity - data.Stock >= productData.volume))
                    {
                        continue;
                    }
                    if (emptyTankCount > 0)
                    {
                        emptyTankCount--;
                        continue;
                    }
                    discardProductList.Add(productData);
                }
            }

            closeButton.OnClickAsObservable().Take(1).Subscribe(_ =>
            {
                LocalCacheManager.Load<Action>(CallbackTag, null)?.Invoke();
                LocalCacheManager.Remove(CallbackTag);
                transform.parent.SetLocalScale(0);
                backgroundAnimator.SetTrigger(CloseTrigger);
                this.CallWaitForSeconds(.25f, () =>
                {
                    TransitionManager.Instance.UnloadScene(GameScenes.AutomaticCookingComplete);
                });
            }).AddTo(this);

            if (discardProductList.Count > 0)
            {
                getButton.OnClickAsObservable().ThrottleFirst(TimeSpan.FromSeconds(.3f)).Subscribe(_ =>
                {
                    TransitionManager.Instance.UnloadScene(GameScenes.AutomaticCookingComplete);
                    AutoCookCaution.ShowDialog((earnProductArray, discardProductList), () =>
                    {
                        LocalCacheManager.Load<Action>(CallbackTag, null)?.Invoke();
                        LocalCacheManager.Remove(CallbackTag);
                    });
                }).AddTo(this);
            }
            else
            {
                getButton.OnClickAsObservable().ThrottleFirst(TimeSpan.FromSeconds(.3f)).Subscribe(_ =>
                {
                    // コーン獲得
                    foreach (var productData in earnProductArray)
                    {
                        CookingResult.AddStock(productData);
                    }
                    
                    // 自動調理セーブ
                    gameData.AutoCookProducts = Array.Empty<int>();
                    var maxLevel = autoCookDataList.Last().level;
                    if (gameData.AutoCookLevel < maxLevel)
                    {
                        gameData.AutoCookUsesCount++;
                        if (gameData.AutoCookUsesCount >= autoCookData.clearCount)
                        {
                            gameData.AutoCookUsesCount = 0;
                            gameData.AutoCookLevel++;
                        }
                    }
                    GameDataManager.SaveGameData();
                    closeButton.onClick.Invoke();
                }).AddTo(this);
            }

            // 完成したポップコーンを表示
            for (int i = 0; i < popcorns.Length; i++)
            { 
                if (i < productCount)
                {
                    popcorns[i].SetView(earnProductArray[i]);
                    popcorns[i].SetActive(true);
                }
                else
                {
                    popcorns[i].SetActive(false);
                }
            }

            // 描画計算
            var rebuildTarget = popcorns[0].transform.parent.parent;
            var originalScale = rebuildTarget.localScale;
            rebuildTarget.localScale = Vector3.zero;
            Observable.TimerFrame(0, FrameCountType.EndOfFrame).Subscribe(_ =>
            {
                LayoutRebuilder.ForceRebuildLayoutImmediate(rebuildTarget as RectTransform);
                rebuildTarget.localScale = originalScale;
            }).AddTo(this);
        }
        
        public static void ShowDialog(Action onClose = null){
            LocalCacheManager.Save(CallbackTag, onClose);
            TransitionManager.Instance.LoadSceneAdditive(GameScenes.AutomaticCookingComplete);
        }
    }
}