from typing import Optional
import typer
from utils import *
import boto3
from logs import get_logger, get_rich_console
from rich.columns import Columns
from rich.panel import Panel
from rich.console import Group
from rich.layout import Layout
from rich.pretty import Pretty
import os
from nodes import ServiceNode
from reader import ServiceReader
from custom_nodes import *

def _create_boto_session():
    profile_name = os.environ.get('AWS_PROFILE', False)
    region_name = os.environ.get('AWS_REGION', False)
    _kwargs_dict = {}
    if profile_name:
        _kwargs_dict['profile_name']=profile_name
    if region_name:
        _kwargs_dict['region_name']=region_name
    session = boto3.session.Session(**_kwargs_dict)
    return session 

console = get_rich_console()
logger = get_logger(__name__)
session = _create_boto_session()

app = typer.Typer(no_args_is_help=True)
aws_app = typer.Typer() # no_args_is_help=True
app.add_typer(aws_app, name="aws")
# aws_ls_app = typer.Typer(no_args_is_help=True)
# aws_app.add_typer(aws_ls_app, name="ls")

def _get_available_service_node_names():
    return get_all_available_services(session)

def generate_service_node_completion_items():
    service_names = _get_available_service_node_names(session)
    return service_names



    
@aws_app.command('ls')
def _cli_ls_command(
        service: Optional[str] = typer.Argument(None, show_default=False,help='The AWS service name'),
        resource_node: Optional[str] = typer.Argument(None, show_default=False, help='The AWS Resource Node'),
    ):
    """
    Lists and details AWS Services/ResourceNodes.
    TODO: Document the functions here for --help option
    """
    available_service_names = _get_available_service_node_names()
    if not service and not resource_node:
        # nothing is given
        console.print(Columns(available_service_names, equal=True, expand=True))
        return
    
    if service and not resource_node:
        # we only have service name
        
        if service not in available_service_names:
            similar_service_names = ifind_similar_names_in_list(service, available_service_names)
            if similar_service_names:
                console.print(f"[yellow]Found Similar Service Names:")
                console.print(Columns(similar_service_names, equal=True, expand=True))
                return
            else:
                raise typer.Exit(f"Invalid service name: {service}. Please pick a proper one.")
            
        service_node = ServiceNode(service, session)
        resource_nodes = service_node.get_resource_nodes()
        
        resource_node_names = []
        for _rn in resource_nodes:
            _rn_name = _rn.name
            if _rn.get_all_required_parameter_names():
                _rn_name = f"[bold]{_rn_name}[/]"
            resource_node_names.append(_rn_name)
        
        resource_node_name_as_columns =  Columns(resource_node_names, equal=True, expand=True)
        console.print(resource_node_name_as_columns)
        return
        
    elif service and resource_node:
        # we got both options filled
        service_node = ServiceNode(service, session)
        resource_nodes = service_node.get_resource_nodes()
        resource_node_names = [ _rn.name for _rn in resource_nodes]
        resource_node_obj = service_node.get_resource_node_by_name(resource_node)
        if not resource_node_obj:
            
            similar_resource_names = ifind_similar_names_in_list(resource_node, resource_node_names)
            if similar_resource_names:
                console.print(f"[yellow]Found Similar Resource Node Names:")
                console.print(Columns(similar_resource_names, equal=True, expand=True))
                return 
            else:
                raise typer.Exit(f"Invalid Resource Node name: [bold]{resource_node}[/] for Service: [bold]{service}[/].")
        operations_panel = service_node._get_operation_details_panel(resource_node_obj.name)
        console.print(operations_panel)

        return    


@aws_app.command('read')
def _cli_read_command(
        service: Optional[str] = typer.Argument(None, show_default=False,help='The AWS service name',),
        resource_node: Optional[str] = typer.Argument(None, show_default=False, help='The AWS Resource Node'),
    ):
    available_service_names = _get_available_service_node_names()
    if not service and not resource_node:
        _cli_ls_command(service, resource_node)
        console.print(Panel(f"[bold]Please pick one of the AWS Services", title="[red][bold]ERROR"))
        return
    if service and not resource_node:
        _cli_ls_command(service, resource_node)
        console.print(Panel(f"[bold]Please pick one of the Resource Nodes from [green]{service}[/] Service", title="[red][bold]ERROR"))
        return
    elif service and resource_node:
        service_node = ServiceNode(service, session)
        service_reader = ServiceReader(service_node)
        read = service_reader.read_resource_node(resource_node)
        console.print(Pretty(read))
        # console.print(Panel(read, title=f"[green][bold]{resource_node} RESPONSE"))
        return
    
    
def run_app():
    app()
    
if __name__ == "__main__":
    # typer.run(main)
    app()
    
    




