from fastapi import APIRouter, Request, Query, Path, Body
from typing import Any, List, Dict, Union
from app.services.tjnetwork import (
    Any,
    ChangeSet,
    PIPE_STATUS_OPEN,
    add_pipe,
    delete_pipe,
    get_all_pipes,
    get_pipe,
    get_pipe_schema,
    set_pipe,
)

router = APIRouter()

@router.get("/getpipeschema", summary="获取管道模式", description="获取管道对象的模式定义，包含所有可用字段及其类型")
async def fastapi_get_pipe_schema(
    network: str = Query(..., description="管网名称（或数据库名称）")
) -> dict[str, dict[str, Any]]:
    """
    获取管道数据模式定义。
    
    Args:
        network: 管网名称（或数据库名称）
        
    Returns:
        包含管道模式信息的字典
    """
    return get_pipe_schema(network)

@router.post("/addpipe/", response_model=None, summary="添加管道", description="向网络中添加新的管道，需要提供管道的基本参数如长度、管径、粗糙度等")
async def fastapi_add_pipe(
    network: str = Query(..., description="管网名称（或数据库名称）"),
    pipe: str = Query(..., description="管道标识符"),
    node1: str = Query(..., description="管道起始节点ID"),
    node2: str = Query(..., description="管道终止节点ID"),
    length: float = Query(0, description="管道长度（单位：米）"),
    diameter: float = Query(0, description="管道管径（单位：毫米）"),
    roughness: float = Query(0, description="管道粗糙度"),
    minor_loss: float = Query(0, description="管道局部阻力系数"),
    status: str = Query(PIPE_STATUS_OPEN, description="管道状态（开启/关闭）"),
) -> ChangeSet:
    """
    添加新管道到网络。
    
    Args:
        network: 管网名称（或数据库名称）
        pipe: 管道ID
        node1: 起始节点ID
        node2: 终止节点ID
        length: 管道长度
        diameter: 管道管径
        roughness: 管道粗糙度
        minor_loss: 局部阻力系数
        status: 管道状态
        
    Returns:
        ChangeSet对象，包含本次操作的变更信息
    """
    ps = {
        "id": pipe,
        "node1": node1,
        "node2": node2,
        "length": length,
        "diameter": diameter,
        "roughness": roughness,
        "minor_loss": minor_loss,
        "status": status,
    }
    return add_pipe(network, ChangeSet(ps))

@router.post("/deletepipe/", response_model=None, summary="删除管道", description="从网络中删除指定的管道")
async def fastapi_delete_pipe(
    network: str = Query(..., description="管网名称（或数据库名称）"),
    pipe: str = Query(..., description="要删除的管道ID")
) -> ChangeSet:
    """
    删除管道。
    
    Args:
        network: 管网名称（或数据库名称）
        pipe: 管道ID
        
    Returns:
        ChangeSet对象，包含本次删除操作的变更信息
    """
    ps = {"id": pipe}
    return delete_pipe(network, ChangeSet(ps))

@router.get("/getpipenode1/", summary="获取管道起始节点", description="获取指定管道的起始节点ID")
async def fastapi_get_pipe_node1(
    network: str = Query(..., description="管网名称（或数据库名称）"),
    pipe: str = Query(..., description="管道ID")
) -> str | None:
    """
    获取管道的起始节点。
    
    Args:
        network: 管网名称（或数据库名称）
        pipe: 管道ID
        
    Returns:
        起始节点ID，如果不存在则返回None
    """
    ps = get_pipe(network, pipe)
    return ps["node1"]

@router.get("/getpipenode2/", summary="获取管道终止节点", description="获取指定管道的终止节点ID")
async def fastapi_get_pipe_node2(
    network: str = Query(..., description="管网名称（或数据库名称）"),
    pipe: str = Query(..., description="管道ID")
) -> str | None:
    """
    获取管道的终止节点。
    
    Args:
        network: 管网名称（或数据库名称）
        pipe: 管道ID
        
    Returns:
        终止节点ID，如果不存在则返回None
    """
    ps = get_pipe(network, pipe)
    return ps["node2"]

@router.get("/getpipelength/", summary="获取管道长度", description="获取指定管道的长度")
async def fastapi_get_pipe_length(
    network: str = Query(..., description="管网名称（或数据库名称）"),
    pipe: str = Query(..., description="管道ID")
) -> float | None:
    """
    获取管道长度。
    
    Args:
        network: 管网名称（或数据库名称）
        pipe: 管道ID
        
    Returns:
        管道长度（单位：米），如果不存在则返回None
    """
    ps = get_pipe(network, pipe)
    return ps["length"]

