"""Mock data provider that loads portfolio data from a Ghostfolio export JSON file.

Computes holdings by replaying all BUY/SELL activities to derive net positions.
Uses the latest transaction price as a proxy for current market price.
"""

from __future__ import annotations

import json
from datetime import UTC, datetime
from pathlib import Path
from typing import Any

_DATA_FILE = Path(__file__).parent / "mock_data" / "large_mock_data.json"

# Sector/region/asset_class lookup for known symbols
_SYMBOL_META: dict[str, dict[str, str]] = {
    # US Large-Cap Tech
    "AAPL": {"name": "Apple Inc.", "sector": "Technology", "region": "North America", "asset_class": "Equity"},
    "MSFT": {"name": "Microsoft Corp.", "sector": "Technology", "region": "North America", "asset_class": "Equity"},
    "GOOGL": {"name": "Alphabet Inc.", "sector": "Technology", "region": "North America", "asset_class": "Equity"},
    "AMZN": {"name": "Amazon.com Inc.", "sector": "Technology", "region": "North America", "asset_class": "Equity"},
    "META": {"name": "Meta Platforms Inc.", "sector": "Technology", "region": "North America", "asset_class": "Equity"},
    "NVDA": {"name": "NVIDIA Corp.", "sector": "Technology", "region": "North America", "asset_class": "Equity"},
    "NFLX": {"name": "Netflix Inc.", "sector": "Technology", "region": "North America", "asset_class": "Equity"},
    "CRM": {"name": "Salesforce Inc.", "sector": "Technology", "region": "North America", "asset_class": "Equity"},
    "PLTR": {
        "name": "Palantir Technologies",
        "sector": "Technology",
        "region": "North America",
        "asset_class": "Equity",
    },
    "COIN": {
        "name": "Coinbase Global Inc.",
        "sector": "Technology",
        "region": "North America",
        "asset_class": "Equity",
    },
    "SPOT": {"name": "Spotify Technology", "sector": "Technology", "region": "Europe", "asset_class": "Equity"},
    "ABNB": {"name": "Airbnb Inc.", "sector": "Technology", "region": "North America", "asset_class": "Equity"},
    "UBER": {"name": "Uber Technologies", "sector": "Technology", "region": "North America", "asset_class": "Equity"},
    "SOFI": {"name": "SoFi Technologies", "sector": "Financials", "region": "North America", "asset_class": "Equity"},
    "INTC": {"name": "Intel Corp.", "sector": "Technology", "region": "North America", "asset_class": "Equity"},
    "AMD": {
        "name": "Advanced Micro Devices",
        "sector": "Technology",
        "region": "North America",
        "asset_class": "Equity",
    },
    "PYPL": {"name": "PayPal Holdings", "sector": "Financials", "region": "North America", "asset_class": "Equity"},
    # US Large-Cap Other
    "TSLA": {"name": "Tesla Inc.", "sector": "Consumer Cyclical", "region": "North America", "asset_class": "Equity"},
    "JPM": {"name": "JPMorgan Chase & Co.", "sector": "Financials", "region": "North America", "asset_class": "Equity"},
    "V": {"name": "Visa Inc.", "sector": "Financials", "region": "North America", "asset_class": "Equity"},
    "MA": {"name": "Mastercard Inc.", "sector": "Financials", "region": "North America", "asset_class": "Equity"},
    "GS": {"name": "Goldman Sachs Group", "sector": "Financials", "region": "North America", "asset_class": "Equity"},
    "JNJ": {"name": "Johnson & Johnson", "sector": "Healthcare", "region": "North America", "asset_class": "Equity"},
    "UNH": {"name": "UnitedHealth Group", "sector": "Healthcare", "region": "North America", "asset_class": "Equity"},
    "PG": {
        "name": "Procter & Gamble",
        "sector": "Consumer Defensive",
        "region": "North America",
        "asset_class": "Equity",
    },
    "HD": {
        "name": "Home Depot Inc.",
        "sector": "Consumer Cyclical",
        "region": "North America",
        "asset_class": "Equity",
    },
    "COST": {
        "name": "Costco Wholesale",
        "sector": "Consumer Defensive",
        "region": "North America",
        "asset_class": "Equity",
    },
    "DIS": {
        "name": "Walt Disney Co.",
        "sector": "Communication Services",
        "region": "North America",
        "asset_class": "Equity",
    },
    "BA": {"name": "Boeing Co.", "sector": "Industrials", "region": "North America", "asset_class": "Equity"},
    "XYZ": {"name": "XYZ Corp.", "sector": "Technology", "region": "North America", "asset_class": "Equity"},
    # ETFs
    "SPY": {"name": "SPDR S&P 500 ETF", "sector": "Diversified", "region": "North America", "asset_class": "ETF"},
    "QQQ": {"name": "Invesco QQQ Trust", "sector": "Technology", "region": "North America", "asset_class": "ETF"},
    "VTI": {
        "name": "Vanguard Total Stock Market ETF",
        "sector": "Diversified",
        "region": "North America",
        "asset_class": "ETF",
    },
    "VOO": {"name": "Vanguard S&P 500 ETF", "sector": "Diversified", "region": "North America", "asset_class": "ETF"},
    "VGT": {"name": "Vanguard Info Tech ETF", "sector": "Technology", "region": "North America", "asset_class": "ETF"},
    "VWO": {
        "name": "Vanguard FTSE Emerging Markets ETF",
        "sector": "Diversified",
        "region": "Emerging Markets",
        "asset_class": "ETF",
    },
    "SCHD": {
        "name": "Schwab US Dividend Equity ETF",
        "sector": "Diversified",
        "region": "North America",
        "asset_class": "ETF",
    },
    "XLF": {
        "name": "Financial Select Sector SPDR",
        "sector": "Financials",
        "region": "North America",
        "asset_class": "ETF",
    },
    "IWM": {
        "name": "iShares Russell 2000 ETF",
        "sector": "Diversified",
        "region": "North America",
        "asset_class": "ETF",
    },
    "ARKK": {"name": "ARK Innovation ETF", "sector": "Technology", "region": "North America", "asset_class": "ETF"},
    # Crypto
    "BTCUSD": {"name": "Bitcoin", "sector": "Cryptocurrency", "region": "Global", "asset_class": "Crypto"},
    "ETHUSD": {"name": "Ethereum", "sector": "Cryptocurrency", "region": "Global", "asset_class": "Crypto"},
    "SOLUSD": {"name": "Solana", "sector": "Cryptocurrency", "region": "Global", "asset_class": "Crypto"},
    "ADAUSD": {"name": "Cardano", "sector": "Cryptocurrency", "region": "Global", "asset_class": "Crypto"},
    "DOTUSD": {"name": "Polkadot", "sector": "Cryptocurrency", "region": "Global", "asset_class": "Crypto"},
    "LINKUSD": {"name": "Chainlink", "sector": "Cryptocurrency", "region": "Global", "asset_class": "Crypto"},
    "MATICUSD": {"name": "Polygon", "sector": "Cryptocurrency", "region": "Global", "asset_class": "Crypto"},
    "AVAXUSD": {"name": "Avalanche", "sector": "Cryptocurrency", "region": "Global", "asset_class": "Crypto"},
}


