using System; using System.Collections.Generic; using UnityEngine; using UnityEngine.Networking; using UnityEngine.UI; using UnityEngine.SceneManagement; using TMPro; using Newtonsoft.Json; using CommanderAILab.Models; using CommanderAILab.Services; namespace CommanderAILab.UI { /// /// DeckGenerator scene — AI deck generation wizard: /// commander pick, strategy/budget inputs, precon base, /// streaming progress, result preview, save to DeckBuilder. /// public class DeckGeneratorController : MonoBehaviour { // ── Navigation ──────────────────────────────────────────────────── [Header("Navigation")] [SerializeField] private Button backButton; // ── Step 1: Commander Selection ─────────────────────────────────── [Header("Step 1 - Commander")] [SerializeField] private TMP_InputField commanderSearchInput; [SerializeField] private Button commanderSearchButton; [SerializeField] private Transform commanderResultParent; [SerializeField] private GameObject commanderResultRowPrefab; [SerializeField] private TMP_Text selectedCommanderLabel; // ── Step 2: Strategy & Budget ───────────────────────────────────── [Header("Step 2 - Strategy & Budget")] [SerializeField] private TMP_Dropdown strategyDropdown; // Aggro/Control/Combo/Midrange/Stax/Chaos [SerializeField] private TMP_Dropdown budgetDropdown; // Pauper/$50/$100/$250/No limit [SerializeField] private TMP_InputField synergiesInput; // free-text themes [SerializeField] private TMP_Dropdown preconBaseDropdown; // optional precon starting point [SerializeField] private Toggle ownedOnlyToggle; // restrict to owned cards // ── Step 3: Generate ────────────────────────────────────────────── [Header("Step 3 - Generate")] [SerializeField] private Button generateButton; [SerializeField] private GameObject progressPanel; [SerializeField] private Slider progressSlider; [SerializeField] private TMP_Text progressText; // ── Step 4: Result Preview ──────────────────────────────────────── [Header("Step 4 - Result")] [SerializeField] private GameObject resultPanel; [SerializeField] private Transform resultCardListParent; [SerializeField] private GameObject resultCardRowPrefab; [SerializeField] private TMP_Text resultSummaryText; [SerializeField] private TMP_Text resultManaCurveText; [SerializeField] private Button saveToDeckBuilderButton; [SerializeField] private Button regenerateButton; // ── Error ───────────────────────────────────────────────────────── [Header("Error")] [SerializeField] private GameObject errorPanel; [SerializeField] private TMP_Text errorText; [SerializeField] private Button retryButton; // ── State ───────────────────────────────────────────────────────── private CardModel _selectedCommander; private DeckGenResponse _lastResult; private List _commanderRows = new(); private List _resultRows = new(); private List _preconNames = new(); // ── Lifecycle ───────────────────────────────────────────────────── private void Start() { backButton.onClick.AddListener(() => SceneManager.LoadScene("MainMenu")); commanderSearchButton.onClick.AddListener(OnCommanderSearch); commanderSearchInput.onSubmit.AddListener(_ => OnCommanderSearch()); generateButton.onClick.AddListener(OnGenerate); saveToDeckBuilderButton.onClick.AddListener(OnSaveToDeckBuilder); regenerateButton.onClick.AddListener(OnGenerate); retryButton.onClick.AddListener(OnGenerate); progressPanel.SetActive(false); resultPanel.SetActive(false); errorPanel.SetActive(false); LoadPrecons(); } // ── Precon list ─────────────────────────────────────────────────── private void LoadPrecons() { ApiClient.Instance.GetPrecons( json => { try { var wrapper = JsonConvert.DeserializeObject(json); _preconNames = wrapper?.precons ?? new List(); } catch { _preconNames = new List(); } var options = new List { new("None (from scratch)") }; foreach (var p in _preconNames) options.Add(new TMP_Dropdown.OptionData(p)); preconBaseDropdown.options = options; preconBaseDropdown.value = 0; }, err => Debug.LogWarning($"[DeckGen] Could not load precons: {err}")); } // ── Commander Search ────────────────────────────────────────────── private void OnCommanderSearch() { string q = commanderSearchInput.text.Trim(); if (string.IsNullOrEmpty(q)) return; string path = $"/api/collection?search={UnityWebRequest.EscapeURL(q)}&type=Legendary+Creature&per_page=20"; ApiClient.Instance.GetRaw(path, json => PopulateCommanderResults(json), err => ShowError($"Commander search failed:\n{err}")); } private void PopulateCommanderResults(string json) { foreach (var go in _commanderRows) if (go) Destroy(go); _commanderRows.Clear(); List cards; try { var resp = JsonConvert.DeserializeObject(json); cards = resp?.cards ?? new List(); } catch { return; } foreach (var card in cards) { var row = Instantiate(commanderResultRowPrefab, commanderResultParent); _commanderRows.Add(row); var label = row.GetComponentInChildren(); if (label) label.text = $"{card.name} — {card.manaCost}"; var btn = row.GetComponentInChildren