import json
import uuid
import os
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from typing import Dict, Any, List, Optional, Union

app = FastAPI()

CONFIGS_DIR = "configs"
os.makedirs(CONFIGS_DIR, exist_ok=True)

class ParamUpdate(BaseModel):
    name: str
    value: Any

def load_config(config_id: str):
    file_path = f"{CONFIGS_DIR}/{config_id}.json"
    try:
        with open(file_path, "r") as f:
            return json.load(f)
    except FileNotFoundError:
        raise HTTPException(status_code=404, detail=f"Configuration {config_id} not found")

def save_config(config_id: str, config: dict):
    file_path = f"{CONFIGS_DIR}/{config_id}.json"
    with open(file_path, "w") as f:
        json.dump(config, f, indent=2)

@app.post("/config")
async def create_config():
    config_id = str(uuid.uuid4())
    initial_config = {
        "version": "1.0.0",
        "sections": {
            "main": [{"ai": {}}]
        }
    }
    save_config(config_id, initial_config)
    return {"config_id": config_id}

@app.get("/config/{config_id}")
async def get_config(config_id: str):
    return load_config(config_id)

@app.delete("/config/{config_id}")
async def delete_config(config_id: str):
    file_path = f"{CONFIGS_DIR}/{config_id}.json"
    try:
        os.remove(file_path)
        return {"message": f"Configuration {config_id} deleted successfully"}
    except FileNotFoundError:
        raise HTTPException(status_code=404, detail=f"Configuration {config_id} not found")

@app.put("/config/{config_id}/params/{param_name}")
async def update_param(config_id: str, param_name: str, value: Any):
    config = load_config(config_id)
    if "params" not in config["sections"]["main"][0]["ai"]:
        config["sections"]["main"][0]["ai"]["params"] = {}
    config["sections"]["main"][0]["ai"]["params"][param_name] = value
    save_config(config_id, config)
    return {"message": f"Parameter {param_name} updated successfully"}

@app.put("/config/{config_id}/params")
async def update_multiple_params(config_id: str, params: List[ParamUpdate]):
    config = load_config(config_id)
    if "params" not in config["sections"]["main"][0]["ai"]:
        config["sections"]["main"][0]["ai"]["params"] = {}
    
    for param in params:
        config["sections"]["main"][0]["ai"]["params"][param.name] = param.value
    
    save_config(config_id, config)
    return {"message": f"{len(params)} parameters updated successfully"}

@app.delete("/config/{config_id}/params/{param_name}")
async def delete_param(config_id: str, param_name: str):
    config = load_config(config_id)
    if "params" in config["sections"]["main"][0]["ai"] and param_name in config["sections"]["main"][0]["ai"]["params"]:
        del config["sections"]["main"][0]["ai"]["params"][param_name]
        save_config(config_id, config)
        return {"message": f"Parameter {param_name} deleted successfully"}
    raise HTTPException(status_code=404, detail=f"Parameter {param_name} not found")

@app.put("/config/{config_id}/prompt")
async def update_prompt(config_id: str, prompt: Dict[str, Any]):
    config = load_config(config_id)
    config["sections"]["main"][0]["ai"]["prompt"] = prompt
    save_config(config_id, config)
    return {"message": "Prompt updated successfully"}

@app.put("/config/{config_id}/post_prompt")
async def update_post_prompt(config_id: str, post_prompt: Dict[str, Any]):
    config = load_config(config_id)
    config["sections"]["main"][0]["ai"]["post_prompt"] = post_prompt
    save_config(config_id, config)
    return {"message": "Post-prompt updated successfully"}

@app.put("/config/{config_id}/languages")
async def update_languages(config_id: str, languages: List[Dict[str, str]]):
    config = load_config(config_id)
    config["sections"]["main"][0]["ai"]["languages"] = languages
    save_config(config_id, config)
    return {"message": "Languages updated successfully"}

@app.put("/config/{config_id}/hints")
async def update_hints(config_id: str, hints: List[str]):
    config = load_config(config_id)
    config["sections"]["main"][0]["ai"]["hints"] = hints
    save_config(config_id, config)
    return {"message": "Hints updated successfully"}

@app.put("/config/{config_id}/swaig/functions/{function_name}")
async def update_swaig_function(config_id: str, function_name: str, function: Dict[str, Any]):
    config = load_config(config_id)
    if "SWAIG" not in config["sections"]["main"][0]["ai"]:
        config["sections"]["main"][0]["ai"]["SWAIG"] = {"functions": []}
    functions = config["sections"]["main"][0]["ai"]["SWAIG"]["functions"]
    for i, func in enumerate(functions):
        if func["function"] == function_name:
            functions[i] = function
            save_config(config_id, config)
            return {"message": f"SWAIG function {function_name} updated successfully"}
    functions.append(function)
    save_config(config_id, config)
    return {"message": f"SWAIG function {function_name} added successfully"}

@app.delete("/config/{config_id}/swaig/functions/{function_name}")
async def delete_swaig_function(config_id: str, function_name: str):
    config = load_config(config_id)
    if "SWAIG" in config["sections"]["main"][0]["ai"] and "functions" in config["sections"]["main"][0]["ai"]["SWAIG"]:
        functions = config["sections"]["main"][0]["ai"]["SWAIG"]["functions"]
        for i, func in enumerate(functions):
            if func["function"] == function_name:
                del functions[i]
                save_config(config_id, config)
                return {"message": f"SWAIG function {function_name} deleted successfully"}
    raise HTTPException(status_code=404, detail=f"SWAIG function {function_name} not found")

@app.get("/config/{config_id}/swaig/functions/{function_name}")
async def get_swaig_function(config_id: str, function_name: str):
    config = load_config(config_id)
    if "SWAIG" in config["sections"]["main"][0]["ai"] and "functions" in config["sections"]["main"][0]["ai"]["SWAIG"]:
        for func in config["sections"]["main"][0]["ai"]["SWAIG"]["functions"]:
            if func["function"] == function_name:
                return func
    raise HTTPException(status_code=404, detail=f"SWAIG function {function_name} not found")