def _load_data(path: Path | None = None) -> dict[str, Any]:
    """Load and cache the JSON export file."""
    p = path or _DATA_FILE
    with open(p) as f:
        return json.load(f)


def _compute_holdings(activities: list[dict[str, Any]]) -> list[dict[str, Any]]:
    """Replay BUY/SELL activities to compute net positions and cost basis."""
    # Track quantity and total cost per symbol
    positions: dict[str, dict[str, float]] = {}

    # Sort by date to process chronologically
    sorted_activities = sorted(activities, key=lambda a: a.get("date", ""))

    # Track latest price per symbol
    latest_prices: dict[str, float] = {}

    for act in sorted_activities:
        symbol = act.get("symbol", "")
        act_type = act.get("type", "")
        qty = float(act.get("quantity", 0))
        price = float(act.get("unitPrice", 0))

        if not symbol or act_type not in ("BUY", "SELL"):
            # Track dividend prices as latest price reference too
            if act_type == "DIVIDEND" and price > 0:
                # Dividend unit price is per-share dividend, not market price — skip
                pass
            continue

        latest_prices[symbol] = price

        if symbol not in positions:
            positions[symbol] = {"quantity": 0.0, "total_cost": 0.0}

        pos = positions[symbol]
        if act_type == "BUY":
            pos["total_cost"] += qty * price
            pos["quantity"] += qty
        elif act_type == "SELL":
            if pos["quantity"] > 0:
                # Reduce cost proportionally
                avg_cost = pos["total_cost"] / pos["quantity"]
                pos["total_cost"] -= qty * avg_cost
                pos["quantity"] -= qty

    # Build holdings list from positions with quantity > 0
    holdings: list[dict[str, Any]] = []
    for symbol, pos in positions.items():
        if pos["quantity"] <= 0.001:
            continue

        current_price = latest_prices.get(symbol, 0.0)
        market_value = pos["quantity"] * current_price
        cost_basis = pos["total_cost"]
        perf_pct = ((market_value - cost_basis) / cost_basis * 100) if cost_basis > 0 else 0.0

        meta = _SYMBOL_META.get(symbol, {})
        holdings.append(
            {
                "symbol": symbol,
                "name": meta.get("name", symbol),
                "quantity": pos["quantity"],
                "value": round(market_value, 2),
                "cost_basis": round(cost_basis, 2),
                "performance_pct": round(perf_pct, 2),
                "current_price": current_price,
                "sector": meta.get("sector", "Unknown"),
                "region": meta.get("region", "Unknown"),
                "asset_class": meta.get("asset_class", "Unknown"),
            }
        )

    # Sort by value descending
    holdings.sort(key=lambda h: h["value"], reverse=True)

    # Compute allocation percentages
    total_value = sum(h["value"] for h in holdings)
    for h in holdings:
        h["allocation_pct"] = round(h["value"] / total_value * 100, 2) if total_value > 0 else 0.0

    return holdings


