using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using MyGame.Scenes.Main.Scripts;
using MyGame.Scripts;
using UniRx;
using UniRx.Triggers;
using Unity.Mathematics;
using UnityEngine;
using UnityEngine.UI;

public class KitchenManager : MonoBehaviour
{
    private static readonly double refreshWaitTime = 300;
    [Range(0, 9)]
    [SerializeField] private int livelyRate = 7;
    [SerializeField] int refreshRewardCoin = 100;
    [SerializeField] private Button cookingButton;
    [SerializeField] private Button adButton;
    [SerializeField] private KitchenView kitchenView;
    [SerializeField] private BulkOrderIndicatorView orderIndicatorView;
    [SerializeField] private AutoCookView autoCookView;
    
    private readonly Subject<Unit> showAdDialogSubject = new Subject<Unit>();
    private IDisposable timerDisposable = null;
    private IDisposable tapPhoneDisposable;
    
    // Start is called before the first frame update
    void Start()
    {
        showAdDialogSubject.AddTo(this);
        SoundManager.Instance.PlayBGM("bgm_Main");
        var gameData = GameDataManager.GameData;
        
        // レシピの表示
        cookingButton.OnClickAsObservable().Subscribe(_ =>
        {
            RecipeSelectDialog.ShowDialog(ProductViewType.Default);
        });
        
        // 大量注文データ
        var bulkOrderList = SpreadsheetDataManager.Instance.GetBaseDataList<BulkOrderData>(Const.BulkOrderDataSheet);
        var bulkOrderData = bulkOrderList.FirstOrDefault(data => data.id == gameData.OrderIdInProgress);
        var achieved = bulkOrderData is null || gameData.DeliveredOrder.Contains(bulkOrderData.id) || gameData.AchievedOrderLevel == bulkOrderData.shopLevel;
        var cancelled = gameData.OrderIdInProgress == gameData.CancelOrderId;
        
        CheckOrderAndSetPhoneTap();

        // 大量注文達成通知
        if (bulkOrderData == null)
        {
            orderIndicatorView.SetBadgeActive(false);
        }
        else
        {
            var orderList = new List<int>
            {
                bulkOrderData.productId1,
                bulkOrderData.productId2,
                bulkOrderData.productId3,
            };
            var completed = gameData.CompletedProductList.Count == orderList.Count(x => x != 0);
            orderIndicatorView.SetBadgeActive(completed && !achieved && !cancelled);
        }
        
        // 大量注文の調理から戻ってきたときにダイアログ開く
        if (LocalCacheManager.Load(Const.ProductViewTypeTag, ProductViewType.Default) == ProductViewType.BulkOrder)
        {
            BulkOrderShowDialogWithSetup();
        }
        
        // 自動調理
        autoCookView.Initialize();
        // レベル確認
        autoCookView.SetActive(gameData.ViewedShopLevel >= Const.AutoCookAvailableLevel);
        
        var autoCookDataList = SpreadsheetDataManager.Instance.GetBaseDataList<AutoCookData>(Const.AutoCookDataSheet);
        if (autoCookDataList.FirstOrDefault(data => data.level == gameData.AutoCookLevel) is AutoCookData autoCookData)
        {
            autoCookView.CheckNotify();
            CookState state;
            var remainingTime = DateTime.FromBinary(gameData.AutoCookFinishTime).Subtract(DateTime.UtcNow);
            if (gameData.AutoCookProducts.Length > 0)
            {
                autoCookView.ResetTimer((int)remainingTime.TotalSeconds, (int)TimeSpan.FromHours(autoCookData.duration).TotalSeconds);
            }
            autoCookView.Button.ThrottleFirst(TimeSpan.FromSeconds(.3f)).Subscribe(_ =>
            {
                // 自動調理チュートリアル
                if (!gameData.FinishedFlags.HasFlag(TutorialFlag.AutoCook))
                {
                    TutorialManager.Instance.ShowTutorialConversation(14, () =>
                    {
                        gameData.FinishedFlags |= TutorialFlag.AutoCook;
                        GameDataManager.SaveGameData();
                        autoCookView.ShowDialog(CookState.Ready, () =>
                        {
                            autoCookView.CheckNotify();
                            remainingTime = DateTime.FromBinary(gameData.AutoCookFinishTime).Subtract(DateTime.UtcNow);
                            autoCookView.ResetTimer((int)remainingTime.TotalSeconds, (int)TimeSpan.FromHours(autoCookData.duration).TotalSeconds);
                        });
                    });
                    return;
                }
                
                remainingTime = DateTime.FromBinary(gameData.AutoCookFinishTime).Subtract(DateTime.UtcNow);
                if (gameData.AutoCookProducts.Length == 0)
                {
                    state = CookState.Ready;
                }
                else if (remainingTime.TotalSeconds <= 0)
                {
                    state = CookState.Complete;
                }
                else
                {
                    state = CookState.Progress;
                }

                autoCookView.ShowDialog(state, () =>
                {
                    autoCookView.CheckNotify();
                    if (gameData.AutoCookProducts.Length == 0)
                    {
                        autoCookView.Ready();
                    }
                    else
                    {
                        remainingTime = DateTime.FromBinary(gameData.AutoCookFinishTime).Subtract(DateTime.UtcNow);
                        autoCookView.ResetTimer((int)remainingTime.TotalSeconds, (int)TimeSpan.FromHours(autoCookData.duration).TotalSeconds);
                    }
                });
            }).AddTo(this);
        }
        
        // tutorial
        if (!gameData.FinishedFlags.HasFlag(TutorialFlag.FirstPlay))
        {
            if (TutorialManager.Instance.Index == 0)
            {
                gameData.ViewedShopLevel = 0;
                // アイテム付与
                gameData.CornSeed = 100;
                gameData.Coin = 0;
                if (!(gameData.Material.FirstOrDefault(x => x.Id == 2) is MaterialData materialData))
                {
                    materialData = new MaterialData {Id = 2};
                    gameData.Material.Add(materialData);
                }
                materialData.Amount++;
                gameData.InitTank();
                gameData.ShopStock.Clear();
                // ミッションカウンターリセット
                gameData.ResetNormalTotalCount();
                gameData.ResetDailyTotalCount();
                
                // 店舗レベル1達成表示
                kitchenView.SetActive(false);
                ShopLevelUp.ShowDialog(1, () =>
                {
                    TutorialManager.Instance.ShowTutorialConversation(1, () =>
                    {
                        kitchenView.SetActive(true);
                        // マスク表示
                        var buttonRectTransform = cookingButton.transform as RectTransform;
                        var go = TutorialManager.Instance.ShowTutorialMask(buttonRectTransform.parent, buttonRectTransform);
                        cookingButton.OnClickAsObservable().Take(1).Subscribe(_ =>
                        {
                            DestroyImmediate(go);
                        }).AddTo(this);
                    });
                });
            }
            else
            {
                // チュートリアル調理終了後
                kitchenView.SetActive(false);
                TutorialManager.Instance.ShowTutorialConversation(3, () =>
                {
                    kitchenView.SetActive(true);
                    var go = FindObjectOfType<FooterManager>().transform;
                    go.transform.FindChildByName("Button_shop", t =>
                    {
                        TutorialManager.Instance.ShowTutorialMask(go.parent, t as RectTransform, true);
                    });
                });
            }
        }
        
        CoinManager.Instance.ChangeCoin(gameData.Coin);
        HeartMeter.Instance.Initialize(gameData.ViewedShopLevel, gameData.Heart);
        
        // ハートゲージがフルかつダイアログが開いていない場合レベルアップ
        HeartMeter.Instance.FulledHeart
            .SkipWhile(_ => !gameData.FinishedFlags.HasFlag(TutorialFlag.FirstPlay))
            .DelaySubscription(TimeSpan.FromSeconds(.4f))
            .Subscribe(_ =>
            {
                kitchenView.SetActive(false);
                ShopLevelUp.ShowDialog(gameData.ViewedShopLevel + 1, () =>
                {
                    kitchenView.SetActive(true);
                    CheckOrderAndSetPhoneTap();
                    autoCookView.SetActive(gameData.ViewedShopLevel >= Const.AutoCookAvailableLevel);
                });
            }).AddTo(this);

        GameDataObserver.Instance.HeartObserver
            .DistinctUntilChanged()
            .Pairwise()
            .Subscribe(pair =>
            {
                HeartMeter.Instance.AddHeart(pair.Current - pair.Previous);
            }).AddTo(this);

        kitchenView.Initialize();
        adButton.OnClickAsObservable()
            .Merge(showAdDialogSubject)
            .ThrottleFirst(TimeSpan.FromSeconds(.3f)).Subscribe(_ =>
            {
                // 動画視聴POP
                GetRewardDialog.ShowCoinDialog(() =>
                {
                    CoinGetDialog.ShowDialog(refreshRewardCoin, () =>
                    {
                        CoinManager.Instance.AddCoin(refreshRewardCoin);
                        gameData.Coin = CoinManager.Instance.OwnCoin;
                        gameData.kitchenRefreshTime = DateTime.UtcNow.AddSeconds(refreshWaitTime).ToBinary();
                        GameDataManager.SaveGameData();

                        // SetTimer((int)refreshWaitTime);
                        adButton.gameObject.SetActive(false);
                        if (gameData.kitchenRefreshTime % 10 < livelyRate)
                        {
                            kitchenView.SetLivelyAnimation();
                        }
                        else
                        {
                            kitchenView.SetNormalAnimation();
                        }
                    });
                });
            }).AddTo(this);
        
        // 休憩リワード
        var remaining = (int) DateTime.FromBinary(gameData.kitchenRefreshTime).Subtract(DateTime.UtcNow).TotalSeconds;
        // timerDisposable = SetTimer(remaining);
        
        // 商品在庫計算
        var shopStock = gameData.ShopStock.Count;
        var tankStock = gameData.StorageTanks.Sum(x => x.Stock);
        var totalStock = shopStock + tankStock;

        if (remaining <= 0 && gameData.FinishedFlags.HasFlag(TutorialFlag.FirstPlay))
        {
            // コイン獲得有効
            adButton.gameObject.SetActive(true);
            kitchenView.SetNormalAnimation();
        }
        else if (gameData.Coin + gameData.Material.Sum(data => data.Amount) + totalStock == 0)
        {
            // 所持金0救済
            adButton.gameObject.SetActive(true);
            kitchenView.SetNormalAnimation();
            showAdDialogSubject.OnNext(Unit.Default);
        }
        else if (remaining > 0)
        {
            // 獲得後
            adButton.gameObject.SetActive(false);
            if (gameData.kitchenRefreshTime % 10 < livelyRate)
            {
                kitchenView.SetLivelyAnimation();
            }
            else
            {
                kitchenView.SetNormalAnimation();
            }
        }
        else
        {
            // 獲得無効
            adButton.gameObject.SetActive(false);
            kitchenView.SetNormalAnimation();
        }

#if UNITY_EDITOR
        Debug.Log($"remaining: {remaining}");
        Market.StockFlavorLog();
#endif

    }

