from dataclasses import fields
from urllib.parse import urlparse
from abc import ABC, abstractmethod, abstractproperty
import logging

from airflow.models.dag import DAG
from airflow.utils.task_group import TaskGroup
from airflow.operators.python_operator import PythonOperator
from airflow.providers.google.cloud.transfers.gcs_to_bigquery import GCSToBigQueryOperator

from gcp_airflow_foundations.base_class.salesforce_ingestion_config import SalesforceIngestionConfig

from gcp_airflow_foundations.operators.api.operators.sf_to_gcs_query_operator import SalesforceToGcsQueryOperator
from gcp_airflow_foundations.base_class.data_source_table_config import DataSourceTablesConfig
from gcp_airflow_foundations.source_class.source import DagBuilder
from gcp_airflow_foundations.common.gcp.load_builder import load_builder


class FTPtoBQDagBuilder(DagBuilder):
    """
    Builds DAGs to load files from FTP to a BigQuery Table.
    """

    def set_schema_method_type(self):
        self.schema_source_type = self.config.source.schema_options.schema_source_type     

    def get_bq_ingestion_task(self, table_config):
        taskgroup = TaskGroup(group_id="ftp_taskgroup")

        sensor_task = self.get_file_sensor(table_config)
        sensor_task.task_group = taskgroup

        file_ingestion_task = self.file_ingestion_task(table_config)
        file_ingestion_task.task_group = taskgroup

        load_to_landing_task = self.load_to_landing_task(table_config)
        load_to_landing_task.task_group = taskgroup

        sensor_task >> file_ingestion_task >> load_to_landing_task

        return taskgroup

    @abstractmethod
    def metadata_file_tasks(self, table_config):
        pass

    @abstractmethod
    def file_ingestion_task(self, table_config):
        """
        Implements an Airflow task to ingest the files from the FTP source into GCS (e.g. from an SFTP server or an AWS bucket)
        """
        pass

    @abstractmethod
    def file_sensor(self, table_config):
        """
        Returns an Airflow sensor that waits for the list of files specified by either
        (1) the metadata file provided, or
        (2) the files provided in the config
        """
        pass

    @abstractmethod
    def load_to_landing_task(self, table_config):
        pass

    def validate_extra_options(self):
        tables = self.config.tables