"""
스크립트 관리 라우트 및 API
"""
from flask import Blueprint, render_template, request, jsonify, send_file
from flask_login import login_required
from pathlib import Path
import yaml
import json
import logging

script_manager_bp = Blueprint("script_manager", __name__)

# 프로파일 디렉토리
PROFILES_DIR = Path(__file__).parent.parent.parent / "data" / "scripts" / "profiles"
UNIFIED_DIR = Path(__file__).parent.parent.parent / "data" / "scripts" / "unified"


@script_manager_bp.route("/script_manager")
@login_required
def index():
    """스크립트 관리 메인 페이지"""
    return render_template("script_manager.html")


@script_manager_bp.route("/api/profiles", methods=["GET"])
@login_required
def get_profiles():
    """모든 프로파일 목록 (카드 뷰용)"""
    profiles = []
    
    for yaml_file in PROFILES_DIR.glob("*.yaml"):
        try:
            with open(yaml_file, 'r', encoding='utf-8') as f:
                data = yaml.safe_load(f)
                category = yaml_file.stem.replace('_profiles', '')  # mac, guid, server_info
                
                for name, config in data.get('profiles', {}).items():
                    profiles.append({
                        "name": name,
                        "description": config.get("description", ""),
                        "category": category,
                        "items": _count_items(config, category),
                        "is_default": name == "default"
                    })
        except Exception as e:
            logging.error(f"프로파일 로드 오류 ({yaml_file}): {e}")
    
    return jsonify(profiles)


@script_manager_bp.route("/api/profiles/<category>", methods=["GET"])
@login_required
def get_profiles_by_category(category):
    """특정 카테고리의 프로파일 목록"""
    profiles = []
    # 파일명 매핑 (server_info -> server_info_profiles.yaml)
    # category가 mac, guid, server_info 등으로 넘어옴
    
    yaml_file = PROFILES_DIR / f"{category}_profiles.yaml"
    
    if not yaml_file.exists():
         return jsonify({"error": f"프로파일 파일이 없습니다: {category}"}), 404

    try:
        with open(yaml_file, 'r', encoding='utf-8') as f:
            data = yaml.safe_load(f)
            
            for name, config in data.get('profiles', {}).items():
                profiles.append({
                    "name": name,
                    "description": config.get("description", ""),
                    "category": category,
                    "items": _count_items(config, category),
                    "is_default": name == "default"
                })
    except Exception as e:
        logging.error(f"프로파일 로드 오류 ({yaml_file}): {e}")
        return jsonify({"error": str(e)}), 500
    
    return jsonify(profiles)


@script_manager_bp.route("/api/profiles/<category>/<path:name>", methods=["GET"])
@login_required
def get_profile(category, name):
    """특정 프로파일 상세 정보 (편집용)"""
    profile_file = PROFILES_DIR / f"{category}_profiles.yaml"
    
    if not profile_file.exists():
        return jsonify({"error": "프로파일 파일 없음"}), 404
    
    try:
        with open(profile_file, 'r', encoding='utf-8') as f:
            profiles = yaml.safe_load(f)['profiles']
        
        profile = profiles.get(name)
        if not profile:
            return jsonify({"error": "프로파일 없음"}), 404
        
        # UI 친화적 형식으로 변환
        return jsonify({
            "name": name,
            "description": profile.get("description", ""),
            "category": category,
            "config": profile
        })
    except Exception as e:
        logging.error(f"프로파일 로드 오류: {e}")
        return jsonify({"error": str(e)}), 500


@script_manager_bp.route("/api/profiles/<category>/<path:name>", methods=["PUT"])
@login_required
def update_profile(category, name):
    """프로파일 업데이트"""
    profile_file = PROFILES_DIR / f"{category}_profiles.yaml"
    
    if not profile_file.exists():
        return jsonify({"error": "프로파일 파일 없음"}), 404
    
    try:
        data = request.json
        
        # 기존 프로파일 로드
        with open(profile_file, 'r', encoding='utf-8') as f:
            profiles_data = yaml.safe_load(f)
        
        # 업데이트
        profiles_data['profiles'][name] = data.get('config', {})
        
        # 저장
        with open(profile_file, 'w', encoding='utf-8') as f:
            yaml.dump(profiles_data, f, allow_unicode=True, default_flow_style=False)
        
        return jsonify({"success": True, "message": "프로파일이 저장되었습니다."})
    except Exception as e:
        logging.error(f"프로파일 저장 오류: {e}")
        return jsonify({"error": str(e)}), 500


@script_manager_bp.route("/api/profiles/<category>", methods=["POST"])
@login_required
def create_profile(category):
    """새 프로파일 생성"""
    profile_file = PROFILES_DIR / f"{category}_profiles.yaml"
    
    if not profile_file.exists():
        return jsonify({"error": "프로파일 파일 없음"}), 404
    
    try:
        data = request.json
        name = data.get('name')
        
        if not name:
            return jsonify({"error": "프로파일 이름 필요"}), 400
        
        # 기존 프로파일 로드
        with open(profile_file, 'r', encoding='utf-8') as f:
            profiles_data = yaml.safe_load(f)
        
        # 중복 체크
        if name in profiles_data['profiles']:
            return jsonify({"error": "이미 존재하는 프로파일"}), 400
        
        # 새 프로파일 추가
        profiles_data['profiles'][name] = data.get('config', {})
        
        # 저장
        with open(profile_file, 'w', encoding='utf-8') as f:
            yaml.dump(profiles_data, f, allow_unicode=True, default_flow_style=False)
        
        return jsonify({"success": True, "message": "프로파일이 생성되었습니다."})
    except Exception as e:
        logging.error(f"프로파일 생성 오류: {e}")
        return jsonify({"error": str(e)}), 500