    // 大量注文タップ時の挙動設定
    private void CheckOrderAndSetPhoneTap()
    {
        var gameData = GameDataManager.GameData;
        // 大量注文データ
        var bulkOrderList = SpreadsheetDataManager.Instance.GetBaseDataList<BulkOrderData>(Const.BulkOrderDataSheet);
        var bulkOrderData = bulkOrderList.FirstOrDefault(data => data.id == gameData.OrderIdInProgress);
        var achieved = bulkOrderData is null || gameData.DeliveredOrder.Contains(bulkOrderData.id) || gameData.AchievedOrderLevel == bulkOrderData.shopLevel;
        var cancelled = gameData.OrderIdInProgress == gameData.CancelOrderId;
        var result = CheckBulkOrder();
        orderIndicatorView.SetIndicate(result.newOrder, achieved || cancelled);

        if (!result.newOrder)
        {
            if (!cancelled)
            {
                SetPhoneTap();
            }
        }
        else
        {
            // 新着処理
            SoundManager.Instance.StopSE("se_Main_phone_sound");
            var messageList = SpreadsheetDataManager.Instance.GetBaseDataList<BulkOrderTextData>(Const.BulkOrderTextDataSheet);
            var nextMessageList = messageList.Where(data => data.shopLevel == result.nextOrderLevel).ToList();
            tapPhoneDisposable?.Dispose();
            tapPhoneDisposable = orderIndicatorView.TappedPhone.Take(1).Subscribe(_ =>
            {
                // タップで更新
                gameData.CompletedProductList.Clear();
                gameData.OrderIdInProgress = result.nextOrderId;
                if (nextMessageList.Exists(data => data.id == gameData.OrderTextId))
                {
                    var nextMessageIndex = nextMessageList.FindIndex(data => data.id == gameData.OrderTextId) + 1;
                    gameData.OrderTextId = nextMessageList[nextMessageIndex >= nextMessageList.Count ? 0 : nextMessageIndex].id;
                }
                else
                {
                    gameData.OrderTextId = nextMessageList.First().id;
                }

                GameDataManager.SaveGameData();

                var orderData = bulkOrderList.First(data => data.id == result.nextOrderId);
                LocalCacheManager.Save(BulkOrder.DataTag, orderData);
                BulkOrderNotifyView.ShowDialog(BulkOrderShowDialogWithSetup);

                // 通知をタップ後タップ動作を切り替える
                SetPhoneTap();
                orderIndicatorView.SetIndicate(false, false);
            }).AddTo(this);
        }
    }
    
