from __future__ import annotations

import argparse
import json
import os
from datetime import datetime, timezone
from pathlib import Path

from investly.domain import Market, Strategy
from investly.email.render import preopen_email
from investly.providers.router import ProviderRouter
from investly.providers.sahmk import SahmkProvider
from investly.providers.yahoo import YahooProvider
from investly.runtime.store import RuntimeStore
from investly.service import AnalysisService


def provider_for(market: Market) -> ProviderRouter:
    yahoo = YahooProvider()
    if market == Market.TASI and os.getenv("SAHMK_API_KEY"):
        return ProviderRouter(SahmkProvider(), [yahoo])
    return ProviderRouter(yahoo, [])


def main() -> None:
    parser = argparse.ArgumentParser()
    subparsers = parser.add_subparsers(dest="cmd", required=True)
    analyze = subparsers.add_parser("analyze")
    analyze.add_argument("--market", choices=[market.value for market in Market], default="TASI")
    analyze.add_argument("--symbols", required=True)
    analyze.add_argument("--budget", type=float, default=100000)
    analyze.add_argument("--out", default="out")
    args = parser.parse_args()

    if args.cmd == "analyze":
        market = Market(args.market)
        symbols = [symbol.strip() for symbol in args.symbols.split(",") if symbol.strip()]
        recommendations = AnalysisService(provider_for(market)).analyze(market, symbols)
        store = RuntimeStore(os.getenv("INVESTLY_RUNTIME_DB", "sqlite:///investly-runtime.db"))
        session_id = datetime.now(timezone.utc).date().isoformat()
        portfolios = {
            strategy: store.load_or_create_portfolio(market.value, strategy.value, args.budget)
            for strategy in Strategy
        }
        actions = []
        for recommendation in recommendations:
            store.append_recommendation(recommendation, session_id)
            portfolio = portfolios[recommendation.strategy]
            action = portfolio.apply(recommendation)
            actions.append(action)
            store.append_action(action, market.value, recommendation.engine_version)
            store.save_portfolio(market.value, recommendation.strategy.value, portfolio)

        out = Path(args.out)
        out.mkdir(parents=True, exist_ok=True)
        summaries = {
            portfolio.portfolio_id: (portfolio.initial_cash, portfolio.cash)
            for portfolio in portfolios.values()
        }
        html, text = preopen_email(market.value, recommendations, actions, summaries)
        (out / "preopen.html").write_text(html, encoding="utf-8")
        (out / "preopen.txt").write_text(text, encoding="utf-8")
        (out / "recommendations.json").write_text(
            json.dumps([recommendation.to_dict() for recommendation in recommendations], indent=2),
            encoding="utf-8",
        )
        print(json.dumps({
            "recommendations": len(recommendations),
            "session": session_id,
            "portfolios": {
                portfolio.portfolio_id: {
                    "initial_cash": portfolio.initial_cash,
                    "cash": portfolio.cash,
                    "positions": len(portfolio.positions),
                }
                for portfolio in portfolios.values()
            },
            "out": str(out),
        }, indent=2))


if __name__ == "__main__":
    main()
