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

public class Information : MonoBehaviour
{
    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 GameObject shopInfoEnabled;
    [SerializeField] private GameObject recordEnabled;
    [SerializeField] private Button shopInfoButton;
    [SerializeField] private Button recordButton;

    [SerializeField] private ScrollRect scrollRect;
    [SerializeField] private GameObject shopInfoObject;
    [SerializeField] private GameObject recordObject;

    [SerializeField] private Transform historyTarget;
    [SerializeField] private Transform productTarget;
    [SerializeField] private Transform materialTarget;
    
    [SerializeField] private ShopHistoryItemView historyPrefab;
    [SerializeField] private HasProductItemView productPrefab;
    [SerializeField] private HasMaterialItemView materialPrefab;
    
    [SerializeField] private Text totalDayText;
    [SerializeField] private Text totalSalesText;
    [SerializeField] private Text totalCoinText;

    public static readonly string shopLevelFormat = "Lv.{0}";
    public static readonly string progressFormat = "{0}/{1}";
    
    [SerializeField] private Text achievementText;
    [SerializeField] private Text shopLevelText;
    [SerializeField] private Text progressText;
    [SerializeField] private Text shopCustomizeLevelText;
    [SerializeField] private Text shopCustomizeProgressText;
    [SerializeField] private Text autoCookLevelText;
    [SerializeField] private Text autoCookProgressText;
    [SerializeField] private GameObject autoCookLevelObject;
    [SerializeField] private GameObject autoCookProgressObject;

    private bool isOdd;