@router.get("/getpipediameter/", summary="获取管道管径", description="获取指定管道的管径")
async def fastapi_get_pipe_diameter(
    network: str = Query(..., description="管网名称（或数据库名称）"),
    pipe: str = Query(..., description="管道ID")
) -> float | None:
    """
    获取管道管径。
    
    Args:
        network: 管网名称（或数据库名称）
        pipe: 管道ID
        
    Returns:
        管道管径（单位：毫米），如果不存在则返回None
    """
    ps = get_pipe(network, pipe)
    return ps["diameter"]

@router.get("/getpiperoughness/", summary="获取管道粗糙度", description="获取指定管道的粗糙度")
async def fastapi_get_pipe_roughness(
    network: str = Query(..., description="管网名称（或数据库名称）"),
    pipe: str = Query(..., description="管道ID")
) -> float | None:
    """
    获取管道粗糙度。
    
    Args:
        network: 管网名称（或数据库名称）
        pipe: 管道ID
        
    Returns:
        管道粗糙度值，如果不存在则返回None
    """
    ps = get_pipe(network, pipe)
    return ps["roughness"]

@router.get("/getpipeminorloss/", summary="获取管道局部阻力系数", description="获取指定管道的局部阻力系数")
async def fastapi_get_pipe_minor_loss(
    network: str = Query(..., description="管网名称（或数据库名称）"),
    pipe: str = Query(..., description="管道ID")
) -> float | None:
    """
    获取管道局部阻力系数。
    
    Args:
        network: 管网名称（或数据库名称）
        pipe: 管道ID
        
    Returns:
        局部阻力系数，如果不存在则返回None
    """
    ps = get_pipe(network, pipe)
    return ps["minor_loss"]

@router.get("/getpipestatus/", summary="获取管道状态", description="获取指定管道的状态（开启或关闭）")
async def fastapi_get_pipe_status(
    network: str = Query(..., description="管网名称（或数据库名称）"),
    pipe: str = Query(..., description="管道ID")
) -> str | None:
    """
    获取管道状态。
    
    Args:
        network: 管网名称（或数据库名称）
        pipe: 管道ID
        
    Returns:
        管道状态（开启/关闭），如果不存在则返回None
    """
    ps = get_pipe(network, pipe)
    return ps["status"]

@router.post("/setpipenode1/", response_model=None, summary="设置管道起始节点", description="设置指定管道的起始节点")
async def fastapi_set_pipe_node1(
    network: str = Query(..., description="管网名称（或数据库名称）"),
    pipe: str = Query(..., description="管道ID"),
    node1: str = Query(..., description="新的起始节点ID")
) -> ChangeSet:
    """
    设置管道起始节点。
    
    Args:
        network: 管网名称（或数据库名称）
        pipe: 管道ID
        node1: 新的起始节点ID
        
    Returns:
        ChangeSet对象，包含本次修改的变更信息
    """
    ps = {"id": pipe, "node1": node1}
    return set_pipe(network, ChangeSet(ps))

@router.post("/setpipenode2/", response_model=None, summary="设置管道终止节点", description="设置指定管道的终止节点")
async def fastapi_set_pipe_node2(
    network: str = Query(..., description="管网名称（或数据库名称）"),
    pipe: str = Query(..., description="管道ID"),
    node2: str = Query(..., description="新的终止节点ID")
) -> ChangeSet:
    """
    设置管道终止节点。
    
    Args:
        network: 管网名称（或数据库名称）
        pipe: 管道ID
        node2: 新的终止节点ID
        
    Returns:
        ChangeSet对象，包含本次修改的变更信息
    """
    ps = {"id": pipe, "node2": node2}
    return set_pipe(network, ChangeSet(ps))

@router.post("/setpipelength/", response_model=None, summary="设置管道长度", description="设置指定管道的长度")
async def fastapi_set_pipe_length(
    network: str = Query(..., description="管网名称（或数据库名称）"),
    pipe: str = Query(..., description="管道ID"),
    length: float = Query(..., description="新的管道长度（单位：米）")
) -> ChangeSet:
    """
    设置管道长度。
    
    Args:
        network: 管网名称（或数据库名称）
        pipe: 管道ID
        length: 新的管道长度
        
    Returns:
        ChangeSet对象，包含本次修改的变更信息
    """
    ps = {"id": pipe, "length": length}
    return set_pipe(network, ChangeSet(ps))

