"""Flask API 服务：TF 树加载、查询、更新、保存。"""
import os
from flask import Flask, request, jsonify
import numpy as np

from .manager import TFTreeManager

app = Flask(__name__)

DATA_DIR = os.environ.get("TFTREE_DATA_DIR", "./data")
manager = None


def get_manager():
    global manager
    if manager is None:
        if not os.path.exists(DATA_DIR):
            os.makedirs(DATA_DIR, exist_ok=True)
        manager = TFTreeManager(DATA_DIR)
        try:
            manager.load_from_yaml()
        except Exception:
            pass
    return manager


@app.route('/api/load', methods=['POST'])
def load_data():
    """重新加载数据"""
    path = request.json.get('path', DATA_DIR)
    global manager
    manager = TFTreeManager(path)
    try:
        manager.load_from_yaml()
        return jsonify({"status": "success", "message": f"Loaded from {path}", "frames": list(manager.get_all_frames())})
    except Exception as e:
        return jsonify({"status": "error", "message": str(e)}), 400


@app.route('/api/frames', methods=['GET'])
def get_frames():
    """获取所有坐标系"""
    m = get_manager()
    return jsonify({"frames": list(m.get_all_frames())})


@app.route('/api/transforms', methods=['GET'])
def get_all_transforms():
    """获取所有已定义的变换"""
    m = get_manager()
    return jsonify({"transforms": m.order})


@app.route('/api/transform', methods=['GET'])
def get_transform():
    """计算两个节点间的变换"""
    source = request.args.get('source')
    target = request.args.get('target')
    if not source or not target:
        return jsonify({"status": "error", "message": "Missing source or target"}), 400

    m = get_manager()
    T = m.get_transform(source, target)
    if T is None:
        return jsonify({"status": "error", "message": f"No path from {source} to {target}"}), 404

    return jsonify({
        "source": source,
        "target": target,
        "matrix": T.tolist(),
        "translation": T[:3, 3].tolist(),
        "rotation_matrix": T[:3, :3].tolist()
    })


@app.route('/api/compute_all', methods=['GET'])
def compute_all():
    """从根节点计算所有变换"""
    root = request.args.get('root')
    if not root:
        return jsonify({"status": "error", "message": "Missing root"}), 400

    m = get_manager()
    try:
        transforms = m.compute_all_transforms_from_root(root)
        result = {}
        for frame, T in transforms.items():
            result[frame] = {
                "matrix": T.tolist(),
                "translation": T[:3, 3].tolist()
            }
        return jsonify({"root": root, "transforms": result})
    except Exception as e:
        return jsonify({"status": "error", "message": str(e)}), 400


@app.route('/api/update', methods=['POST'])
def update_transform():
    """更新变换参数"""
    data = request.json
    source = data.get('source')
    target = data.get('target')
    translation = data.get('translation')
    rotation = data.get('rotation')

    if not source or not target:
        return jsonify({"status": "error", "message": "Missing source or target"}), 400

    m = get_manager()
    try:
        trans_np = np.array(translation) if translation else None
        rot_np = np.array(rotation) if rotation else None
        m.update_transform(source, target, trans_np, rot_np)
        return jsonify({"status": "success"})
    except Exception as e:
        return jsonify({"status": "error", "message": str(e)}), 400


@app.route('/api/invert', methods=['POST'])
def invert_transform():
    """求逆变换"""
    data = request.json
    source = data.get('source')
    target = data.get('target')

    if not source or not target:
        return jsonify({"status": "error", "message": "Missing source or target"}), 400

    m = get_manager()
    try:
        m.invert_transform(source, target)
        return jsonify({"status": "success"})
    except Exception as e:
        return jsonify({"status": "error", "message": str(e)}), 400


@app.route('/api/save', methods=['POST'])
def save_data():
    """保存到 YAML"""
    m = get_manager()
    try:
        m.save_to_yaml()
        return jsonify({"status": "success", "message": f"Saved to {m.yaml_dir}"})
    except Exception as e:
        return jsonify({"status": "error", "message": str(e)}), 500


@app.route('/api/cycles', methods=['GET'])
def detect_cycles():
    """检测环"""
    m = get_manager()
    cycles = m.detect_cycles()
    return jsonify({"cycles": cycles})


def run(host='0.0.0.0', port=5000, debug=True):
    """启动 Flask 服务（供命令行入口调用）。"""
    app.run(host=host, port=port, debug=debug)


if __name__ == '__main__':
    run()