@script_manager_bp.route("/api/profiles/<category>/<path:name>", methods=["DELETE"])
@login_required
def delete_profile(category, name):
    """프로파일 삭제"""
    profile_file = PROFILES_DIR / f"{category}_profiles.yaml"
    
    if not profile_file.exists():
        return jsonify({"error": "프로파일 파일 없음"}), 404
    
    try:
        # default 프로파일은 삭제 불가
        if name == "default":
            return jsonify({"error": "기본 프로파일은 삭제할 수 없습니다."}), 400
        
        # 기존 프로파일 로드
        with open(profile_file, 'r', encoding='utf-8') as f:
            profiles_data = yaml.safe_load(f)
        
        # 삭제
        if name in profiles_data['profiles']:
            del profiles_data['profiles'][name]
        else:
            return jsonify({"error": "프로파일 없음"}), 404
        
        # 저장
        with open(profile_file, 'w', encoding='utf-8') as f:
            yaml.dump(profiles_data, f, allow_unicode=True, default_flow_style=False)
        
        return jsonify({"success": True, "message": "프로파일이 삭제되었습니다."})
    except Exception as e:
        logging.error(f"프로파일 삭제 오류: {e}")
        return jsonify({"error": str(e)}), 500


@script_manager_bp.route("/api/profiles/<category>/export", methods=["GET"])
@login_required
def export_profile(category):
    """프로파일 YAML 파일 다운로드"""
    name = request.args.get("name", "")
    if not name:
        return jsonify({"error": "프로파일 이름 필요"}), 400
    profile_file = PROFILES_DIR / f"{category}_profiles.yaml"
    
    if not profile_file.exists():
        return jsonify({"error": "프로파일 파일 없음"}), 404
    
    try:
        with open(profile_file, 'r', encoding='utf-8') as f:
            profiles = yaml.safe_load(f)
        
        # 단일 프로파일만 추출
        single_profile = {
            "profiles": {
                name: profiles['profiles'][name]
            }
        }
        
        # 임시 파일 생성
        temp_dir = Path(__file__).parent.parent.parent / "data" / "temp_zips"
        temp_dir.mkdir(parents=True, exist_ok=True)
        export_file = temp_dir / f"{name}_profile.yaml"
        
        with open(export_file, 'w', encoding='utf-8') as f:
            yaml.dump(single_profile, f, allow_unicode=True)
        
        return send_file(export_file, as_attachment=True, download_name=f"{name}_profile.yaml")
    except Exception as e:
        logging.error(f"프로파일 내보내기 오류: {e}")
        return jsonify({"error": str(e)}), 500


@script_manager_bp.route("/api/test_racadm", methods=["POST"])
@login_required
def test_racadm():
    """Racadm 명령어 테스트"""
    try:
        import subprocess
        
        data = request.json
        ip = data.get("ip")
        user = data.get("user", "root")
        password = data.get("password")
        command = data.get("command")
        
        if not all([ip, user, password, command]):
            return jsonify({"success": False, "error": "필수 입력값 누락"}), 400
            
        # 명령어 구성 (racadm -r <IP> -u <USER> -p <PW> <CMD>)
        # 보안을 위해 shell=False로 리스트 형태로 전달
        full_cmd = ["racadm", "-r", ip, "-u", user, "-p", password] + command.split()
        
        logging.info(f"[Test] Executing racadm on {ip}: {command}")
        
        # 타임아웃 30초
        result = subprocess.run(
            full_cmd,
            capture_output=True,
            text=True,
            timeout=30,
            check=False 
        )
        
        return jsonify({
            "success": True,
            "return_code": result.returncode,
            "output": result.stdout + (result.stderr if result.stderr else "")
        })
        
    except subprocess.TimeoutExpired:
        return jsonify({
            "success": False, 
            "error": "명령어 실행 시간 초과 (30초)"
        })
    except Exception as e:
        logging.error(f"[Test] Racadm execution error: {e}")
        return jsonify({"success": False, "error": str(e)})


def _count_items(profile: dict, category: str) -> int:
    """프로파일에서 수집할 항목 개수 계산"""
    count = 0
    
    if category == "mac":
        count += len(profile.get("nic_patterns", []))
        if profile.get("infiniband_slots"):
            count += len(profile["infiniband_slots"])
        if profile.get("include_idrac_mac"):
            count += 1
    elif category == "guid":
        count += len(profile.get("slot_priority", []))
    elif category == "gpu":
        # GUID slot priority + GPU settings
        count += len(profile.get("slot_priority", []))
        if profile.get("gpu_settings"):
            count += 1
    elif category == "server_info":
        count += len(profile.get("firmware", []))
        count += len(profile.get("bios_settings", []))
        count += len(profile.get("idrac_settings", []))
        count += len(profile.get("raid_settings", []))
        count += len(profile.get("custom_items", []))
    
    return count


def register_script_manager(app):
    """블루프린트 등록"""
    app.register_blueprint(script_manager_bp)
