from .service import get_service
from googleapiclient.errors import HttpError
from typing import Optional

def get_tasks_list_names_and_ids() -> list:
    """
    Module to get list of tasks names and ids.

    Returns:
        list: List of task names and ids.

    Raises:
        Exception: For errors to get the list.
    
    Example:
        ```python
        def test_get_tasks_list_names_and_ids():
            try:
                lists = get_tasks_list_names_and_ids()
                return f'Test case passed: {lists}'
            except Exception as e:
                return f'Error Getting Tasks: {e}'
        ```
    """
    try:
        service = get_service(service_name= 'tasks')
        results = service.tasklists().list().execute()
        list_items = results.get("items", [])
        if not list_items:
            return []
        lists_names_and_ids = []
        for task in list_items:
            lists_names_and_ids.append({
                'title': task['title'],
                'id': task['id']
            })
        return lists_names_and_ids
    except HttpError as error:
        raise Exception(f" Error {error}")

def get_pending_tasks_of_specific_list(list_name: str) -> list:
    """
    Module to get pending tasks of specific list.

    Args:
        list_name (str): Name of list.

    Returns:
        list: List of pending tasks.

    Raises:
        Exception: If there is no list named as the mentioned in the parameters.
        Exception: For errors to get the pending tasks.
    
    Example:
        ```python
        def test_get_pending_tasks_of_specific_list():
            try:
                tasks = get_pending_tasks_of_specific_list(
                    list_name='Monday'
                )
                return f'Test case passed: {tasks}'
            except Exception as e:
                return f'Error Getting Tasks: {e}'
        ```
    """
    try:
        service = get_service(service_name= 'tasks')
        task_lists = get_tasks_list_names_and_ids()
        if not task_lists:
            return []
        tasks = []
        for tlist in task_lists:
            if tlist['title'] == list_name:
                tasks_result = service.tasks().list(tasklist= tlist['id']).execute()
                task_items = tasks_result.get("items", [])
                if not task_items:
                    return []
                else:
                    for task in task_items:
                        tasks.append(
                            {
                                'id': task.get('id'),
                                'Task Name': task.get('title', 'No-Title'),
                                'Task Due Date': task.get('due', 'No due date'),
                                'Task Details': task.get('notes', 'No Details'),
                                'Tasks Status': task.get('status', 'No Status')
                            }
                        )
                return tasks
        raise Exception("Sorry, this list does not exist")
    except HttpError as error:
        raise Exception(f" Error {error}")

def create_new_list(list_name: str) -> dict:
    """
    Module to create new list.

    Args:
        list_name (str): Name of list.

    Returns:
        dict: New list.

    Raises:
        Exception: If there is already an existing list with that name.
        Exception: For errors to create the list.
    
    Example:
        ```python
        def test_create_new_list():
            try:
                create_list = create_new_list(
                    list_name='Testing.'
                )
                return f'Test case passed: {create_list}'
            except Exception as e:
                return f'Error Getting Tasks: {e}'
        ```
    """
    try:
        service = get_service(service_name= 'tasks')
        existing_lists = get_tasks_list_names_and_ids()
        for tlist in existing_lists:
            if tlist['title'] == list_name:
                raise Exception(f"{list_name} Already exist, Please give some another name to this new list.")
        create_list = service.tasklists().insert(body={'title': list_name}).execute()
        return {"id": create_list["id"], "title": create_list["title"]}
    except HttpError as error:
        raise Exception(f" Error {error}")

