import threading
from typing import Optional

from ...infrastructure.elasticsearch.client import ElasticsearchClient
from ...infrastructure.repositories.consultor_repository_impl import ConsultorRepositoryImpl
from ...infrastructure.oracle.client import OracleClient
from ...infrastructure.oracle.ranking_repository import RankingOracleRepository
from ...application.jobs.processar_ranking import ProcessarRankingJob
from ...infrastructure.ranking_store import ranking_store, RankingStore
from .config import settings


es_client = ElasticsearchClient(
    url=settings.ES_URL,
    index=settings.ES_INDEX,
    user=settings.ES_USER,
    password=settings.ES_PASSWORD,
    verify_ssl=settings.ES_VERIFY_SSL,
)

oracle_client: Optional[OracleClient] = OracleClient(
    user=settings.ORACLE_LOCAL_USER,
    password=settings.ORACLE_LOCAL_PASSWORD,
    dsn=settings.ORACLE_LOCAL_DSN,
) if settings.ORACLE_LOCAL_USER and settings.ORACLE_LOCAL_DSN else None

ranking_oracle_repo: Optional[RankingOracleRepository] = RankingOracleRepository(oracle_client) if oracle_client else None

_repository: Optional[ConsultorRepositoryImpl] = None
_processar_job: Optional[ProcessarRankingJob] = None
_lock = threading.Lock()


def get_repository() -> ConsultorRepositoryImpl:
    global _repository
    if _repository is None:
        with _lock:
            if _repository is None:
                _repository = ConsultorRepositoryImpl(es_client=es_client, oracle_client=oracle_client)
    return _repository


def get_ranking_store() -> RankingStore:
    return ranking_store


def get_oracle_client() -> OracleClient:
    return oracle_client


def get_es_client() -> ElasticsearchClient:
    return es_client


def get_ranking_oracle_repo() -> RankingOracleRepository:
    return ranking_oracle_repo


def get_processar_job() -> ProcessarRankingJob:
    global _processar_job
    if _processar_job is None:
        with _lock:
            if _processar_job is None:
                _processar_job = ProcessarRankingJob(
                    es_client=es_client,
                    ranking_store=ranking_store,
                    ranking_oracle_repo=ranking_oracle_repo,
                )
    return _processar_job
