from configparser import SectionProxy
from dataclasses import dataclass

from reactivex import Observable, operators as ops

from clochette.application.service.provider.dto.ProviderDTO import ProviderDTO
from clochette.application.store.ProviderStore import ProviderStore
from clochette.domain.entity.ISourceCalendar import ISourceCalendar


@dataclass
class SourceConfigurationMapperStrategy:
    _provider_store: ProviderStore

    def read(self, section: SectionProxy) -> Observable[ISourceCalendar]:

        def find_provider_for_section(providers: list[ProviderDTO], section: SectionProxy) -> ProviderDTO:
            """Find the provider whose mapper matches this section."""
            for provider_dto in providers:
                if provider_dto.provider_configuration_mapper.match(section):
                    return provider_dto
            raise Exception("Failed to parse calendar configuration, no matching provider found")

        return self._provider_store.providers.pipe(
            ops.take(1),
            ops.map(lambda providers: find_provider_for_section(providers, section)),
            ops.map(lambda p: p.provider_configuration_mapper.read(section)),
        )

    def write(self, source: ISourceCalendar) -> Observable[dict[str, str]]:

        def find_provider_for_source(providers: list[ProviderDTO], source: ISourceCalendar) -> ProviderDTO:
            """Find the provider that matches this source's provider type."""
            for provider_dto in providers:
                if source.provider_type == provider_dto.provider_type:
                    return provider_dto
            raise Exception(f"Unsupported provider type: {source.provider_type}")

        return self._provider_store.providers.pipe(
            ops.take(1),
            ops.map(lambda providers: find_provider_for_source(providers, source)),
            ops.map(lambda p: p.provider_configuration_mapper.write(source)),
        )
