using System;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.UI;
using Vanguard.Api;
using Vanguard.Auth;
using Vanguard.State;
namespace Vanguard.UI
{
/// Главный экран после входа: профиль, балансы и заглушки разделов.
public sealed class MetaView : IDisposable
{
private readonly AuthService _auth;
private readonly PlayerState _player;
private readonly Action _onLoggedOut;
private readonly Action _onCollection;
private readonly Action _onDecks;
private readonly Action _onStore;
private readonly Action _onPlay;
private readonly Action _onOnboarding;
private bool _disposed;
private readonly RectTransform _root;
private readonly Text _playerName;
private readonly Text _onboarding;
private readonly Text _gold;
private readonly Text _dust;
private readonly Text _tokens;
private readonly Text _ranked;
private readonly Text _casual;
private readonly Text _record;
private readonly Text _status;
private readonly Button _logout;
private readonly Button _onboardingButton;
private bool _refreshing;
public MetaView(
Transform parent,
AuthService auth,
PlayerState player,
Action onLoggedOut,
Action onCollection,
Action onDecks,
Action onStore,
Action onPlay,
Action onOnboarding)
{
_auth = auth;
_player = player;
_onLoggedOut = onLoggedOut;
_onCollection = onCollection;
_onDecks = onDecks;
_onStore = onStore;
_onPlay = onPlay;
_onOnboarding = onOnboarding;
_root = UiKit.CreatePanel(parent, "MetaScreen", new Color(0.035f, 0.045f, 0.065f, 1f));
var top = UiKit.CreatePanel(_root, "TopBar", new Color(0.07f, 0.085f, 0.115f, 1f));
var topRect = top;
topRect.anchorMin = new Vector2(0f, 1f);
topRect.anchorMax = new Vector2(1f, 1f);
topRect.pivot = new Vector2(0.5f, 1f);
topRect.anchoredPosition = Vector2.zero;
topRect.sizeDelta = new Vector2(0f, 92f);
UiKit.AddHorizontalLayout(top, 22, 16);
var brand = UiKit.CreateText(
top, "Brand", "VANGUARD", 34, new Color(0.86f, 0.90f, 1f), TextAnchor.MiddleLeft);
brand.fontStyle = FontStyle.Bold;
UiKit.SetPreferredHeight(brand, 48f, 0f);
_playerName = UiKit.CreateText(
top, "PlayerName", "…", 20, new Color(0.70f, 0.76f, 0.90f), TextAnchor.MiddleLeft);
UiKit.SetPreferredHeight(_playerName, 40f);
_logout = UiKit.CreateButton(top, "Logout", "Выйти", OnLogoutClicked, 18);
UiKit.SetPreferredHeight(_logout, 42f, 0f);
var content = UiKit.CreatePanel(_root, "Content", new Color(0.035f, 0.045f, 0.065f, 0f));
var contentRect = content;
contentRect.anchorMin = Vector2.zero;
contentRect.anchorMax = Vector2.one;
contentRect.offsetMin = new Vector2(48f, 36f);
contentRect.offsetMax = new Vector2(-48f, -116f);
UiKit.AddVerticalLayout(contentRect, 12, 16);
var welcome = UiKit.CreateText(
content, "Welcome", "Личный кабинет", 38, Color.white, TextAnchor.MiddleLeft);
UiKit.SetPreferredHeight(welcome, 56f);
_onboarding = UiKit.CreateText(
content, "Onboarding", string.Empty, 18,
new Color(1f, 0.76f, 0.38f), TextAnchor.MiddleLeft);
UiKit.SetPreferredHeight(_onboarding, 28f);
var stats = UiKit.CreatePanel(content, "Stats", new Color(0.07f, 0.085f, 0.115f, 1f));
UiKit.SetPreferredHeight(stats, 130f);
UiKit.AddHorizontalLayout(stats, 18, 14);
_gold = AddStat(stats, "Gold");
_dust = AddStat(stats, "Пыль");
_tokens = AddStat(stats, "Токены");
_ranked = AddStat(stats, "Ranked MMR");
_casual = AddStat(stats, "Casual MMR");
var actions = UiKit.CreatePanel(content, "Actions", new Color(0.07f, 0.085f, 0.115f, 1f));
UiKit.SetPreferredHeight(actions, 96f);
UiKit.AddHorizontalLayout(actions, 18, 14);
AddAction(actions, "Коллекция", _onCollection);
AddAction(actions, "Колоды", _onDecks);
AddAction(actions, "Магазин", _onStore);
AddAction(actions, "В бой", _onPlay);
var lower = UiKit.CreatePanel(content, "Lower", new Color(0.07f, 0.085f, 0.115f, 1f));
UiKit.SetPreferredHeight(lower, 220f, 1f);
UiKit.AddVerticalLayout(lower, 20, 8);
_record = UiKit.CreateText(
lower, "Record", string.Empty, 20,
new Color(0.72f, 0.78f, 0.92f), TextAnchor.MiddleLeft);
UiKit.SetPreferredHeight(_record, 28f);
_status = UiKit.CreateText(
lower, "Status", string.Empty, 18,
new Color(0.62f, 0.68f, 0.82f), TextAnchor.UpperLeft);
UiKit.SetPreferredHeight(_status, 70f);
_onboardingButton = UiKit.CreateButton(
lower, "OnboardingButton", "Выбрать триал-деку", () => _onOnboarding(), 20);
UiKit.SetPreferredHeight(_onboardingButton, 46f);
_player.Changed += UpdateTexts;
_root.gameObject.SetActive(false);
}
public void Show()
{
UiKit.SetActive(_root, true);
UpdateTexts();
_ = RefreshAsync();
}
public void Hide() => UiKit.SetActive(_root, false);
public void Dispose()
{
if (_disposed)
return;
_disposed = true;
_player.Changed -= UpdateTexts;
}
private static Text AddStat(Transform parent, string caption)
{
var card = UiKit.CreatePanel(parent, "Stat_" + caption, new Color(0.09f, 0.11f, 0.15f, 1f));
UiKit.AddVerticalLayout(card, 12, 4);
var element = card.gameObject.AddComponent();
element.flexibleWidth = 1f;
element.preferredHeight = 100f;
var label = UiKit.CreateText(
card, "Caption", caption, 16, new Color(0.58f, 0.65f, 0.78f));
UiKit.SetPreferredHeight(label, 22f);
var value = UiKit.CreateText(
card, "Value", "—", 30, Color.white);
value.fontStyle = FontStyle.Bold;
UiKit.SetPreferredHeight(value, 40f);
return value;
}
private static Button AddAction(Transform parent, string caption, Action onClick)
{
var button = UiKit.CreateButton(parent, "Action_" + caption, caption, () => onClick(), 20);
var element = button.gameObject.AddComponent();
element.flexibleWidth = 1f;
element.preferredHeight = 56f;
return button;
}
private async Task RefreshAsync()
{
if (_refreshing)
return;
_refreshing = true;
SetStatus("Обновляем профиль…", new Color(0.62f, 0.68f, 0.82f));
try
{
await _auth.RefreshMeAsync();
if (_disposed)
return;
SetStatus("Профиль обновлён.", new Color(0.45f, 0.85f, 0.55f));
}
catch (ApiException exception) when (exception.StatusCode == 401)
{
if (!_disposed)
_onLoggedOut();
}
catch (Exception exception)
{
Debug.LogException(exception);
SetStatus("Не удалось обновить профиль. Сервер недоступен?", new Color(1f, 0.60f, 0.45f));
}
finally
{
_refreshing = false;
}
}
private void UpdateTexts()
{
if (_disposed)
return;
_playerName.text = string.IsNullOrEmpty(_player.UserName)
? "…"
: _player.UserName;
_gold.text = _player.Gold.ToString();
_dust.text = _player.Dust.ToString();
_tokens.text = _player.Tokens.ToString();
_ranked.text = _player.RankedMmr.ToString();
_casual.text = _player.CasualMmr.ToString();
_record.text = "Матчей: " + _player.Matches + " · побед: " + _player.Wins
+ " · XP: " + _player.Xp;
_onboarding.text = _player.OnboardingCompleted
? "Онбординг завершён: " + (_player.SelectedTrialDeckId ?? "—")
: "Онбординг не завершён: выберите стартовую триал-деку.";
_onboardingButton.gameObject.SetActive(!_player.OnboardingCompleted);
}
private void SetStatus(string text, Color color)
{
if (_disposed || _status == null)
return;
_status.text = text ?? string.Empty;
_status.color = color;
}
private async void OnLogoutClicked()
{
_logout.interactable = false;
await _auth.LogoutAsync();
if (_disposed)
return;
_logout.interactable = true;
_onLoggedOut();
}
}
}