using System;
using System.Linq;
using MyGame.Scripts;
using TMPro;
using UniRx;
using UnityEngine;
using UnityEngine.UI;

public class CookingResult : MonoBehaviour
{
    private static readonly string BulkOrderRarityTextFormat = "大成功ボーナス獲得";
    private static readonly string QuantityTextFormat = "x{0}";
    [SerializeField] private GameObject smokeEffect;
    [SerializeField] private GameObject glitterEffect;
    [SerializeField] private Button centerOkButton;
    [SerializeField] private Button perfectButton;
    [SerializeField] private Button leftOkButton;
    [SerializeField] private Button destructionButton;
    [SerializeField] private Transform popcornTarget;
    [SerializeField] private Text popcornText;
    [SerializeField] private Text popcornTextPerfect;
    [SerializeField] private TextMeshProUGUI quantityText;
    [SerializeField] private Text rarityText;
    [SerializeField] private RarityView rarityView;
    [SerializeField] private GameObject detailObject;
    [SerializeField] private GameObject explainObject;
    [SerializeField] private GameObject explainWithRarityObject;
    [SerializeField] private GameObject perfectResultObject;
    [SerializeField] private GameObject goodResultObject;
    [SerializeField] private GameObject failureResultObject;

    ReactiveProperty<CornResult> result = new ReactiveProperty<CornResult>();
   
    private void Start()
    {
        result.AddTo(this);
        SoundManager.Instance.ChangeVolumeUniqueBGM(.3f);
        
        var viewType = LocalCacheManager.Load(Const.ProductViewTypeTag, ProductViewType.Default);
        var productData = LocalCacheManager.Load<ProductData>(PopcornGameManager.CookingDataTag);
        var (rarityData, resultData, successAction) = LocalCacheManager.Load<(RarityData, CornResult, Action)>(PopcornGameManager.CookingResultDataTag);
        result.Value = resultData;
        SetData(productData, rarityData, viewType);

        if (GameDataManager.GameData.isFirstPlay)
        {
            SetUI(resultData, rarityData.Rarity != ProductRarity.Normal, true);
            // ボタン非表示
            if (resultData == CornResult.Failure)
            {
                TutorialManager.Instance.ShowTutorialConversation(9, () =>
                {
                    SoundManager.Instance.ChangeVolumeUniqueBGM(1f);
                    TransitionManager.Instance.UnloadScene(GameScenes.CookingResults);
                    LocalCacheManager.Load<Action>(PopcornGameManager.RestartCallbackTag, null)?.Invoke();
                });
            }
            else
            {
                successAction?.Invoke();
                centerOkButton.gameObject.SetActive(true);
                centerOkButton.OnClickAsObservable().Subscribe(_ =>
                {
                    // 獲得、遷移
                    AddStock(productData, rarityData.Rarity);
                    TransitionManager.Instance.LoadScene(GameScenes.Main);
                }).AddTo(this);
            }
            return;
        }
        
        result.Subscribe(r =>
        {
            SetUI(r, rarityData.Rarity != ProductRarity.Normal);
            if (r != CornResult.Failure)
            {
                successAction?.Invoke();
            }
        }).AddTo(this);

        // 各種ボタン押下後、獲得処理
        if (viewType == ProductViewType.Default)
        {
            Market.Instance.IsPause.Value = true;
            centerOkButton.OnClickAsObservable().Subscribe(_ =>
            {
                // 獲得、遷移
                AddStock(productData, rarityData.Rarity);
                Market.Instance.IsPause.Value = false;
                TransitionManager.Instance.LoadScene(GameScenes.Main);
            }).AddTo(this);
            leftOkButton.OnClickAsObservable().Subscribe(_ =>
            {
                // 獲得、遷移
                AddStock(productData);
                Market.Instance.IsPause.Value = false;
                TransitionManager.Instance.LoadScene(GameScenes.Main);
            }).AddTo(this);
        }
        else
        {
            // 大量注文時処理
            var materialNumber = LocalCacheManager.Load<int>(BulkOrder.MaterialNumberTag);
            centerOkButton.OnClickAsObservable().Take(1).Subscribe(_ =>
            {
                // 獲得、遷移
                if (!GameDataManager.GameData.CompletedProductList.Exists(data => data.Number == materialNumber))
                {
                    GameDataManager.GameData.CompletedProductList.Add(new BulkOrderResultData(){Number = materialNumber, Rarity = rarityData.Rarity});
                    GameDataManager.SaveGameData();
                }
                TransitionManager.Instance.LoadScene(GameScenes.Main);
            }).AddTo(this);
            leftOkButton.OnClickAsObservable().Take(1).Subscribe(_ =>
            {
                // 獲得、遷移
                if (!GameDataManager.GameData.CompletedProductList.Exists(data => data.Number == materialNumber))
                {
                    GameDataManager.GameData.CompletedProductList.Add(new BulkOrderResultData(){Number = materialNumber, Rarity = ProductRarity.Normal});
                    GameDataManager.SaveGameData();
                }
                TransitionManager.Instance.LoadScene(GameScenes.Main);
            }).AddTo(this);
        }
        
        perfectButton.OnClickAsObservable().ThrottleFirst(TimeSpan.FromSeconds(.3f)).Subscribe(_ =>
        {
            // 広告視聴後、結果上書き
            GetRewardDialog.ShowPerfectPopcornDialog(() =>
            {
                result.Value = CornResult.Perfect;
            });
        }).AddTo(this);
        destructionButton.OnClickAsObservable().Take(1).Subscribe(_ =>
        {
            // 遷移
            TransitionManager.Instance.LoadScene(GameScenes.Main);
        }).AddTo(this);
    }

