"""Paper trading via Alpaca (compte fictif, argent virtuel).

Nécessite un compte gratuit sur https://alpaca.markets puis, dans un
fichier .env à la racine du projet :

    ALPACA_API_KEY=...
    ALPACA_SECRET_KEY=...

On force TOUJOURS l'environnement « paper » : aucun ordre réel possible ici.
"""
from __future__ import annotations

import os
from pathlib import Path

from dotenv import load_dotenv

load_dotenv(Path(__file__).resolve().parent.parent / ".env")


class NotConfigured(RuntimeError):
    pass


def _client():
    from alpaca.trading.client import TradingClient

    key = os.getenv("ALPACA_API_KEY")
    secret = os.getenv("ALPACA_SECRET_KEY")
    if not key or not secret:
        raise NotConfigured(
            "Clés Alpaca absentes. Crée un compte gratuit sur alpaca.markets, "
            "génère des clés 'Paper Trading' et renseigne ALPACA_API_KEY / "
            "ALPACA_SECRET_KEY dans le fichier .env."
        )
    # paper=True : compte fictif, jamais d'argent réel.
    return TradingClient(key, secret, paper=True)


def account() -> dict:
    a = _client().get_account()
    return {
        "statut": a.status,
        "cash": float(a.cash),
        "valeur_portefeuille": float(a.portfolio_value),
        "pouvoir_achat": float(a.buying_power),
        "devise": a.currency,
    }


def positions() -> list[dict]:
    return [
        {
            "ticker": p.symbol,
            "qté": float(p.qty),
            "PRU": float(p.avg_entry_price),
            "cours": float(p.current_price),
            "valeur": float(p.market_value),
            "P&L": float(p.unrealized_pl),
            "P&L_%": round(float(p.unrealized_plpc) * 100, 2),
        }
        for p in _client().get_all_positions()
    ]


def order(symbol: str, qty: float, side: str = "buy", limit: float | None = None) -> dict:
    """Passe un ordre fictif (paper). side = buy|sell."""
    from alpaca.trading.enums import OrderSide, TimeInForce
    from alpaca.trading.requests import LimitOrderRequest, MarketOrderRequest

    client = _client()
    os_side = OrderSide.BUY if side.lower() == "buy" else OrderSide.SELL
    if limit:
        req = LimitOrderRequest(
            symbol=symbol, qty=qty, side=os_side,
            time_in_force=TimeInForce.DAY, limit_price=limit,
        )
    else:
        req = MarketOrderRequest(
            symbol=symbol, qty=qty, side=os_side, time_in_force=TimeInForce.DAY,
        )
    o = client.submit_order(req)
    return {"id": str(o.id), "ticker": o.symbol, "qté": float(o.qty), "sens": side, "statut": o.status}


if __name__ == "__main__":
    try:
        print("Compte paper :", account())
        print("Positions :", positions())
    except NotConfigured as e:
        print(e)
