from __future__ import annotations

from dataclasses import dataclass
from pathlib import Path
from collections.abc import Callable

from backend.data import DataGateway, build_data_gateway
from backend.database.repositories import RepositoryBundle, build_repository_bundle
from backend.features.alerts import AlertService
from backend.features.mentor.agent import MentorSkillRegistry
from backend.features.review import TradeJournalService
from backend.features.screener.engine import ScreenerEngine
from backend.features.screener.tracking import StrategyTrackingService
from backend.jobs import InProcessJobRunner, JobRegistry, SQLiteJobRunRepository
from database import ReviewDatabase
from backend.data.providers.ifind_client import IfindHttpClient
from backend.data.realtime import WebRealtimeAggregator
from backend.features.market.charts import MarketChartClient


@dataclass(frozen=True)
class ApplicationContainer:
    database: ReviewDatabase
    repositories: RepositoryBundle
    data_gateway: DataGateway
    ifind: IfindHttpClient
    screener: ScreenerEngine
    strategy_tracking: StrategyTrackingService
    alert_service: AlertService
    trade_journal: TradeJournalService
    mentor_skills: MentorSkillRegistry
    realtime_aggregator: WebRealtimeAggregator
    chart_data: MarketChartClient
    jobs: InProcessJobRunner


def build_application_container(
    database: ReviewDatabase,
    credentials: dict[str, object],
    mentor_skills_dir: Path,
    private_mentor_skills_dir: Path,
    tushare_token_supplier: Callable[[], str] | None = None,
) -> ApplicationContainer:
    data_gateway = build_data_gateway(credentials, tushare_token_supplier)
    repositories = build_repository_bundle(database)
    jobs = InProcessJobRunner(JobRegistry.load(), SQLiteJobRunRepository(database))
    return ApplicationContainer(
        database=database,
        repositories=repositories,
        data_gateway=data_gateway,
        ifind=data_gateway.ifind,
        screener=ScreenerEngine(database),
        strategy_tracking=StrategyTrackingService(repositories.strategy_tracking),
        alert_service=AlertService(repositories.alerts),
        trade_journal=TradeJournalService(repositories.trades),
        mentor_skills=MentorSkillRegistry(mentor_skills_dir, private_mentor_skills_dir),
        realtime_aggregator=data_gateway.realtime_observer,
        chart_data=data_gateway.chart_data,
        jobs=jobs,
    )
