import concurrent.futures as cex

import connection as conn
from openstack.exceptions import ResourceFailure
from typing import Final


compute = conn.cloud.compute
network = conn.cloud.network
volume = conn.cloud.volume

CLIENT_NAME_MASK: Final[str] = conn.FIO_CLIENT_NAME_MASK
AA_SERVER_GROUP_NAME: Final[str] = conn.FIO_AA_SERVER_GROUP_NAME
FLAVOR_NAME: Final[str] = conn.FIO_FLAVOR_NAME
KEYPAIR_NAME: Final[str] = conn.FIO_KEYPAIR_NAME
SG_NAME: Final[str] = conn.FIO_SG_NAME
VOL_NAME_MASK: Final[str] = conn.FIO_VOL_NAME_MASK

ROUTER_NAME: Final[str] = conn.FIO_ROUTER_NAME
NET_NAME: Final[str] = conn.FIO_NET_NAME
CONCURRENCY: Final[int] = conn.CONCURRENCY


def delete_fio_client(vm_id: str) -> None:
    vm = compute.get_server(vm_id)
    attachments = compute.volume_attachments(vm)
    # Delete fio volume attachment (and any other attachments
    # that the VM could have)
    # Delete the volume and the server
    for att in attachments:
        vol_id = att.volume_id
        vol = volume.get_volume(vol_id)
        try:
            conn.detach_volume(vm, vol)
            print(
                f"'{vol.id}' volume has been detached from fio '{vm.name}'"
                " server.")
            conn.delete_volume(vol)
            print(f"'{vol.id}' volume has been deleted.")
        except ResourceFailure as e:
            print(
                f"Cleanup of '{vm.id}' with volume '{vol.id}' attached "
                f"failed with '{e.message}' error.")
            conn.delete_volume(vol)
    conn.delete_server(vm)
    print(f"'{vm.name}' server has been deleted.")


if __name__ == "__main__":
    # Find fio VMs
    vms = list(compute.servers(name=CLIENT_NAME_MASK, details=False))

    # Delete fio VMs in parallel in batches of CONCURRENCY size
    with cex.ThreadPoolExecutor(max_workers=CONCURRENCY) as executor:
        futures = [executor.submit(delete_fio_client, vm.id) for vm in vms]
        # Waits for batch of fio VMs to be deleted
        _ = [future.result() for future in futures]

    # Remove ports from fio router (including external GW)
    router = network.find_router(ROUTER_NAME)
    if router:
        network.update_router(router.id, external_gateway_info={})
        print("Externa GW port has been deleted from fio router.")
        router_ports = network.ports(device_id=router.id)
        for p in router_ports:
            network.remove_interface_from_router(router.id, port_id=p.id)
            print(f"'{p.id}' port has been deleted from fio router.")

    # Delete fio network topology
    net = network.find_network(NET_NAME)
    if net:
        network.delete_network(net.id)
        print(f"fio '{net.id}' network has been deleted.")
    if router:
        network.delete_router(router.id)
        print(f"fio '{router.id}' router has been deleted.")

    # Delete fio flavor
    flavor = compute.find_flavor(FLAVOR_NAME)
    if flavor:
        compute.delete_flavor(flavor.id)
        print(f"fio '{flavor.id}' flavor has been deleted.")

    # # Delete fio keypair
    kp = compute.find_keypair(KEYPAIR_NAME)
    if kp:
        compute.delete_keypair(kp)
        print(f"fio '{kp.id}' keypair has been deleted.")

    # Delete fio security group
    sg = network.find_security_group(SG_NAME)
    if sg:
        network.delete_security_group(sg)
        print(f"fio '{sg.id}' security group has been deleted.")

    # Delete the orphan fio volumes which are not attached (if any)
    volumes = volume.volumes(VOL_NAME_MASK)
    for v in volumes:
        if not v.attachments:
            volume.delete_volume(v.id)
            print(f"'{v.id}' volume has been deleted.")

    # Delete fio server group
    server_group = compute.find_server_group(
        AA_SERVER_GROUP_NAME, all_projects=True)
    if server_group:
        compute.delete_server_group(server_group)
        print(f"fio '{server_group.name}' server group has been deleted.")
