from dataclasses import dataclass

from reactivex import operators as ops, Observable

from clochette import log
from clochette.application.service.provider.dto.ProviderDTO import ProviderDTO
from clochette.application.store.ProviderStore import ProviderStore
from clochette.domain.entity.ICredentialCalendar import ICredentialCalendar
from clochette.domain.entity.configuration.CalendarConfiguration import CalendarConfiguration
from clochette.framework.rx.Scheduler import scheduler


@dataclass
class SaveCredentialUseCase:
    """Use case to save calendar credentials to the provider's keyring."""

    _provider_store: ProviderStore

    def save_credentials(self, calendar: CalendarConfiguration, credentials: ICredentialCalendar) -> Observable[None]:
        """Save credentials for a calendar using the provider's keyring service."""

        def store(provider_dto: ProviderDTO) -> None:
            if provider_dto.keyring is not None:
                provider_dto.keyring.store_auth(calendar.id, credentials)

        return self._provider_store.get_by_type(calendar.source.provider_type).pipe(
            ops.do_action(on_next=store),
            ops.map(lambda _: None),
            ops.do_action(
                on_error=lambda e: log.error(f"Failed to save credentials for calendar: {calendar.name}", exc_info=e)
            ),
            ops.subscribe_on(scheduler=scheduler),
        )
