from typing import Literal, List
from .service import get_service
from googleapiclient.errors import HttpError
from typing import Optional
from .drive import delete_file

def create_spreadsheet(title: str) -> dict:
    """Create a spreadsheet in Google Sheets.

    Args:
        title (str): Title of the spreadsheet.

    Returns:
        dict: Dictionary containing the spreadsheet ID,
            e.g. `{"spreadsheetId": "ID of the spreadsheet"}`.

    Example:
        ```python
        def test_create_sheet():
            try:
                sheet = create_spreadsheet(title='Test')
                print(f'Test case passed: {sheet}')
            except Exception as e:
                print(f'Error creating sheet: {e}')
        ```
    """
    try:
        service= get_service(service_name= "sheets")
        spreadsheet = {"properties": {"title": title}}
        spreadsheet = (
            service.spreadsheets()
            .create(body=spreadsheet, fields="spreadsheetId")
            .execute()
        )
        return spreadsheet
    except HttpError as error:
        return {'Error': error}

def read_spreadsheet(spreadsheet_id: str, cells_range: str, sheet_name: Optional[str]= None) -> dict:
    """
    To read the spreadsheet in google sheets.

    Args:
        spreadsheet_id (str): Spreadsheet id
        cells_range (str): Range of the cells - It will decide how many cells will be read (range will be like A1:C2)
        sheet_name (str): As a single spreadsheet can have multiple sheets, this parameter takes the specific
                            name of the sheet to retrieve the data from. If value not provided, It
                            will retrieve from first sheet in the spreadsheet.
    Returns:
        dict: Dictionary with information and Data.
                Like:
                {'range': 'Sheet1!A1:C2', 'majorDimension': 'ROWS', 'values': [['1', '2', '3'], ['4', '5', '6']]}
    Example:
            ```python
        def test_read_spreadsheet():
            try:
                data = read_spreadsheet(
                    spreadsheet_id="1MIzcEON-5G4sBPoPQPMEQeRi22CtTA4AZxNjqwkg-CE",
                    cells_range= "A1:C2",
                    sheet_name= "Sheet1"
                )
                return f'Test case passed: {data}'
            except Exception as e:
                return f'Error retrieving data: {e}'
            ```
    """
    try:
        service= get_service(service_name= "sheets")
        sheet_cell_range= f"{sheet_name}!{cells_range}"
        result = (
            service.spreadsheets()
            .values()
            .get(spreadsheetId= spreadsheet_id, range= sheet_cell_range)
            .execute()
        )
        return result
    except HttpError as error:
        return {'Error': error}

def insert_data_in_spreadsheet(spreadsheet_id: str, cells_range: str, value_input_option: Literal['RAW', 'USER_ENTERED'], values: List, sheet_name: str= None) -> dict:
    """
    To insert the data in the specific sheet of the spreadsheet or by default in the first sheet.

    Args:
        spreadsheet_id (str): Spreadsheet id
        cells_range (str): Range of the cells in which data will be inserted.
        value_input_option (str): It can be either of two values:
                    - RAW: 	The input is not parsed and is inserted as a string. For example, the input "=1+2" places the string, not the formula, "=1+2" in the cell.
                    (Non-string values like booleans or numbers are always handled as RAW.)
                    - USER_ENTERED: The input is parsed exactly as if it were entered into the Sheets UI. For example, "Mar 1 2016" becomes a date, and "=1+2" becomes a formula.
                    Formats can also be inferred, so "$100.15" becomes a number with currency formatting.
        values (list): List of values to be inserted into the spreadsheet.
                        like [[1,2], [3,4]]
        sheet_name (str): As a single spreadsheet can have multiple sheets, this parameter takes the specific sheet name to insert the data into. If sheet_name is not provided it will
                            insert in the first sheet.

    Returns:
        dict: Information about the insertion/update.

                Like:
                    {'spreadsheetId': '1MIzcEON-5G4sBPoPQPMEQeRi22CtTA4AZxNjbwkg-CE', 'updatedRange': 'Sheet1!A3:C4', 'updatedRows': 2, 'updatedColumns': 3, 'updatedCells': 6}

    Example:
            ```python
            def test_insert_data_in_spreadsheet():
                try:
                    insertion = insert_data_in_spreadsheet(
                        spreadsheet_id="126-Qh-8mCCWjdmd1D4sdQpfgvEk_kQr6FxrwmnGrDZA",
                        cells_range= "A3:C4",
                        value_input_option= "USER_ENTERED",
                        values= [[110, 11, 12], [113, 14, 151]],
                        sheet_name= "Sheet1"
                    )
                    return f'Test case passed: {insertion}'
                except Exception as e:
                    return f'Error data insertion: {e}'
        ```
    """
    try:
        assert value_input_option in ['RAW', 'USER_ENTERED']
        service = get_service(service_name= 'sheets')
        sheet_cell_range= f"{sheet_name}!{cells_range}"
        body = {"values": values}
        result = (
            service.spreadsheets()
            .values()
            .update(
                spreadsheetId= spreadsheet_id,
                range= sheet_cell_range,
                valueInputOption= value_input_option,
                body= body,
            )
            .execute()
        )
        return result
    except HttpError as error:
        return {"Error": error}

def delete_spreadsheet(spreadsheet_id: str) -> str:
    """
    Delete a Google Spreadsheet by its ID. It will use delete_file function from the drive to delete the spreadsheet.

    Args:
        spreadsheet_id (str): The ID of the spreadsheet to delete.

    Returns:
        str: Confirmation message if successful.
    
    Example:
        ```python
            def test_delete_spreadsheet():
                try:
                    deletion = delete_spreadsheet(
                        spreadsheet_id="12Osrhvm1NPDH5MqwlvtSiV7nbC016hrei_ehhn4uzMs"
                    )
                    return f'Test case passed: {deletion}'
                except Exception as e:
                    return f'Error while deleting spreadsheet: {e}'
        ```
    """
    try:
        return delete_file(file_id= spreadsheet_id)
    except HttpError as error:
        return error