    private void SetPhoneTap()
    {
        tapPhoneDisposable?.Dispose();
        tapPhoneDisposable = orderIndicatorView.TappedPhone
            .ThrottleFirst(TimeSpan.FromSeconds(1f))
            .Subscribe(_ =>
            {
                BulkOrderShowDialogWithSetup();
            }).AddTo(this);
    }

    private void BulkOrderShowDialogWithSetup()
    {
        BulkOrder.ShowDialog(
            onAchieved: () =>
            {
                orderIndicatorView.SetIndicate(false, true);
                orderIndicatorView.SetBadgeActive(false);
            },
            onCancel: () =>
            {
                orderIndicatorView.SetIndicate(false, true);
                orderIndicatorView.SetBadgeActive(false);
            });
    }

    private (bool newOrder, int nextOrderId, int nextOrderLevel) CheckBulkOrder()
    {
        var gameData = GameDataManager.GameData;
        var nextOrderLevel = 0;
        var nextOrderId = gameData.OrderIdInProgress;
        var bulkOrderList = SpreadsheetDataManager.Instance.GetBaseDataList<BulkOrderData>(Const.BulkOrderDataSheet);
        if (!(bulkOrderList.FirstOrDefault(data => data.shopLevel >= gameData.AchievedOrderLevel + 1) is BulkOrderData bulkOrderData))
        {
            return (false, nextOrderId, nextOrderLevel);
        }
        
        nextOrderLevel = bulkOrderData.shopLevel;
        if (gameData.ViewedShopLevel < nextOrderLevel)
        {
            return (false, nextOrderId, nextOrderLevel);
        }
        var achieved = gameData.DeliveredOrder.Contains(gameData.OrderIdInProgress);
        var canceled = gameData.OrderIdInProgress == gameData.CancelOrderId;
        var nextOrderList = bulkOrderList.Where(data => data.shopLevel == nextOrderLevel).ToList();
        if (!nextOrderList.Exists(data => data.id == gameData.OrderIdInProgress))
        {
            // まだ次のオーダーが設定されてない場合nextOrderListの一番若いIDを設定
            nextOrderId = nextOrderList.First().id;
        }
        else if (achieved || canceled)
        {
            // 達成済みか、キャンセルされた場合次のIDを設定
            // 未達成のオーダー
            var orderList = nextOrderList.Where(data => !gameData.DeliveredOrder.Contains(data.id)).ToList();
            if (orderList.Count <= 0)
            {
#if UNITY_EDITOR
                // オーダーリストがすべて達成済みの場合エラー
                Debug.LogError($"大量注文レベル{nextOrderLevel}に受けられるオーダーがありませんデータを確認してください\n" +
                               $"maxOrder:{nextOrderList[0].maxOrder}\n" +
                               $"delivered:{gameData.DeliveredOrder.Aggregate(string.Empty, (s, data) => $"{s}, {data}")}\n" +
                               $"orderList:{nextOrderList.Aggregate(string.Empty, (s, data) => $"{s}, {data.id}")}");
#endif
                return (false, nextOrderId, nextOrderLevel);
            }

            var nextIndex = orderList.FindIndex(data => data.id > gameData.OrderIdInProgress);
            nextOrderId = orderList[Mathf.Max(0, nextIndex)].id;
        }
        
        

        if (gameData.OrderIdInProgress == nextOrderId)
        {
            return (false, nextOrderId, nextOrderLevel);
        }

        var orderData = nextOrderList.First(data => data.id == nextOrderId);
         // キャンセル時retryConditionを使う
        var condition = canceled ? orderData.retryCondition : orderData.firstOrderCondition;
#if UNITY_EDITOR
        Debug.Log($"nextOrderId: {nextOrderId} use {(canceled ? "retryCondition" : "firstOrderCondition")} ({gameData.OrderConditionCount}/{condition})");
#endif
        // 条件チェック
        return (condition <= gameData.OrderConditionCount, nextOrderId, nextOrderLevel);
    }

    private IDisposable SetTimer(int time)
    {
        timerDisposable?.Dispose();
        return Observable.Timer(TimeSpan.Zero,TimeSpan.FromSeconds(1f))
            .Select(x => (int)(time - x))
            .TakeWhile(x => x > 0)
            .Subscribe(x => { }
                , () =>
                {
                    kitchenView.SetNormalAnimation();
                    adButton.gameObject.SetActive(true);
                }).AddTo(this);
    }

    private void OnDestroy()
    {
        if (SoundManager.ExistsInstance)
        {
            SoundManager.Instance.StopSE("se_Main_phone_sound");
        }
    }
}
