from __future__ import annotations

from typing import Any

import streamlit as st
import yfinance as yf


@st.cache_data(show_spinner=False, ttl=3600)
def lookup_symbol_candidates(query: str, max_results: int = 10) -> list[dict[str, str]]:
    cleaned = query.strip()
    if len(cleaned) < 2:
        return []

    try:
        search = yf.Search(cleaned, max_results=max_results)
        quotes = getattr(search, "quotes", []) or []
    except Exception:
        return []

    seen_symbols: set[str] = set()
    candidates: list[dict[str, str]] = []
    for quote in quotes:
        symbol = str(quote.get("symbol", "")).strip().upper()
        if not symbol or symbol in seen_symbols:
            continue

        seen_symbols.add(symbol)
        candidates.append(
            {
                "symbol": symbol,
                "name": str(quote.get("shortname") or quote.get("longname") or "").strip(),
                "exchange": str(quote.get("exchDisp") or quote.get("exchange") or "").strip(),
                "type": str(quote.get("typeDisp") or quote.get("quoteType") or "").strip(),
            }
        )
    return candidates


@st.cache_data(show_spinner=False, ttl=3600)
def resolve_symbol_identity(symbol: str) -> dict[str, str]:
    normalized_symbol = symbol.strip().upper()
    if not normalized_symbol:
        return {"symbol": "", "name": "", "exchange": ""}

    def _from_quote(quote: dict[str, Any]) -> dict[str, str]:
        return {
            "symbol": normalized_symbol,
            "name": str(quote.get("shortname") or quote.get("longname") or "").strip(),
            "exchange": str(quote.get("exchDisp") or quote.get("exchange") or "").strip(),
        }

    try:
        search = yf.Search(normalized_symbol, max_results=8)
        quotes = getattr(search, "quotes", []) or []
        for quote in quotes:
            candidate_symbol = str(quote.get("symbol", "")).strip().upper()
            if candidate_symbol == normalized_symbol:
                return _from_quote(quote)
        if quotes:
            return _from_quote(quotes[0])
    except Exception:
        pass

    try:
        info = yf.Ticker(normalized_symbol).info
        return {
            "symbol": normalized_symbol,
            "name": str(info.get("shortName") or info.get("longName") or "").strip(),
            "exchange": str(info.get("exchange") or "").strip(),
        }
    except Exception:
        return {"symbol": normalized_symbol, "name": "", "exchange": ""}
