from dataclasses import dataclass

from reactivex import operators as ops

from clochette.application.service.provider.dto.ProviderDTO import ProviderDTO
from clochette.application.service.provider.dto.ProviderType import ProviderType
from clochette.application.store.ProviderStore import ProviderStore
from clochette.domain.entity.CalendarID import CalendarID
from clochette.domain.entity.ICredentialCalendar import ICredentialCalendar
from clochette.domain.entity.ISourceCalendar import ISourceCalendar
from clochette.framework.qt.QComponent import QComponent
from clochette.framework.rx.Scheduler import scheduler
from clochette.presentation.settings.calendar.provider.ProviderModel import ProviderModel
from clochette.presentation.settings.calendar.provider.QAuthenticationSourceView import QAuthenticationSourceView


@dataclass
class QAuthenticationSourceComponent(QComponent[QAuthenticationSourceView]):
    """Component that handles provider-specific authentication logic"""

    _view: QAuthenticationSourceView
    _provider_store: ProviderStore
    _provider_model: ProviderModel

    def __post_init__(self):
        super().__init__(self._view)

        self._provider_store.providers.pipe(
            ops.do_action(on_next=lambda providers: self._on_providers_loaded(providers)),
        ).subscribe(scheduler=scheduler)

    def _on_providers_loaded(self, providers: list[ProviderDTO]) -> None:
        self._provider_model.set_providers(providers)
        self._view.set_providers(providers)

    def set_source(self, calendar_id: CalendarID, source: ISourceCalendar) -> None:
        """Set values in the appropriate provider panel based on source type"""
        provider = self._provider_model.get_provider(source.provider_type)
        provider.authentication_component.set_source(calendar_id, source)
        self._view.set_selected_provider_type(provider.provider_type)

    def validate(self) -> bool:
        """Validate the currently selected provider's authentication component."""
        provider = self._provider_model.get_provider(self._view.get_selected_provider_type())
        return provider.authentication_component.validate()

    @property
    def source(self) -> tuple[ISourceCalendar, ICredentialCalendar]:
        """Get the calendar source from the selected provider panel"""
        provider = self._provider_model.get_provider(self._view.get_selected_provider_type())
        return (
            provider.authentication_component.get_source(),
            provider.authentication_component.get_credentials(),
        )

    def clear(self) -> None:
        """Clear all provider panels"""
        for provider in self._provider_model.get_all_providers():
            provider.authentication_component.clear()

    def set_provider_type(self, provider_type: ProviderType) -> None:
        """Set the selected provider type"""
        self._view.set_selected_provider_type(provider_type)
