import xml.etree.ElementTree as ET
from typing import Union
from fastapi import FastAPI
import os
import uuid
import re
import json
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
from subdir import service
from subdir import db

import numpy as np
from fastapi.staticfiles import StaticFiles
from pymongo import AsyncMongoClient
client = AsyncMongoClient()

from fastapi import WebSocket, WebSocketDisconnect

class ConnectionManager:
    """Class defining socket events"""
    def __init__(self):
        """init method, keeping track of connections"""
        self.active_connections = []
    
    async def connect(self, websocket: WebSocket):
        """connect event"""
        await websocket.accept()
        self.active_connections.append(websocket)

    async def send_personal_message(self, message: str, websocket: WebSocket):
        """Direct Message"""
        await websocket.send_text(message)
    
    def disconnect(self, websocket: WebSocket):
        """disconnect event"""
        self.active_connections.remove(websocket)


app = FastAPI()


origins = [
    "http://localhost.tiangolo.com",
    "https://localhost.tiangolo.com",
    "http://localhost",
    "http://localhost:9002",
    "http://127.0.0.1:9002",
]

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)
app.mount("/static", StaticFiles(directory="front/dist"), name="static")
manager = ConnectionManager()


for root, dirs, files in os.walk("./data", topdown=False):
    for name in files:
        print(os.path.join(root, name))
        file_data = os.path.join(root, name)





def getDetail(root):

    print(root.tag)
    print(root.text)
    print(root.attrib)
    result = []
    result.append(["名称", "金额", "暂估价", "安全文明施工费", "规费"])
    for child in root:
        print(child.tag)
        print(child.attrib)
    
        if child.tag == "TouBiaoXx":
            result.append([child.attrib["Zbr"], child.attrib["Tbzj"], child.attrib["Zgj"], child.attrib["Aqwmf"], child.attrib["Gf"]])
        if child.tag == "Dxgcxx":
            Dxgcbh = child.attrib["Dxgcbh"]
            Dxgcmc = child.attrib["Dxgcmc"]

            result.append([child.attrib["Dxgcmc"], child.attrib["Je"], child.attrib["Zgj"], child.attrib["Aqwmf"], child.attrib["Gf"]])

    return result
def getOutline(root):

    print(root.tag)
    print(root.text)
    print(root.attrib)
    result = []
    for child in root:
        print(child.tag)
        print(child.attrib)
    
        if child.tag == "TouBiaoXx":
            result.append({"id" : "TouBiaoXx", "label" : "投标信息" })
        if child.tag == "Dxgcxx":
            Dxgcbh = child.attrib["Dxgcbh"]
            Dxgcmc = child.attrib["Dxgcmc"]
            result2 = []
            for child1 in child:
                #print("level2===================================")
                #print(child1.tag)
                #print(child1.attrib)
                Dwgcbh = child1.attrib["Dwgcbh"]
                Dwgcmc = child1.attrib["Dwgcmc"]
                Zylb = child1.attrib["Zylb"]
                result2.append({"id" : Dwgcbh,"Zylb":Zylb,  "label": Dwgcmc, "children" : service.getDwgc(root, Dwgcbh, Zylb)})

            result.append({"id" : Dxgcbh, "label" : Dxgcmc, "children" : result2})

    return result

class Info(BaseModel):
    name: str
class DingeshuRequest(BaseModel):
    value: int
class DingeXilieRequest(BaseModel):
    value: int
    id: str
class SingleDingeXilieRequest(BaseModel):
    zhuanye: int
    debh: str

class InfoWithID(BaseModel):
    name: str
    id: str

@app.post("/outline")
async def read_root(info: Info):
    for root, dirs, files in os.walk("./data", topdown=False):
        for name in files:
            if name == info.name:
                print(os.path.join(root, name))
                file_data = os.path.join(root, name)
    tree = ET.parse(file_data)
    root = tree.getroot()
    return getOutline(root)

@app.post("/outline2")
async def read_root2(info: Info):
    
    return await db.getOutline(client, info.name)

@app.post("/detail")
async def read_detail(info: Info):
    for root, dirs, files in os.walk("./data", topdown=False):
        for name in files:
            if name == info.name:
                print(os.path.join(root, name))
                file_data = os.path.join(root, name)
    tree = ET.parse(file_data)
    root = tree.getroot()
    return getDetail(root)

@app.post("/detail2")
async def read_detail2(info: Info):
    
    return await db.getDetail(client, info.name)