@router.post("/setpipediameter/", response_model=None, summary="设置管道管径", description="设置指定管道的管径")
async def fastapi_set_pipe_diameter(
    network: str = Query(..., description="管网名称（或数据库名称）"),
    pipe: str = Query(..., description="管道ID"),
    diameter: float = Query(..., description="新的管道管径（单位：毫米）")
) -> ChangeSet:
    """
    设置管道管径。
    
    Args:
        network: 管网名称（或数据库名称）
        pipe: 管道ID
        diameter: 新的管道管径
        
    Returns:
        ChangeSet对象，包含本次修改的变更信息
    """
    ps = {"id": pipe, "diameter": diameter}
    return set_pipe(network, ChangeSet(ps))

@router.post("/setpiperoughness/", response_model=None, summary="设置管道粗糙度", description="设置指定管道的粗糙度")
async def fastapi_set_pipe_roughness(
    network: str = Query(..., description="管网名称（或数据库名称）"),
    pipe: str = Query(..., description="管道ID"),
    roughness: float = Query(..., description="新的管道粗糙度值")
) -> ChangeSet:
    """
    设置管道粗糙度。
    
    Args:
        network: 管网名称（或数据库名称）
        pipe: 管道ID
        roughness: 新的管道粗糙度
        
    Returns:
        ChangeSet对象，包含本次修改的变更信息
    """
    ps = {"id": pipe, "roughness": roughness}
    return set_pipe(network, ChangeSet(ps))

@router.post("/setpipeminorloss/", response_model=None, summary="设置管道局部阻力系数", description="设置指定管道的局部阻力系数")
async def fastapi_set_pipe_minor_loss(
    network: str = Query(..., description="管网名称（或数据库名称）"),
    pipe: str = Query(..., description="管道ID"),
    minor_loss: float = Query(..., description="新的局部阻力系数值")
) -> ChangeSet:
    """
    设置管道局部阻力系数。
    
    Args:
        network: 管网名称（或数据库名称）
        pipe: 管道ID
        minor_loss: 新的局部阻力系数
        
    Returns:
        ChangeSet对象，包含本次修改的变更信息
    """
    ps = {"id": pipe, "minor_loss": minor_loss}
    return set_pipe(network, ChangeSet(ps))

@router.post("/setpipestatus/", response_model=None, summary="设置管道状态", description="设置指定管道的状态（开启或关闭）")
async def fastapi_set_pipe_status(
    network: str = Query(..., description="管网名称（或数据库名称）"),
    pipe: str = Query(..., description="管道ID"),
    status: str = Query(..., description="新的管道状态（开启/关闭）")
) -> ChangeSet:
    """
    设置管道状态。
    
    Args:
        network: 管网名称（或数据库名称）
        pipe: 管道ID
        status: 新的管道状态
        
    Returns:
        ChangeSet对象，包含本次修改的变更信息
    """
    ps = {"id": pipe, "status": status}
    return set_pipe(network, ChangeSet(ps))

@router.get("/getpipeproperties/", summary="获取管道属性", description="获取指定管道的所有属性信息")
async def fastapi_get_pipe_properties(
    network: str = Query(..., description="管网名称（或数据库名称）"),
    pipe: str = Query(..., description="管道ID")
) -> dict[str, Any]:
    """
    获取管道的所有属性。
    
    Args:
        network: 管网名称（或数据库名称）
        pipe: 管道ID
        
    Returns:
        包含管道所有属性的字典
    """
    return get_pipe(network, pipe)

@router.get("/getallpipeproperties/", summary="获取所有管道属性", description="获取网络中所有管道的属性信息列表")
async def fastapi_get_all_pipe_properties(
    network: str = Query(..., description="管网名称（或数据库名称）")
) -> list[dict[str, Any]]:
    """
    获取网络中所有管道的属性。
    
    Args:
        network: 管网名称（或数据库名称）
        
    Returns:
        包含所有管道属性的字典列表
    """
    # 缓存查询结果提高性能
    # global redis_client
    results = get_all_pipes(network)
    return results

@router.post("/setpipeproperties/", response_model=None, summary="设置管道属性", description="批量设置指定管道的多个属性")
async def fastapi_set_pipe_properties(
    network: str = Query(..., description="管网名称（或数据库名称）"),
    pipe: str = Query(..., description="管道ID"),
    req: Request = None
) -> ChangeSet:
    """
    批量设置管道属性。
    
    Args:
        network: 管网名称（或数据库名称）
        pipe: 管道ID
        req: 请求体，包含要设置的属性及其值
        
    Returns:
        ChangeSet对象，包含本次修改的变更信息
    """
    props = await req.json()
    ps = {"id": pipe} | props
    return set_pipe(network, ChangeSet(ps))
