from .database import *
from .s0_base import get_node_links


def calculate_virtual_district(name: str, centers: list[str]) -> dict[str, list[Any]]:
    write(name, 'delete from temp_vd_topology')

    # map node name to index
    i = 0
    isolated_nodes = []
    node_index: dict[str, int] = {}
    for row in read_all(name, 'select id from _node'):
        node = str(row['id'])
        if get_node_links(name, node) == []:
            isolated_nodes.append(node)
            continue
        i += 1
        node_index[node] = i

    # build topology graph
    pipes = read_all(name, 'select node1, node2, length from pipes')
    for pipe in pipes:
        source = node_index[str(pipe['node1'])]
        target = node_index[str(pipe['node2'])]
        cost = float(pipe['length'])
        write(name, f"insert into temp_vd_topology (source, target, cost) values ({source}, {target}, {cost})")
    pumps = read_all(name, 'select node1, node2 from pumps')
    for pump in pumps:
        source = node_index[str(pump['node1'])]
        target = node_index[str(pump['node2'])]
        write(name, f"insert into temp_vd_topology (source, target, cost) values ({source}, {target}, 0.0)")
    valves = read_all(name, 'select node1, node2 from valves')
    for valve in valves:
        source = node_index[str(valve['node1'])]
        target = node_index[str(valve['node2'])]
        write(name, f"insert into temp_vd_topology (source, target, cost) values ({source}, {target}, 0.0)")

    # dijkstra distance
    node_distance: dict[str, dict[str, Any]] = {}
    for center in centers:
        for node, index in node_index.items():
            if node == center:
                node_distance[node] = { 'center': center, 'distance' : 0.0 }
                continue
            # TODO: check none
            distance = float(read(name, f"select max(agg_cost) as distance from pgr_dijkstraCost('select id, source, target, cost from temp_vd_topology', {index}, {node_index[center]}, false)")['distance'])
            if node not in node_distance:
                node_distance[node] = { 'center': center, 'distance' : distance }
            elif distance < node_distance[node]['distance']:
                node_distance[node] = { 'center': center, 'distance' : distance }

    write(name, 'delete from temp_vd_topology')

    # reorganize the distance result
    center_node: dict[str, list[str]] = {}
    for node, value in node_distance.items():
        if value['center'] not in center_node:
            center_node[value['center']] = []
        center_node[value['center']].append(node)

    vds: list[dict[str, Any]] = []

    for center, value in center_node.items():
        vds.append({ 'center': center, 'nodes': value })

    return { 'virtual_districts': vds, 'isolated_nodes': isolated_nodes }