@app.post("/baojiahuizong/")
async def read_bjhz(info: InfoWithID):
    for root, dirs, files in os.walk("./data", topdown=False):
        for name in files:
            if name == info.name:
                print(os.path.join(root, name))
                file_data = os.path.join(root, name)
    tree = ET.parse(file_data)
    root = tree.getroot()
    return service.getBjhz(root, info.id)

@app.post("/baojiahuizong2/")
async def read_bjhz2(info: InfoWithID):
   
    return await db.getBjhz(client, info.name, info.id)

@app.post("/guifeishuijin/")
async def read_gfsj(info: InfoWithID):
    for root, dirs, files in os.walk("./data", topdown=False):
        for name in files:
            if name == info.name:
                print(os.path.join(root, name))
                file_data = os.path.join(root, name)
    tree = ET.parse(file_data)
    root = tree.getroot()
    return service.getGfsj(root, info.id)

@app.post("/guifeishuijin2/")
async def read_gfsj2(info: InfoWithID):
    return await db.getGfsj(client, info.name, info.id)

@app.post("/qitaxiangmu/")
async def read_qtxm(info: InfoWithID):
    for root, dirs, files in os.walk("./data", topdown=False):
        for name in files:
            if name == info.name:
                print(os.path.join(root, name))
                file_data = os.path.join(root, name)
    tree = ET.parse(file_data)
    root = tree.getroot()
    return service.getQtxm(root, info.id)

@app.post("/qitaxiangmu2/")
async def read_qtxm2(info: InfoWithID):
    return await db.getQtxm(client, info.name, info.id)

@app.post("/zanliejine/")
async def read_zlje(info: InfoWithID):
    for root, dirs, files in os.walk("./data", topdown=False):
        for name in files:
            if name == info.name:
                print(os.path.join(root, name))
                file_data = os.path.join(root, name)
    tree = ET.parse(file_data)
    root = tree.getroot()
    return service.getZlje(root, info.id)


@app.post("/zanliejine2/")
async def read_zlje2(info: InfoWithID):
    return await db.getZlje(client, info.name, info.id)

@app.post("/jirigong/")
async def read_jrg(info: InfoWithID):
    for root, dirs, files in os.walk("./data", topdown=False):
        for name in files:
            if name == info.name:
                print(os.path.join(root, name))
                file_data = os.path.join(root, name)
    tree = ET.parse(file_data)
    root = tree.getroot()
    return service.getJrg(root, info.id)

@app.post("/jirigong2/")
async def read_jrg2(info: InfoWithID):
    return await db.getJrg(client, info.name, info.id)

@app.post("/zongchengbaofuwufei/")
async def read_zcbfwf(info: InfoWithID):
    for root, dirs, files in os.walk("./data", topdown=False):
        for name in files:
            if name == info.name:
                print(os.path.join(root, name))
                file_data = os.path.join(root, name)
    tree = ET.parse(file_data)
    root = tree.getroot()
    return service.getZcbfwf(root, info.id)

@app.post("/zongchengbaofuwufei2/")
async def read_zcbfwf2(info: InfoWithID):
    return await db.getZcbfwf(client, info.name, info.id)


@app.post("/fabaorengongyingcailiao/")
async def read_fbrgycl(info: InfoWithID):
    for root, dirs, files in os.walk("./data", topdown=False):
        for name in files:
            if name == info.name:
                print(os.path.join(root, name))
                file_data = os.path.join(root, name)
    tree = ET.parse(file_data)
    root = tree.getroot()
    return service.getFbrgycl(root, info.id)

@app.post("/fabaorengongyingcailiao2/")
async def read_fbrgycl2(info: InfoWithID):
    return await db.getFbrgycl(client, info.name, info.id)


@app.post("/rencaijihuizong/")
async def read_rcjhz(info: InfoWithID):
    for root, dirs, files in os.walk("./data", topdown=False):
        for name in files:
            if name == info.name:
                print(os.path.join(root, name))
                file_data = os.path.join(root, name)
    tree = ET.parse(file_data)
    root = tree.getroot()
    return service.getRcjhz(root, info.id)

@app.post("/rencaijihuizong2/")
async def read_rcjhz2(info: InfoWithID):
    return await db.getRcjhz(client, info.name, info.id)


