import os
import logging
import configparser
import warnings
import pandas as pd
import gspread
from gspread.exceptions import APIError

warnings.filterwarnings("ignore", category=UserWarning)

logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s',
    datefmt='%Y-%m-%d %H:%M:%S',
)


class GGSheetUtils:
    """
    Utils for Google Sheets

    :param email: The client email address
    :param private_key: The client private key

    If two aboved params are not provided
        the default credentials will be used
    """
    def __init__(
        self,
        email: str = None,
        private_key: str = None,
    ) -> None:
        self.current_dir = os.path.dirname(__file__)
        self.config_dir = self.current_dir + '/config.ini'
        self.config = configparser.ConfigParser()
        self.config.read(self.config_dir)

        self.email = email
        self.private_key = private_key

        if self.email and self.private_key:
            self.credentials = {
                'client_email': self.email,
                'private_key': self.private_key,
                'token_uri': 'https://oauth2.googleapis.com/token',
            }
        else:
            self.credentials = {
                'client_email': eval(
                    self.config.get(
                        'da_credentials',
                        'email',
                    )
                ),
                'private_key': eval(
                    self.config.get(
                        'da_credentials',
                        'private_key',
                    )
                ),
                'token_uri': 'https://oauth2.googleapis.com/token',
            }

        self.client = gspread.service_account_from_dict(self.credentials)

    def get_data(
        self,
        sheet_id: str,
        sheet_name: str = None,
        range_from: str = 'A',
        range_to: str = 'Z',
        columns_first_row: bool = False,
    ) -> pd.DataFrame:
        """
        Get data from the given sheet

        :param sheet_id: the id of the sheet
        :param sheet_name: the name of the sheet
            defaults to None
        :param range_from: the begining of the range
            of data from sheet to get
            defaults to A
        :param range_to: the end of the range
            of data from sheet to get
            defaults to Z
        :param columns_first_row: whether to convert the first row
            to columns
            defaults to False

        :return: the dataframe contains data from sheet
        """

        url_content = self.client.open_by_url(
            f'https://docs.google.com/spreadsheets/d/{sheet_id}'
        )

        data_range = f'{range_from}:{range_to}'
        if sheet_name:
            data_range = f'{sheet_name}!{data_range}'

        try:
            data = url_content.values_get(data_range)['values']
            df = pd.DataFrame(data)
            if columns_first_row:
                df.columns = df.iloc[0].to_list()
                df = df.iloc[1:].reset_index(drop=True)
        except APIError as e:
            logging.error(e)
            df = pd.DataFrame()

        return df
