from __future__ import annotations
import os
import sys
import shutil
import subprocess
import logging
from pathlib import Path
from flask import Blueprint, request, redirect, url_for, flash, jsonify, send_file
from flask_login import login_required
from config import Config

utils_bp = Blueprint("utils", __name__)


def register_util_routes(app):
    app.register_blueprint(utils_bp)


@utils_bp.route("/move_mac_files", methods=["POST"])
@login_required
def move_mac_files():
    src = Path(Config.IDRAC_INFO_FOLDER)
    dst = Path(Config.MAC_FOLDER)
    dst.mkdir(parents=True, exist_ok=True)

    moved = 0
    errors = []
    
    try:
        for file in src.iterdir():
            if not file.is_file():
                continue
            
            try:
                # 파일이 존재하는지 확인
                if not file.exists():
                    errors.append(f"{file.name}: 파일이 존재하지 않음")
                    continue
                
                # 대상 파일이 이미 존재하는 경우 건너뛰기
                target = dst / file.name
                if target.exists():
                    logging.warning(f"⚠️ 파일이 이미 존재하여 건너뜀: {file.name}")
                    continue
                
                shutil.move(str(file), str(target))
                moved += 1
                
            except Exception as e:
                error_msg = f"{file.name}: {str(e)}"
                errors.append(error_msg)
                logging.error(f"❌ 파일 이동 실패: {error_msg}")
        
        # 결과 로깅
        if moved > 0:
            logging.info(f"✅ MAC 파일 이동 완료 ({moved}개)")
        
        if errors:
            logging.warning(f"⚠️ 일부 파일 이동 실패: {errors}")
        
        # 하나라도 성공하면 success: true 반환
        return jsonify({
            "success": True,
            "moved": moved,
            "errors": errors if errors else None
        })
        
    except Exception as e:
        logging.error(f"❌ MAC 이동 중 치명적 오류: {e}")
        return jsonify({"success": False, "error": str(e)})


@utils_bp.route("/move_guid_files", methods=["POST"])
@login_required
def move_guid_files():
    src = Path(Config.IDRAC_INFO_FOLDER)
    dst = Path(Config.GUID_FOLDER)
    dst.mkdir(parents=True, exist_ok=True)

    moved = 0
    errors = []
    
    try:
        for file in src.iterdir():
            if not file.is_file():
                continue
            
            try:
                # 파일이 존재하는지 확인
                if not file.exists():
                    errors.append(f"{file.name}: 파일이 존재하지 않음")
                    continue
                
                # 대상 파일이 이미 존재하는 경우 건너뛰기
                target = dst / file.name
                if target.exists():
                    logging.warning(f"⚠️ 파일이 이미 존재하여 건너뜀: {file.name}")
                    continue
                
                shutil.move(str(file), str(target))
                moved += 1
                
            except Exception as e:
                error_msg = f"{file.name}: {str(e)}"
                errors.append(error_msg)
                logging.error(f"❌ 파일 이동 실패: {error_msg}")
        
        # 결과 메시지
        if moved > 0:
            flash(f"GUID 파일이 성공적으로 이동되었습니다. ({moved}개)", "success")
            logging.info(f"✅ GUID 파일 이동 완료 ({moved}개)")
        
        if errors:
            logging.warning(f"⚠️ 일부 파일 이동 실패: {errors}")
            flash(f"일부 파일 이동 실패: {len(errors)}개", "warning")
            
    except Exception as e:
        logging.error(f"❌ GUID 이동 오류: {e}")
        flash(f"오류 발생: {e}", "danger")
    
    return redirect(url_for("main.index"))

@utils_bp.route("/move_gpu_files", methods=["POST"])
@login_required
def move_gpu_files():
    """
    data/idrac_info → data/gpu_serial 로 GPU 시리얼 텍스트 파일 이동
    """
    src = Path(Config.IDRAC_INFO_FOLDER)      # 예: data/idrac_info
    dst = Path(Config.GPU_FOLDER)      # 예: data/gpu_serial
    dst.mkdir(parents=True, exist_ok=True)

    moved = 0
    errors = []

    try:
        for file in src.iterdir():
            if not file.is_file():
                continue

            # GPU 관련 텍스트 파일만 이동 (GUID 등 제외)
            if not file.name.lower().endswith(".txt"):
                continue

            try:
                # 파일 존재 확인
                if not file.exists():
                    errors.append(f"{file.name}: 파일이 존재하지 않음")
                    continue

                # 대상 파일이 이미 존재하면 스킵
                target = dst / file.name
                if target.exists():
                    logging.warning(f"⚠️ 이미 존재하여 건너뜀: {file.name}")
                    continue

                # 파일 이동
                shutil.move(str(file), str(target))
                moved += 1

            except Exception as e:
                error_msg = f"{file.name}: {str(e)}"
                errors.append(error_msg)
                logging.error(f"❌ GPU 파일 이동 실패: {error_msg}")

        # 결과 메시지
        if moved > 0:
            flash(f"GPU 시리얼 파일이 성공적으로 이동되었습니다. ({moved}개)", "success")
            logging.info(f"✅ GPU 파일 이동 완료 ({moved}개)")

        if errors:
            logging.warning(f"⚠️ 일부 파일 이동 실패: {errors}")
            flash(f"일부 GPU 파일 이동 실패: {len(errors)}개", "warning")

    except Exception as e:
        logging.error(f"❌ GPU 이동 오류: {e}")
        flash(f"오류 발생: {e}", "danger")

    return redirect(url_for("main.index"))