    private void Start()
    {
        closeButton.OnClickAsObservable().Take(1).Subscribe(_ =>
        {
            transform.SetLocalScale(0);
            backgroundAnimator.SetTrigger(CloseTrigger);
            this.CallWaitForSeconds(.25f, () =>
            {
                TransitionManager.Instance.UnloadScene(GameScenes.Information);
            });
        }).AddTo(this);
        shopInfoButton.OnClickAsObservable().Select(_ => true)
            .Merge(recordButton.OnClickAsObservable().Select(_ => false))
            .Subscribe( isShopInfo =>
            {
                shopInfoButton.gameObject.SetActive(!isShopInfo);
                shopInfoEnabled.SetActive(isShopInfo);
                shopInfoObject.transform.SetLocalScale(isShopInfo ? 1f : 0f);
                recordButton.gameObject.SetActive(isShopInfo);
                recordEnabled.SetActive(!isShopInfo);
                recordObject.transform.SetLocalScale(isShopInfo ? 0f : 1f);
                scrollRect.content = (isShopInfo ? shopInfoObject.transform : recordObject.transform) as RectTransform;
                scrollRect.verticalNormalizedPosition = 1;
            }).AddTo(this);

        var gameData = GameDataManager.GameData;
        var shopLevelList = SpreadsheetDataManager.Instance.GetBaseDataList<ShopLevelData>(Const.ShopLevelDataSheet);
        shopLevelList = shopLevelList.Where(data => data.shopLevel != Const.SpecialShopLevel).ToList();
        var shopScriptList = SpreadsheetDataManager.Instance.GetBaseDataList<BrotherScriptData>(Const.ScriptDataSheet);
        var shopLevelData = shopLevelList.FirstOrDefault(data => data.shopLevel == gameData.ViewedShopLevel) ?? shopLevelList[0];
        var nextShopLevelData = shopLevelList.FirstOrDefault(data => data.shopLevel == gameData.ViewedShopLevel + 1);
        var nextLevelHeart = nextShopLevelData?.heart ?? shopLevelData.heart;
        var shopCustomizeLevelList = SpreadsheetDataManager.Instance.GetBaseDataList<ShopCustomizeLevelData>(Const.ShopCustomizeLevelDataSheet);
        var shopCustomizeData = shopCustomizeLevelList.FirstOrDefault(data => data.level == gameData.ShopCustomizeLevel) ?? shopCustomizeLevelList[0];
        var nextShopCustomizeData = shopCustomizeLevelList.FirstOrDefault(data => data.level == gameData.ShopCustomizeLevel + 1);
        var nextShopCustomizePoint = nextShopCustomizeData?.point ?? shopCustomizeData.point;
        var autoCookDataList = SpreadsheetDataManager.Instance.GetBaseDataList<AutoCookData>(Const.AutoCookDataSheet);
        var autoCookData = autoCookDataList.FirstOrDefault(data => data.level == gameData.AutoCookLevel) ?? autoCookDataList[0];
        totalDayText.text = $"{gameData.dailyLoginCount}{ScriptLocalization.Unit.Day}";
        totalSalesText.text = $"{gameData.TotalSales}{ScriptLocalization.Unit.Amount}";
        totalCoinText.text = gameData.TotalAddCoin.ToString();
        achievementText.text = shopLevelData.Achievement;
        shopLevelText.text = String.Format(shopLevelFormat, gameData.ViewedShopLevel.ToString());
        progressText.text = String.Format(progressFormat, Mathf.Min(gameData.Heart, nextLevelHeart), nextLevelHeart);
        shopCustomizeLevelText.text = String.Format(shopLevelFormat, gameData.ShopCustomizeLevel.ToString());
        shopCustomizeProgressText.text = String.Format(progressFormat, Mathf.Min(gameData.ShopCustomizePoint, nextShopCustomizePoint), nextShopCustomizePoint);
        autoCookLevelText.text = String.Format(shopLevelFormat, gameData.AutoCookLevel);
        autoCookProgressText.text = String.Format(progressFormat, Mathf.Min(gameData.AutoCookUsesCount, autoCookData.clearCount), autoCookData.clearCount);
        autoCookLevelObject.SetActive(gameData.ViewedShopLevel >= Const.AutoCookAvailableLevel);
        autoCookProgressObject.SetActive(gameData.ViewedShopLevel >= Const.AutoCookAvailableLevel);

        var productList = SpreadsheetDataManager.Instance.GetBaseDataList<ProductData>(Const.ProductDataSheet);
        var materialList = SpreadsheetDataManager.Instance.GetBaseDataList<ShopData>(Const.ShopDataSheet);
        var shopStockList = gameData.ShopStock.Select(data => (data.FlavorId, data.Stock));
        var tankStockList = gameData.StorageTanks.Select(data => (data.FlavorId, data.Stock));
        var totalStockList = shopStockList.Concat(tankStockList).ToList();

        // shopLevel
        historyTarget.DestroyAllChildrens();
        
        var tutorialDataList = SpreadsheetDataManager.Instance.GetBaseDataList<BrotherScriptData>(Const.TutorialScriptDataSheet);
        var mainList = tutorialDataList.Where(data => Const.MainTutorial.Contains(data.id)).OrderBy(data => Array.IndexOf(Const.MainTutorial, data.id)).ToList();
        var fieldList = tutorialDataList.Where(data => Const.FieldTutorial.Contains(data.id)).OrderBy(data => Array.IndexOf(Const.FieldTutorial, data.id)).ToList();
        var shoppingList = tutorialDataList.Where(data => Const.ShoppingTutorial.Contains(data.id)).OrderBy(data => Array.IndexOf(Const.ShoppingTutorial, data.id)).ToList();
        var managementList = tutorialDataList.Where(data => Const.ManagementTutorial.Contains(data.id)).OrderBy(data => Array.IndexOf(Const.ManagementTutorial, data.id)).ToList();
        SetHistory(shopLevelList[0], mainList, false);
        // tutorial用のSetHistoryが必要
        SetHistory(ScriptLocalization.Item.ShopHistoryText0001, fieldList);
        SetHistory(ScriptLocalization.Item.ShopHistoryText0002, shoppingList);
        SetHistory(ScriptLocalization.Item.ShopHistoryText0003, managementList);

        for (var index = 1; index < shopLevelList.Count; index++)
        {
            var levelData = shopLevelList[index];
            var scriptList = shopScriptList.Where(data => data.id == levelData.shopLevel).ToList();
            SetHistory(levelData, scriptList, levelData.shopLevel > gameData.ViewedShopLevel);
        }


        // product
        productTarget.DestroyAllChildrens();
        if (totalStockList.Sum(data => data.Stock) == 0)
        {
            var view = Instantiate(productPrefab, productTarget);
            view.SetNoStock(true);
        }
        else
        {
            foreach (var productData in productList)
            {
                var count = totalStockList.Count(data => data.FlavorId == productData.id);
                if (count == 0)
                {
                    continue;
                }

                var view = Instantiate(productPrefab, productTarget);
                view.SetData(productData, count);
            }
        }

        // material
        materialTarget.DestroyAllChildrens();
        var totalCount = gameData.Material.Sum(data => data.Amount);
        if (totalCount == 0)
        {
            var view = Instantiate(materialPrefab, materialTarget);
            view.SetNoStock(true);
        }
        else
        {
            foreach (var materialData in gameData.Material)
            {
                if (materialData.Amount == 0)
                {
                    continue;
                }
                var view = Instantiate(materialPrefab, materialTarget);
                view.SetData(materialList.First(data => data.itemId == materialData.Id), materialData.Amount);
            }
        }
        
        shopInfoButton.onClick.Invoke();
        
        // 描画計算
        shopInfoObject.SetActive(true);
        recordObject.SetActive(true);
        Observable.TimerFrame(0, FrameCountType.EndOfFrame).Subscribe(_ =>
        {
            LayoutRebuilder.ForceRebuildLayoutImmediate(recordObject.transform as RectTransform);
            LayoutRebuilder.ForceRebuildLayoutImmediate(shopInfoObject.transform as RectTransform);
        }).AddTo(this);
    }

    private void SetHistory(ShopLevelData levelData, List<BrotherScriptData> scriptList, bool unreleased)
    {
        var view = CreateItemView();
        if (unreleased)
        {
            view.SetUnreleased(true);
            return;
        }

        view.SetData(levelData);
        SetScript(view, scriptList);
    }

    private void SetHistory(string text, List<BrotherScriptData> scriptList)
    {
        var view = CreateItemView();
        view.SetAchievementText(text);
        SetScript(view, scriptList);
    }

    private ShopHistoryItemView CreateItemView()
    {
        var view = Instantiate(historyPrefab, historyTarget);
        isOdd = !isOdd;
        view.SetOddBG(isOdd);
        return view;
    }

    private static void SetScript(ShopHistoryItemView view, List<BrotherScriptData> scriptList)
    {
        if (scriptList.Count <= 0)
        {
            view.SetButtonAcive(false);
            return;
        }

        view.PlayButton.ThrottleFirst(TimeSpan.FromSeconds(1f)).Subscribe(_ =>
        {
            LocalCacheManager.Save(BrotherConversation.ScriptDataTag, scriptList);
            TransitionManager.Instance.LoadSceneAdditive(GameScenes.Conversation);
        }).AddTo(view);
    }
}
