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.review import TradeJournalService from backend.features.screener import StrategyTrackingService from backend.jobs import InProcessJobRunner, JobRegistry, SQLiteJobRunRepository from chart_data_provider import MarketChartClient from database import ReviewDatabase from ifind_client import IfindHttpClient from mentor_agent import MentorSkillRegistry from realtime_aggregator import WebRealtimeAggregator from screener import ScreenerEngine @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, )