@utils_bp.route("/update_server_list", methods=["POST"])
@login_required
def update_server_list():
    content = request.form.get("server_list_content")
    if not content:
        flash("내용을 입력하세요.", "warning")
        return redirect(url_for("main.index"))

    path = Path(Config.SERVER_LIST_FOLDER) / "server_list.txt"
    try:
        path.write_text(content, encoding="utf-8")
        result = subprocess.run(
            [sys.executable, str(Path(Config.SERVER_LIST_FOLDER) / "excel.py")],
            capture_output=True,
            text=True,
            check=True,
            cwd=str(Path(Config.SERVER_LIST_FOLDER)),
            timeout=300,
        )
        logging.info(f"서버 리스트 스크립트 실행 결과: {result.stdout}")
        flash("서버 리스트가 업데이트되었습니다.", "success")
    except subprocess.CalledProcessError as e:
        logging.error(f"서버 리스트 스크립트 오류: {e.stderr}")
        flash(f"스크립트 실행 실패: {e.stderr}", "danger")
    except Exception as e:
        logging.error(f"서버 리스트 처리 오류: {e}")
        flash(f"서버 리스트 처리 중 오류 발생: {e}", "danger")

    return redirect(url_for("main.index"))


@utils_bp.route("/update_guid_list", methods=["POST"])
@login_required
def update_guid_list():
    content = request.form.get("server_list_content")
    if not content:
        flash("내용을 입력하세요.", "warning")
        return redirect(url_for("main.index"))

    path = Path(Config.SERVER_LIST_FOLDER) / "guid_list.txt"
    try:
        path.write_text(content, encoding="utf-8")
        result = subprocess.run(
            [sys.executable, str(Path(Config.SERVER_LIST_FOLDER) / "GUIDtxtT0Execl.py")],
            capture_output=True,
            text=True,
            check=True,
            cwd=str(Path(Config.SERVER_LIST_FOLDER)),
            timeout=300,
        )
        logging.info(f"GUID 리스트 스크립트 실행 결과: {result.stdout}")
        flash("GUID 리스트가 업데이트되었습니다.", "success")
    except subprocess.CalledProcessError as e:
        logging.error(f"GUID 리스트 스크립트 오류: {e.stderr}")
        flash(f"스크립트 실행 실패: {e.stderr}", "danger")
    except Exception as e:
        logging.error(f"GUID 리스트 처리 오류: {e}")
        flash(f"GUID 리스트 처리 중 오류 발생: {e}", "danger")

    return redirect(url_for("main.index"))

@utils_bp.route("/update_gpu_list", methods=["POST"])
@login_required
def update_gpu_list():
    """
    GPU 시리얼용 리스트(gpu_serial_list.txt)를 갱신하고 Excel을 생성합니다.
    - form name="gpu_list_content" 로 내용 전달 (S/T 목록 라인별)
    - txt_to_excel.py --preset gpu --list-file <gpu_serial_list.txt>
    """
    content = request.form.get("server_list_content")
    if not content:
        flash("내용을 입력하세요.", "warning")
        return redirect(url_for("main.index"))

    server_list_dir = Path(Config.SERVER_LIST_FOLDER)
    list_path = server_list_dir / "gpu_list.txt"
    # txt_to_excel.py는 server_list 폴더에 둔다고 가정 (위치 다르면 경로만 수정)
    script_path = server_list_dir / "GPUTOExecl.py"

    try:
        # 1) gpu_serial_list.txt 저장
        list_path.write_text(content, encoding="utf-8")

        # 2) 엑셀 생성 실행 (GPU 프리셋)
        cmd = [
            sys.executable,
            str(script_path),
            "--preset", "gpu",
            "--list-file", str(list_path),
        ]
        result = subprocess.run(
            cmd,
            capture_output=True,
            text=True,
            check=True,
            cwd=str(server_list_dir),  # data/server_list 기준 실행
            timeout=300,
        )
        logging.info(f"[GPU] 리스트 스크립트 실행 STDOUT:\n{result.stdout}")
        if result.stderr:
            logging.warning(f"[GPU] 리스트 스크립트 STDERR:\n{result.stderr}")

        flash("GPU 리스트가 업데이트되었습니다.", "success")
    except subprocess.CalledProcessError as e:
        logging.error(f"[GPU] 스크립트 오류: {e.stderr}")
        flash(f"스크립트 실행 실패: {e.stderr}", "danger")
    except Exception as e:
        logging.error(f"[GPU] 처리 오류: {e}")
        flash(f"GPU 리스트 처리 중 오류 발생: {e}", "danger")

    return redirect(url_for("main.index"))

@utils_bp.route("/download_excel")
@login_required
def download_excel():
    path = Path(Config.SERVER_LIST_FOLDER) / "mac_info.xlsx"
    if not path.is_file():
        flash("엑셀 파일을 찾을 수 없습니다.", "danger")
        return redirect(url_for("main.index"))

    logging.info(f"엑셀 파일 다운로드: {path}")
    return send_file(str(path), as_attachment=True, download_name="mac_info.xlsx")