class MockFileDataProvider:
    """Portfolio data provider backed by a Ghostfolio JSON export file."""

    def __init__(self, path: Path | None = None) -> None:
        self._data = _load_data(path)
        self._activities = self._data.get("activities", [])
        self._accounts_raw = self._data.get("accounts", [])
        self._holdings: list[dict[str, Any]] | None = None

    def _get_holdings(self) -> list[dict[str, Any]]:
        if self._holdings is None:
            self._holdings = _compute_holdings(self._activities)
        return self._holdings

    async def get_portfolio_summary(self, account_id: str | None = None) -> dict[str, Any]:
        holdings = self._get_holdings()

        if account_id:
            # Filter activities by account, recompute holdings
            filtered = [a for a in self._activities if a.get("accountId") == account_id]
            holdings = _compute_holdings(filtered)

        total_value = sum(h["value"] for h in holdings)
        return {
            "total_value": round(total_value, 2),
            "currency": "USD",
            "holdings_count": len(holdings),
            "holdings": holdings,
        }

    async def get_performance(self, query_range: str) -> dict[str, Any]:
        holdings = self._get_holdings()
        total_value = sum(h["value"] for h in holdings)
        total_cost = sum(h["cost_basis"] for h in holdings)
        absolute_gain = total_value - total_cost
        return_pct = (absolute_gain / total_cost * 100) if total_cost > 0 else 0.0

        # Scale performance by range (rough approximation)
        scale = {
            "1d": 0.003,
            "1w": 0.02,
            "1m": 0.08,
            "ytd": 0.15,
            "1y": 0.4,
            "5y": 1.0,
            "max": 1.0,
        }
        factor = scale.get(query_range, 1.0)

        return {
            "range": query_range,
            "return_pct": round(return_pct * factor, 2),
            "absolute_gain": round(absolute_gain * factor, 2),
            "currency": "USD",
            "last_updated": datetime.now(UTC).isoformat().replace("+00:00", "Z"),
        }

    async def get_transactions(self) -> list[dict[str, Any]]:
        transactions: list[dict[str, Any]] = []
        for act in self._activities:
            transactions.append(
                {
                    "date": act.get("date", "")[:10],  # YYYY-MM-DD
                    "type": act.get("type", ""),
                    "symbol": act.get("symbol", ""),
                    "quantity": float(act.get("quantity", 0)),
                    "unit_price": float(act.get("unitPrice", 0)),
                    "fee": float(act.get("fee", 0)),
                    "currency": act.get("currency", "USD"),
                }
            )
        return transactions

    async def get_accounts(self) -> list[dict[str, Any]]:
        accounts: list[dict[str, Any]] = []
        for item in self._accounts_raw:
            accounts.append(
                {
                    "id": item.get("id", ""),
                    "name": item.get("name", "Unknown"),
                    "balance": float(item.get("balance", 0)),
                    "currency": item.get("currency", "USD"),
                    "platform": item.get("name", "Unknown"),
                    "is_excluded": bool(item.get("isExcluded", False)),
                }
            )
        return accounts

    async def get_market_data(self, symbols: list[str]) -> dict[str, Any]:
        holdings = self._get_holdings()
        lookup = {s.upper() for s in symbols}
        result: dict[str, Any] = {}
        for h in holdings:
            sym = h["symbol"].upper()
            if sym in lookup:
                result[sym] = {
                    "symbol": h["symbol"],
                    "name": h["name"],
                    "price": h["current_price"],
                    "currency": "USD",
                    "change_pct": h.get("performance_pct", 0.0),
                }
        return result