    private void SetData(ProductData recipe, RarityData rarity, ProductViewType viewType)
    {
        // popcornImage
        popcornText.text = recipe.name;
        popcornTextPerfect.text = recipe.name;
        quantityText.text = string.Format(QuantityTextFormat, recipe.volume);
        var rarityFormat = viewType == ProductViewType.Default ? rarity.text : BulkOrderRarityTextFormat;
        rarityText.text = rarityFormat;
        rarityView.SetRarity(rarity.Rarity);
        popcornTarget.DestroyAllChildrens();
        Instantiate(recipe.GetLargePrefab(), popcornTarget);
    }

    private void SetUI(CornResult result, bool hasRarity, bool isTutorial = false)
    {
        centerOkButton.gameObject.SetActive(false);
        perfectButton.gameObject.SetActive(false);
        leftOkButton.gameObject.SetActive(false);
        destructionButton.gameObject.SetActive(false);

        if (!isTutorial)
        {
            this.CallWaitForSeconds(1.25f, () =>
            {
                centerOkButton.gameObject.SetActive(result == CornResult.Perfect);
                perfectButton.gameObject.SetActive(result != CornResult.Perfect);
                leftOkButton.gameObject.SetActive(result == CornResult.Good);
                destructionButton.gameObject.SetActive(result == CornResult.Failure);
            });   
        }

        perfectResultObject.SetActive(result == CornResult.Perfect);
        goodResultObject.SetActive(result == CornResult.Good);
        failureResultObject.SetActive(result == CornResult.Failure);

        if (result == CornResult.Failure)
        {
            VibrationManager.Instance.PlayVibrationDoubleStrong();
        }
        smokeEffect.SetActive(result == CornResult.Failure);
        glitterEffect.SetActive(result == CornResult.Perfect);

        detailObject.SetActive(result != CornResult.Failure);
        explainObject.SetActive(result == CornResult.Good);
        explainWithRarityObject.SetActive(false);
        if (result == CornResult.Perfect)
        {
            explainWithRarityObject.SetActive(hasRarity);
            explainObject.SetActive(!hasRarity);
        }
    }

    public static void AddStock(ProductData productData, ProductRarity rarity = ProductRarity.Normal)
    {
        var gameData = GameDataManager.GameData;
        // 店頭の空きに追加
        var remain = productData.volume;
        var shopSpace = Market.ShopStockCount - gameData.ShopStock.Count;
        var stockCount = Mathf.Min(shopSpace, remain);
        gameData.ShopStock.AddRange(Enumerable.Repeat(new ProductStockData
        {
            FlavorId = productData.id,
            Rarity = rarity,
        }, stockCount));
        remain -= stockCount;
        // ShopStockに補充された場合、DisplayFlavors更新
        if (stockCount > 0)
        {
            Market.Instance.RefillDisplayFlavors(gameData.ShopStock);
            Market.Instance.CheckStock(gameData.ShopStock);
        }

        // 空タンク並び替え
        gameData.StorageTanks = gameData.StorageTanks.OrderBy(tank => tank.IsEmpty).ToList();
        // 空きのタンクを確認
        gameData.StorageTanks
            .Select((tank, i) => (tank, i))
            .Where(x => x.tank.IsEmpty || x.tank.FlavorId == productData.id && !x.tank.IsFull)
            .Select(x => (x.i, space: x.tank.Capacity - x.tank.Stock))
            .OrderBy(x => x.space)
            .ToList()
            .ForEach(x =>
            {
                if (remain == 0)
                {
                    return;
                }
                // タンクが空ならフレーバー設定
                if (gameData.StorageTanks[x.i].IsEmpty)
                {
                    gameData.StorageTanks[x.i].FlavorId = productData.id;
                }
                // タンクに追加
                stockCount = Mathf.Min(x.space, remain);
                gameData.StorageTanks[x.i].AddStock(rarity, stockCount);
                remain -= stockCount;
            });
        GameDataManager.SaveGameData();
    }
}

