from __future__ import annotations

from dataclasses import dataclass

from backend.bootstrap.settings import PROJECT_ROOT, Settings
from backend.data.gateway import DataGateway
from backend.data.policy import DataSourcePolicy
from backend.data.providers import EastmoneyProvider, IfindProvider, TushareProvider
from backend.data.repository import MarketRepository
from backend.database.connection import Database
from backend.database.repositories.status import DatabaseStatusRepository
from backend.features.accounts.credentials import SystemCredentialService
from backend.features.accounts.model_pool import ModelPoolRepository, ModelPoolService
from backend.features.accounts.repository import AccountRepository, SystemCredentialRepository
from backend.features.accounts.service import (
    AccountService,
    MembershipService,
)
from backend.features.heaven.repository import HeavenRepository
from backend.features.heaven.service import HeavenService
from backend.features.market import MarketService
from backend.features.market.events import MarketEventService
from backend.features.market.insights import MarketInsightService
from backend.features.market.sync import MarketSnapshotService
from backend.features.mentor.context import MentorContextBuilder
from backend.features.mentor.repository import MentorRepository
from backend.features.mentor.service import MentorService
from backend.features.mentor.skills import MentorSkillRegistry
from backend.features.operations import OperationsService
from backend.features.review import ReviewService
from backend.features.review.repository import ReviewRepository
from backend.features.screener.repository import ScreenerRepository
from backend.features.screener.service import ScreenerService
from backend.jobs.repository import JobRepository
from backend.jobs.service import JobService
from backend.llm import LLMGateway
from backend.llm.repository import LLMRepository
from backend.security import PasswordHasher, load_or_create_cipher


@dataclass(frozen=True, slots=True)
class ApplicationContainer:
    settings: Settings
    database: Database
    database_status: DatabaseStatusRepository
    accounts: AccountService
    memberships: MembershipService
    system_credentials: SystemCredentialService
    model_pool: ModelPoolService
    market: MarketService
    screener: ScreenerService
    llm: LLMGateway
    mentor: MentorService
    heaven: HeavenService
    review: ReviewService
    operations: OperationsService


def build_container(settings: Settings) -> ApplicationContainer:
    database = Database(settings.database_path)
    account_repository = AccountRepository()
    credential_repository = SystemCredentialRepository()
    model_pool_repository = ModelPoolRepository()
    screener_repository = ScreenerRepository()
    cipher = load_or_create_cipher(settings)
    credentials = SystemCredentialService(database, credential_repository, cipher)
    tushare = TushareProvider(lambda: credentials.get("tushare_token"))
    market_repository = MarketRepository()
    review_repository = ReviewRepository()
    gateway = DataGateway(
        database,
        market_repository,
        (
            tushare,
            IfindProvider(
                lambda: credentials.get("ifind_refresh_token"),
                lambda: credentials.get("ifind_access_token"),
            ),
            EastmoneyProvider(),
        ),
        DataSourcePolicy(),
    )
    market = MarketService(
        gateway,
        MarketSnapshotService(database, market_repository, gateway),
        MarketInsightService(database, market_repository, review_repository, gateway),
    )
    accounts = AccountService(database, account_repository, PasswordHasher(), cipher)
    llm_repository = LLMRepository()
    memberships = MembershipService(database, account_repository, llm_repository)
    model_pool = ModelPoolService(database, model_pool_repository, cipher)
    llm = LLMGateway(database, llm_repository, memberships, model_pool)
    screener = ScreenerService(
        database, screener_repository, market_repository, gateway, llm
    )
    mentor = MentorService(
        database,
        MentorRepository(),
        MentorSkillRegistry(
            settings.mentor_skills_directory,
            settings.private_mentor_skills_directory,
        ),
        MentorContextBuilder(database, market_repository, screener_repository, gateway),
        gateway,
        llm,
    )
    heaven = HeavenService(
        database,
        HeavenRepository(),
        gateway,
        accounts,
        llm,
        PROJECT_ROOT / "config" / "heaven" / "iching_zh.json",
    )
    review = ReviewService(database, review_repository, gateway, screener, llm)
    jobs = JobService(database, JobRepository())
    events = MarketEventService(database, market_repository, gateway)
    operations = OperationsService(
        database, market_repository, market, events, screener, jobs
    )
    return ApplicationContainer(
        settings=settings,
        database=database,
        database_status=DatabaseStatusRepository(database),
        accounts=accounts,
        memberships=memberships,
        system_credentials=credentials,
        model_pool=model_pool,
        market=market,
        screener=screener,
        llm=llm,
        mentor=mentor,
        heaven=heaven,
        review=review,
        operations=operations,
    )
