# ---
# jupyter:
#   jupytext:
#     formats: ipynb,py:percent
#     text_representation:
#       extension: .py
#       format_name: percent
#       format_version: '1.3'
#       jupytext_version: 1.19.1
#   kernelspec:
#     display_name: Python 3
#     language: python
#     name: python3
# ---

# %% [markdown]
# # End-to-end platform example
#
# This notebook shows one deterministic local flow:
#
# - file adapters create market-data and reference-data providers
# - the engine builder composes the pricing engine
# - a small basket is priced through batch routing
# - ETF and portfolio aggregates are computed from the priced basket

# %%
from __future__ import annotations

import sys
from decimal import Decimal
from pathlib import Path

root = Path.cwd()
if (root / "src").exists():
    sys.path.insert(0, str(root / "src"))
elif (root.parent / "src").exists():
    sys.path.insert(0, str(root.parent / "src"))
    root = root.parent

fixtures = root / "tests" / "data"

# %% [markdown]
# ## Imports

# %%
from fuggers_py.core import Date  # noqa: E402
from fuggers_py.engine import EtfPricer, PortfolioAnalyzer, PortfolioPosition, PricingEngineBuilder, PricingInput  # noqa: E402
from fuggers_py.io import create_empty_output, create_file_market_data, create_file_reference_data  # noqa: E402
from fuggers_py.data import (
    EtfHolding,
    InstrumentId,
    QuoteSide,
)

# %% [markdown]
# ## Load deterministic providers from fixtures

# %%
market_data = create_file_market_data(
    quotes_csv=fixtures / "quotes.csv",
    curve_inputs_json=fixtures / "curve_inputs.json",
    fixings_csv=fixtures / "fixings.csv",
)
reference_data = create_file_reference_data(bonds_csv=fixtures / "bonds.csv")
settlement = Date.from_ymd(2026, 3, 13)

# %%
market_data.get_quote("US1234567890", QuoteSide.MID), reference_data.get_bond_reference("US1234567890")

# %% [markdown]
# ## Build the engine

# %%
engine = (
    PricingEngineBuilder()
    .with_market_data_provider(market_data)
    .with_reference_data_provider(reference_data)
    .with_output_publisher(create_empty_output())
    .with_settlement_date(settlement)
    .build()
)

curve_bundle = engine.curve_builder.bundle(discount_curve="usd.discount")
curve_bundle

# %% [markdown]
# ## Prepare a small basket for batch pricing

# %%
fixed_id = InstrumentId("US1234567890")
callable_id = InstrumentId("US0987654321")

fixed_reference = reference_data.get_bond_reference(fixed_id)
callable_reference = reference_data.get_bond_reference(callable_id)

fixed_quote = market_data.get_quote(fixed_id, QuoteSide.MID)
callable_quote = market_data.get_quote(callable_id, QuoteSide.BID)

pricing_inputs = [
    PricingInput(
        instrument=fixed_reference.to_instrument(),
        settlement_date=settlement,
        market_price=fixed_quote.value,
        curves=curve_bundle,
        instrument_id=fixed_id,
    ),
    PricingInput(
        instrument=callable_reference.to_instrument(),
        settlement_date=settlement,
        market_price=callable_quote.value,
        curves=curve_bundle,
        instrument_id=callable_id,
    ),
]

pricing_inputs

# %% [markdown]
# ## Price the basket

# %%
batch_result = engine.pricing_router.price_batch(pricing_inputs)
quote_outputs = {InstrumentId.parse(key): value for key, value in batch_result.outputs.items()}

quote_outputs

# %% [markdown]
# ## Aggregate ETF and portfolio views

# %%
holdings = [
    EtfHolding(fixed_id, quantity=Decimal("100")),
    EtfHolding(callable_id, quantity=Decimal("50")),
]
positions = [
    PortfolioPosition(fixed_id, Decimal("100")),
    PortfolioPosition(callable_id, Decimal("50")),
]
reference_map = {
    fixed_reference.instrument_id: fixed_reference,
    callable_reference.instrument_id: callable_reference,
}

etf_output = EtfPricer().price(
    "fixture-etf",
    holdings,
    quote_outputs,
    shares_outstanding=Decimal("1000"),
)
portfolio_output = PortfolioAnalyzer().analyze(
    "fixture-portfolio",
    positions,
    quote_outputs,
    reference_data=reference_map,
)

etf_output, portfolio_output

# %% [markdown]
# ## Summarize the full flow

# %%
summary = {
    "engine_type": type(engine).__name__,
    "priced_ids": [key.as_str() for key in quote_outputs],
    "batch_errors": len(batch_result.errors),
    "etf_nav": etf_output.nav,
    "portfolio_market_value": portfolio_output.total_market_value,
    "portfolio_weighted_duration": portfolio_output.weighted_duration,
    "portfolio_dv01": portfolio_output.aggregate_dv01,
}
print(summary)