def add_task_to_list(task_name: str, list_name: str, due_date: Optional[str] = None,
                           task_details: Optional[str] = None) -> dict:
    """
    Module to add task to list.

    Args:
        task_name (str): Name of task.
        list_name (str): Name of list.
        due_date (Optional[str], optional): Due date of task.
        task_details (Optional[str], optional): Task details.

    Returns:
        dict: Task details.

    Raises:
        Exception: If there is already an existing task with that name.
        Exception: For errors to add the task.
        Exception: If the list that was mentioned does not exist.
    
    Example:
        ```python
        def test_add_task_to_list():
            try:
                create_list = add_task_to_list(
                    list_name='Testing.',
                    task_name='Testing task',
                    task_details='content testing',
                    due_date=datetime.datetime.now(datetime.UTC).isoformat()
                )
                return f'Test case passed: {create_list}'
            except Exception as e:
                return f'Error Getting Tasks: {e}'
        ```
    """
    try:
        service = get_service(service_name= 'tasks')
        existing_lists = get_tasks_list_names_and_ids()
        for tlist in existing_lists:
            if tlist['title'] == list_name:
                list_tasks = get_pending_tasks_of_specific_list(list_name= list_name)
                for task in list_tasks:
                    if task['Task Name'] == task_name:
                        raise Exception(f'Sorry, {task_name} already exists in this list.')
                task_body = {"title": task_name}
                if due_date:
                    task_body["due"] = due_date
                if task_details:
                    task_body["notes"] = task_details
                add_task = service.tasks().insert(tasklist=tlist['id'], body=task_body).execute()
                return add_task
        raise Exception(f'Sorry, {list_name} does not exist. You have to create the list first.')
    except HttpError as error:
        raise Exception(f" Error {error}")

def mark_task_complete(task_name: str, list_name: str) -> str:
    """
    Module to mark task as complete in the specified list.

    Args:
        task_name (str): Name of task that you want to mark as complete.
        list_name (str): Name of list that task is in.

    Returns:
        str: Task Mark as complete Confirmation.

    Raises:
        Exception: If there is no list named as mentioned list.
        Exception: If task that was mentioned does not exist.
        Exception: For errors to mark the task as completed.
    
    Example:
        ```python
        def test_mark_task_complete():
            try:
                list_name = 'Monday'
                task_name = 'Push to git'
                mark_as_complete = mark_task_complete(
                    task_name=task_name,
                    list_name=list_name
                )
                return f'Test case passed: {mark_as_complete}'
            except Exception as e:
                return f'Error Getting Tasks: {e}'
        ```
    """
    try:
        service = get_service('tasks')
        task_lists = get_tasks_list_names_and_ids()
        existing_list_names = [existing_list['title'] for existing_list in task_lists]
        if list_name not in existing_list_names:
            raise  Exception(f'Sorry, there is no list named as {list_name}.')
        for tlist in task_lists:
            if tlist['title'] == list_name:
                list_tasks = get_pending_tasks_of_specific_list(list_name=list_name)
                for task in list_tasks:
                    if task['Task Name'] == task_name:
                        task_resource = service.tasks().get(
                            tasklist=tlist['id'],
                            task=task['id']
                        ).execute()
                        task_resource["status"] = "completed"
                        service.tasks().update(
                            tasklist=tlist['id'],
                            task=task['id'],
                            body=task_resource
                        ).execute()
                        return f'{task_name} successfully marked as completed!'
        raise Exception(f'Sorry, the task named {task_name} does not exist in the {list_name} list.')
    except HttpError as error:
        raise Exception(f" Error {error}")

def delete_list(list_name: str) -> str:
    """
    Module to delete an entire list.

    Args:
        list_name (str): Name of list of to be deleted.

    Returns:
        str: Deleted list Confirmation.

    Raises:
        Exception: If there is no list named as the mentioned in the parameters.
        Exception: For errors to delete the list.
    
    Example:
        ```python
        def test_delete_list():
            try:
                list_name = 'Testing.'
                deletion = delete_list(
                    list_name=list_name
                )
                return f'Test case passed: {deletion}'
            except Exception as e:
                return f'Error Getting Tasks: {e}'
        ```
    """
    try:
        service = get_service('tasks')
        task_lists =  get_tasks_list_names_and_ids()
        for tlist in task_lists:
            if tlist['title'] == list_name:
                deletion = service.tasklists().delete(tasklist=tlist['id']).execute()
                return f"{list_name} successfully deleted!"
        raise Exception(f"Sorry, no list named '{list_name}' exists.")
    except HttpError as error:
        raise Exception(f" Error {error}")