@app.post("/qingdanxiangmu/")
async def read_qdxm(info: InfoWithID):
    for root, dirs, files in os.walk("./data", topdown=False):
        for name in files:
            if name == info.name:
                print(os.path.join(root, name))
                file_data = os.path.join(root, name)
    tree = ET.parse(file_data)
    root = tree.getroot()
    return service.getQdxm(root, info.id)
    #return []

@app.post("/qingdanxiangmu2/")
async def read_qdxm2(info: InfoWithID):
    
    return await db.getQdxm(client, info.name, info.id)

class Item(BaseModel):
    bh: str
    bt: str
    name: str
class Rcj(BaseModel):
    bh: str
    bt: str
    bm: str
    name: str
class Dercj(BaseModel):
    bh: str
    bt: str
    qdbm: str
    debm: str
    name: str
class Zjcs(BaseModel):
    bh: str
    name: str


@app.post("/qingdanmingxi/")
async def read_qdmx(item : Item):

    return await db.getQdmx(client, item.name, item.bh, item.bt)

@app.post("/qingdanrcj/")
async def read_rcj(item : Rcj):

    if item.bt == "Djcs":
        return await db.getDjcsQingdanrcj(client, item.name, item.bh, item.bt, item.bm)
    return await db.getQingdanrcj(client, item.name, item.bh, item.bt, item.bm)

@app.post("/qingdantuijian/")
async def read_tuijian(item : Rcj):
    
        
    return service.getQingdanTuijian(item.bh, item.bt, item.bm)


@app.post("/dingercj/")
async def read_dercj(item : Dercj):
    if item.bt == "Djcs":
        return await db.getDjcsDingercj(client, item.name, item.bh, item.bt, item.qdbm, item.debm)

    
    return await db.getDingercj(client, item.name, item.bh, item.bt, item.qdbm, item.debm)


@app.post("/zjcs/")
async def read_zjcs(item : Zjcs):
    return await db.getZjcs(client, item.name, item.bh)


@app.post("/djcs/")
async def read_djcs(item : Zjcs):
    return await db.getDjcs(client, item.name, item.bh)

@app.post("/files/")
async def read_files():
    result = []
    for root, dirs, files in os.walk("./data", topdown=False):
        for name in files:
            print(os.path.join(root, name))
            result.append([name, "", ""])
    return result

@app.post("/files2/")
async def read_files2():
    result = await db.list_files(client)
    return result

@app.post("/des/")
async def read_des(r: DingeshuRequest):
    result = service.getDes(r.value)
    #print(result)
    return result

@app.post("/pbs/")
async def read_pbs(r: DingeshuRequest):
    result = service.getPbs(r.value)
    #print(result)
    return result

@app.post("/pbxl/")
async def read_pbxl(r: Info):
    result = service.getPbxl(r.name)
    #print(result)
    return result

@app.post("/dexilie/")
async def read_dexilie(r: DingeXilieRequest):
    result = service.getDeXilie(r.value, r.id)
    #print(result)
    return result

@app.post("/singledexilie/")
async def read_singledexilie(r: SingleDingeXilieRequest):
    result1, result2, rgde, jxde, clde, bz_selected, bz_selected2, actual_zhuanye= service.getSingleDeXilie(r.zhuanye, r.debh)
    print("get result ***************************************")
    if result1:
        result3 = json.loads(result1)
    else:
        result3 = {}
    result3["reverse"] = str(result2)
    result3["rgde"] = rgde
    result3["jxde"] = jxde
    result3["clde"] = clde
    result3["actual_zhuanye"] = actual_zhuanye
    if bz_selected != None:
        result3["bz_selected"] = json.loads(bz_selected)
    else:
        result3["bz_selected"] = {"BZBH": {}}
    if bz_selected2 != None:
        result3["bz_selected2"] = json.loads(bz_selected2)
    else:
        result3["bz_selected2"] = {"BZBH": {}}
    print(result3)
    return json.dumps(result3, ensure_ascii=False)


@app.post("/save/")
async def save(r: Info):
    data = json.loads(r.name)
    print(data)
 
    return await db.save(client, data)




async def resolve(websocket, data):
    await db.resolve(manager, websocket, data, client)##manager.send_personal_message(f"You wrote: {data}", websocket)


@app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket):
    await manager.connect(websocket)
    try:
        while True:
            data = await websocket.receive_text()
            await resolve(websocket, data)
            ##await manager.broadcast(f"Client #{client_id} says: {data}")
    except WebSocketDisconnect:
        manager.disconnect(websocket)
        ##await manager.broadcast(f"Client  left the chat")
