{% extends "base.html" %}

{% block title %}스크립트 관리{% endblock %}

{% block content %}
<div class="container-fluid py-4">
    <div class="d-flex justify-content-between align-items-center mb-4">
        <h2><i class="bi bi-code-square"></i> 스크립트 관리</h2>
        <button class="btn btn-outline-info" data-bs-toggle="modal" data-bs-target="#yamlGuideModal">
            <i class="bi bi-question-circle"></i> YAML 작성 가이드
        </button>
    </div>

    <!-- 탭 네비게이션 -->
    <ul class="nav nav-tabs mb-3" id="scriptTabs" role="tablist">
        <li class="nav-item" role="presentation">
            <button class="nav-link active" id="mac-tab" data-bs-toggle="tab" data-bs-target="#mac" type="button">
                <i class="bi bi-ethernet"></i> MAC 수집
            </button>
        </li>
        <li class="nav-item" role="presentation">
            <button class="nav-link" id="server-tab" data-bs-toggle="tab" data-bs-target="#server" type="button">
                <i class="bi bi-server"></i> 서버 정보
            </button>
        </li>
        <li class="nav-item" role="presentation">
            <button class="nav-link" id="gpu-tab" data-bs-toggle="tab" data-bs-target="#gpu" type="button">
                <i class="bi bi-gpu-card"></i> GPU 서버 정보
            </button>
        </li>
        <li class="nav-item" role="presentation">
            <button class="nav-link" id="terminal-tab" data-bs-toggle="tab" data-bs-target="#terminal" type="button">
                <i class="bi bi-terminal"></i> 터미널
            </button>
        </li>
    </ul>

    <!-- 탭 컨텐츠 -->
    <div class="tab-content" id="scriptTabContent">
        <!-- MAC 수집 탭 -->
        <div class="tab-pane fade show active" id="mac" role="tabpanel">
            <div class="row g-3" id="macProfiles">
                <!-- 프로파일 카드가 여기에 동적으로 추가됨 -->
            </div>
        </div>

        <!-- 서버 정보 탭 -->
        <div class="tab-pane fade" id="server" role="tabpanel">
            <div class="row g-3" id="serverProfiles">
                <!-- 프로파일 카드가 여기에 동적으로 추가됨 -->
            </div>
        </div>

        <!-- GPU 서버 정보 탭 -->
        <div class="tab-pane fade" id="gpu" role="tabpanel">
            <div class="row g-3" id="gpuProfiles">
                <!-- 프로파일 카드가 여기에 동적으로 추가됨 -->
            </div>
        </div>

        <!-- 터미널 탭 (Racadm Tester) -->
        <div class="tab-pane fade" id="terminal" role="tabpanel">
            <div class="row">
                <div class="col-md-12">
                    <div class="card border shadow-sm">
                        <div class="card-header bg-light py-3">
                            <h5 class="mb-0"><i class="bi bi-terminal-fill me-2"></i>Racadm Command Tester</h5>
                        </div>
                        <div class="card-body p-4">
                            <form id="racadmForm" onsubmit="event.preventDefault(); runRacadmCommand();">
                                <div class="row g-3">
                                    <div class="col-md-3">
                                        <label class="form-label fw-bold">iDRAC IP</label>
                                        <input type="text" class="form-control" id="targetIp" placeholder="192.168.0.1"
                                            required>
                                    </div>
                                    <div class="col-md-3">
                                        <label class="form-label fw-bold">Username</label>
                                        <input type="text" class="form-control" id="targetUser" value="root">
                                    </div>
                                    <div class="col-md-3">
                                        <label class="form-label fw-bold">Password</label>
                                        <input type="password" class="form-control" id="targetPass" value="calvin">
                                    </div>
                                    <div class="col-md-3 d-flex align-items-end">
                                        <button type="submit" class="btn btn-dark w-100" id="btnRunCommand">
                                            <i class="bi bi-play-fill me-1"></i> Run Command
                                        </button>
                                    </div>
                                    <div class="col-12">
                                        <label class="form-label fw-bold">Command</label>
                                        <div class="input-group">
                                            <span class="input-group-text font-monospace bg-light">racadm</span>
                                            <input type="text" class="form-control font-monospace" id="targetCmd"
                                                placeholder="getsysinfo" value="getsysinfo" required>
                                        </div>
                                        <div class="form-text">Note: 'racadm' is automatically prepended. Just enter the
                                            arguments (e.g. 'getsysinfo' or 'get NIC.NICConfig.1').</div>
                                    </div>
                                </div>
                            </form>

                            <hr class="my-4">

                            <div>
                                <div class="d-flex justify-content-between align-items-center mb-2">
                                    <label class="form-label fw-bold mb-0">Output</label>
                                    <button class="btn btn-sm btn-outline-secondary"
                                        onclick="document.getElementById('cmdOutput').innerText=''">
                                        Clear
                                    </button>
                                </div>
                                <div class="bg-dark text-light p-3 rounded font-monospace"
                                    style="min-height: 200px; overflow: auto; resize: vertical;">
                                    <pre id="cmdOutput" class="mb-0 text-break" style="white-space: pre-wrap;"></pre>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>


<!-- YAML 가이드 모달 -->
<div class="modal fade" id="yamlGuideModal" tabindex="-1">
    <div class="modal-dialog modal-lg">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title"><i class="bi bi-book"></i> YAML 프로파일 작성 가이드</h5>
                <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
            </div>
            <div class="modal-body">
                <!-- 탭 메뉴 -->
                <ul class="nav nav-tabs mb-3" id="yamlGuideTabs" role="tablist">
                    <li class="nav-item">
                        <button class="nav-link active" data-bs-toggle="tab" data-bs-target="#guide-basic"><i
                                class="bi bi-lightbulb"></i> YAML 기초</button>
                    </li>
                    <li class="nav-item">
                        <button class="nav-link" data-bs-toggle="tab" data-bs-target="#guide-mac">MAC 수집</button>
                    </li>
                    <li class="nav-item">
                        <button class="nav-link" data-bs-toggle="tab" data-bs-target="#guide-server">서버 정보</button>
                    </li>
                    <li class="nav-item">
                        <button class="nav-link" data-bs-toggle="tab" data-bs-target="#guide-gpu">GPU/GUID</button>
                    </li>
                </ul>

                <!-- 탭 컨텐츠 -->
                <div class="tab-content border p-3 rounded bg-light" style="max-height: 60vh; overflow-y: auto;">

                    <!-- 1. YAML 기초 -->
                    <div class="tab-pane fade show active" id="guide-basic">
                        <h5 class="mb-3 text-primary">YAML 파일 작성 규칙 (초보자 필독)</h5>
                        <div class="alert alert-warning">
                            <strong><i class="bi bi-exclamation-triangle-fill"></i> 가장 중요한 규칙 2가지</strong>
                            <ol class="mb-0 mt-2">
                                <li><strong>들여쓰기(띄어쓰기)</strong>: 절대 <code>Tab</code> 키를 쓰지 마세요! <span
                                        class="badge bg-danger">스페이스바 2칸</span>을 사용해야 합니다.</li>
                                <li><strong>콜론(:) 다음 공백</strong>: <code>key:value</code> (X) -> <code>key: value</code>
                                    (O) <br>콜론 뒤에는 반드시 한 칸을 띄워야 합니다.</li>
                            </ol>
                        </div>

                        <div class="card mb-3">
                            <div class="card-header fw-bold">구조 이해하기</div>
                            <div class="card-body">
                                <p class="card-text">설정은 크게 <strong>이름(Key)</strong>과 <strong>값(Value)</strong>으로 나뉩니다.
                                </p>
                                <div class="row">
                                    <div class="col-md-6">
                                        <h6><i class="bi bi-list-ul"></i> 목록 (List) 작성법</h6>
                                        <p class="small text-muted">여러 개의 값을 넣으려면 대쉬(<code>-</code>)를 사용합니다.</p>
                                        <pre class="bg-dark text-light p-2 rounded small"><code># 과일 목록 예시
fruits:
  - "사과"    # 리스트 1
  - "바나나"  # 리스트 2
  - "포도"    # 리스트 3</code></pre>
                                    </div>
                                    <div class="col-md-6">
                                        <h6><i class="bi bi-card-text"></i> 설정 (Object) 작성법</h6>
                                        <p class="small text-muted">하위 설정을 넣으려면 들여쓰기를 합니다.</p>
                                        <pre class="bg-dark text-light p-2 rounded small"><code># 자동차 설정 예시
car:
  color: "Red"     # 스페이스 2칸
  speed: 100       # 스페이스 2칸
  is_active: true  # 스페이스 2칸</code></pre>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>

                    <!-- 2. MAC 수집 -->
                    <div class="tab-pane fade" id="guide-mac">
                        <h5 class="mb-3">MAC 주소 수집 프로파일</h5>
                        <p class="text-muted">서버의 네트워크 카드(NIC)의 물리적 주소(MAC)를 가져오는 설정입니다.</p>

                        <div class="card mb-3 border-primary">
                            <div class="card-header bg-primary text-white">복사해서 사용하세요</div>
                            <div class="card-body bg-dark text-light p-0">
                                <pre class="m-0 p-3"><code>description: "기본 MAC 수집 설정"

# 1. 수집할 NIC(네트워크 카드)의 이름 패턴
nic_patterns:
  - "NIC.Integrated.1"  # 메인보드 내장 랜카드 1번
  - "NIC.Slot.*"        # 슬롯에 꽂힌 모든 랜카드 (PCIe)

# 2. InfiniBand(고속 네트워크) 카드가 있다면 슬롯 번호를 적으세요
infiniband_slots:
  - "PCIeSlot3"         # 3번 슬롯에 꽂힌 카드

# 3. iDRAC 전용 포트의 MAC도 필요하면 true로 설정
include_idrac_mac: true</code></pre>
                            </div>
                        </div>

                        <h6 class="mt-4"><i class="bi bi-question-circle-fill"></i> 상세 설명</h6>
                        <table class="table table-sm table-bordered bg-white">
                            <thead class="table-light">
                                <tr>
                                    <th>항목</th>
                                    <th>설명</th>
                                </tr>
                            </thead>
                            <tbody>
                                <tr>
                                    <td><code>nic_patterns</code></td>
                                    <td>가져올 랜카드의 이름입니다. <code>*</code>(별표)는 '모두'를 의미합니다.<br>예: <code>NIC.*</code>는 모든
                                        랜카드를 다 가져옵니다.</td>
                                </tr>
                                <tr>
                                    <td><code>infiniband_slots</code></td>
                                    <td>InfiniBand는 일반 NIC와 달라서 슬롯 번호(예: PCIeSlot3)를 정확히 적어야 합니다.</td>
                                </tr>
                            </tbody>
                        </table>
                    </div>

                    <!-- 3. 서버 정보 -->
                    <div class="tab-pane fade" id="guide-server">
                        <h5 class="mb-3">서버 정보 수집 프로파일</h5>
                        <p class="text-muted">서버의 펌웨어, BIOS 설정, 하드웨어 상태 등을 확인하는 설정입니다.</p>

                        <div class="card mb-3 border-success">
                            <div class="card-header bg-success text-white">복사해서 사용하세요</div>
                            <div class="card-body bg-dark text-light p-0">
                                <pre class="m-0 p-3"><code>description: "서버 점검용 설정"

# 1. 버전 정보를 알고 싶은 펌웨어 이름들
firmware:
  - "iDRAC"
  - "BIOS"
  - "NIC"

# 2. 확인하고 싶은 BIOS 설정값
bios_settings:
  - "MemTest"           # 메모리 테스트 옵션
  - "LogicalProc"       # 하이퍼스레딩(논리코어)

# 3. RAID 컨트롤러의 디스크 정보
raid_settings:
  - "Disk.Bay.0"        # 0번 베이의 하드디스크 정보

# 4. 기타 명령어 실행 (상급자용)
custom_items:
  - command: "getsysinfo"
    label: "전체 시스템 요약"</code></pre>
                            </div>
                        </div>
                    </div>

                    <!-- 4. GPU/GUID -->
                    <div class="tab-pane fade" id="guide-gpu">
                        <h5 class="mb-3">GPU 및 GUID 설정</h5>
                        <p class="text-muted">GPU의 시리얼 번호를 수집하거나, iDRAC MAC 주소를 기반으로 GUID를 생성할 때 사용합니다.</p>

                        <div class="card mb-3 border-danger">
                            <div class="card-header bg-danger text-white">복사해서 사용하세요</div>
                            <div class="card-body bg-dark text-light p-0">
                                <pre class="m-0 p-3"><code>description: "GPU 서버용 설정"

# 1. GPU 시리얼 수집 설정 (GPU가 있는 경우 필수)
gpu_settings:
  target_slots: 
    - "Video.Slot.*"    # 모든 비디오 카드 수집
  sort_order: "slot_index" # 슬롯 순서대로 정렬

# 2. GUID 생성 시 슬롯 우선순위
# iDRAC MAC 말고, 특정 랜카드의 MAC을 GUID로 쓰고 싶을 때 사용
slot_priority: 
  - 38  # 38번 슬롯 카드의 MAC을 1순위로 사용
  - 1   # 없으면 1번 슬롯 사용

output_format: "combined"</code></pre>
                            </div>
                        </div>
                        <div class="alert alert-light border">
                            <strong><i class="bi bi-lightbulb"></i> 팁:</strong> GPU 시리얼만 필요하다면
                            <code>slot_priority</code> 부분은 지워도 됩니다.
                        </div>
                    </div>
                </div>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">닫기</button>
            </div>
        </div>
    </div>
</div>

<!-- 프로파일 편집 모달 -->
<div class="modal fade" id="profileModal" tabindex="-1">
    <div class="modal-dialog modal-lg">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title" id="profileModalTitle">프로파일 편집</h5>
                <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
            </div>
            <div class="modal-body">
                <div class="mb-3">
                    <label class="form-label">프로파일 이름</label>
                    <input type="text" class="form-control" id="profileName" readonly>
                </div>
                <div class="mb-3">
                    <label class="form-label">설명</label>
                    <input type="text" class="form-control" id="profileDescription">
                </div>
                <div class="mb-3">
                    <label class="form-label">설정 (YAML)</label>
                    <textarea class="form-control font-monospace" id="profileConfig" rows="15"></textarea>
                    <small class="text-muted">YAML 형식으로 프로파일 설정을 편집할 수 있습니다.</small>
                </div>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">취소</button>
                <button type="button" class="btn btn-primary" onclick="saveProfile()">
                    <i class="bi bi-save"></i> 저장
                </button>
            </div>
        </div>
    </div>
</div>

<style>
    .profile-card {
        transition: transform 0.2s, box-shadow 0.2s;
    }

    .profile-card:hover {
        transform: translateY(-5px);
        box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
    }

    .profile-card .card-body {
        min-height: 180px;
    }

    .border-dashed {
        border-style: dashed !important;
    }

    /* 탭 가시성 강제 설정 */
    .nav-tabs .nav-link {
        color: #495057 !important;
        font-weight: 500;
    }

    .nav-tabs .nav-link.active {
        color: #fff !important;
        background-color: #0d6efd !important;
    }

    .nav-tabs .nav-link:hover {
        color: #0a58ca !important;
    }
</style>

<script>
    let currentCategory = 'mac';
    let currentProfile = null;
    let allProfiles = [];

    // 페이지 로드 시 프로파일 목록 가져오기
    document.addEventListener('DOMContentLoaded', function () {
        loadProfiles();
    });

    // 프로파일 목록 로드
    async function loadProfiles() {
        // 로딩 표시
        ['macProfiles', 'serverProfiles', 'gpuProfiles'].forEach(id => {
            const el = document.getElementById(id);
            if (el) el.innerHTML = '<div class="col-12 text-center py-5"><div class="spinner-border text-primary" role="status"></div><p class="mt-2 text-muted">프로파일을 불러오는 중입니다...</p></div>';
        });

        try {
            const response = await fetch('/api/profiles');
            if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);

            allProfiles = await response.json();

            if (!Array.isArray(allProfiles)) throw new Error('데이터 형식이 올바르지 않습니다.');

            renderProfiles();
        } catch (error) {
            console.error('프로파일 로드 오류:', error);
            // 에러 표시
            ['macProfiles', 'serverProfiles', 'gpuProfiles'].forEach(id => {
                const el = document.getElementById(id);
                if (el) el.innerHTML = `<div class="col-12 text-center py-5"><i class="bi bi-exclamation-triangle text-danger fs-1"></i><p class="mt-2 text-danger">프로파일을 불러오지 못했습니다.<br><small>${error.message}</small></p></div>`;
            });
        }
    }

    // 프로파일 렌더링
    function renderProfiles() {
        const gpuContainer = document.getElementById('gpuProfiles');
        const categories = {
            'mac': document.getElementById('macProfiles'),
            'server_info': document.getElementById('serverProfiles'),
            'guid': gpuContainer,
            'gpu': gpuContainer
        };

        // 각 카테고리 초기화
        Object.values(categories).forEach(el => { if (el) el.innerHTML = ''; });

        // 프로파일 카드 생성
        allProfiles.forEach(profile => {
            const container = categories[profile.category];
            if (!container) return;

            const card = createProfileCard(profile);
            container.insertAdjacentHTML('beforeend', card);
        });

        // 새 프로파일 추가 카드
        const targets = [
            { cat: 'mac', el: document.getElementById('macProfiles') },
            { cat: 'server_info', el: document.getElementById('serverProfiles') },
            { cat: 'gpu', el: gpuContainer }
        ];

        targets.forEach(t => {
            if (t.el) t.el.insertAdjacentHTML('beforeend', createNewProfileCard(t.cat));
        });
    }

    // 프로파일 카드 HTML 생성
    function createProfileCard(profile) {
        const badgeClass = profile.is_default ? 'bg-success' : 'bg-secondary';
        const badgeText = profile.is_default ? '기본' : '사용자 정의';

        return `
        <div class="col-md-4">
            <div class="card profile-card">
                <div class="card-body">
                    <div class="d-flex justify-content-between align-items-start mb-2">
                        <div>
                            <h5 class="card-title">
                                ${profile.is_default ? '<i class="bi bi-star-fill text-warning"></i>' : ''}
                                ${profile.name}
                            </h5>
                            <p class="card-text text-muted small">${profile.description}</p>
                        </div>
                        <span class="badge ${badgeClass}">${badgeText}</span>
                    </div>
                    
                    <div class="mt-3">
                        <small class="text-muted">수집 항목:</small>
                        <div class="mt-1">
                            <span class="badge bg-light text-dark">${profile.items}개</span>
                        </div>
                    </div>
                    
                    <div class="mt-3 d-flex gap-2">
                        <button class="btn btn-sm btn-outline-primary flex-fill" onclick="editProfile('${profile.category}', '${profile.name}')">
                            <i class="bi bi-pencil"></i> 편집
                        </button>
                        <button class="btn btn-sm btn-outline-secondary" onclick="exportProfile('${profile.category}', '${profile.name}')">
                            <i class="bi bi-download"></i> 내보내기
                        </button>
                        ${!profile.is_default ? `
                        <button class="btn btn-sm btn-outline-danger" onclick="deleteProfile('${profile.category}', '${profile.name}')">
                            <i class="bi bi-trash"></i>
                        </button>
                        ` : ''}
                    </div>
                </div>
            </div>
        </div>
    `;
    }

    // 새 프로파일 추가 카드
    function createNewProfileCard(category) {
        return `
        <div class="col-md-4">
            <div class="card profile-card border-dashed" style="border: 2px dashed #dee2e6;">
                <div class="card-body d-flex flex-column align-items-center justify-content-center" style="min-height: 180px;">
                    <i class="bi bi-plus-circle fs-1 text-muted mb-3"></i>
                    <button class="btn btn-outline-primary" onclick="createNewProfile('${category}')">
                        새 프로파일 만들기
                    </button>
                </div>
            </div>
        </div>
    `;
    }

    // 프로파일 편집
    async function editProfile(category, name) {
        try {
            const response = await fetch(`/api/profiles/${category}/${name}`);
            const profile = await response.json();

            currentCategory = category;
            currentProfile = name;

            document.getElementById('profileName').value = name;
            document.getElementById('profileDescription').value = profile.description;
            document.getElementById('profileConfig').value = JSON.stringify(profile.config, null, 2);

            const modal = new bootstrap.Modal(document.getElementById('profileModal'));
            modal.show();
        } catch (error) {
            console.error('프로파일 로드 오류:', error);
            alert('프로파일을 불러오는 중 오류가 발생했습니다.');
        }
    }

    // 프로파일 저장
    async function saveProfile() {
        try {
            const config = JSON.parse(document.getElementById('profileConfig').value);

            const response = await fetch(`/api/profiles/${currentCategory}/${currentProfile}`, {
                method: 'PUT',
                headers: {
                    'Content-Type': 'application/json',
                    'X-CSRFToken': '{{ csrf_token() }}'
                },
                body: JSON.stringify({
                    config: config
                })
            });

            const result = await response.json();

            if (result.success) {
                alert('프로파일이 저장되었습니다.');
                bootstrap.Modal.getInstance(document.getElementById('profileModal')).hide();
                loadProfiles();
            } else {
                alert('저장 실패: ' + result.error);
            }
        } catch (error) {
            console.error('저장 오류:', error);
            alert('프로파일 저장 중 오류가 발생했습니다.');
        }
    }

    // 프로파일 내보내기
    function exportProfile(category, name) {
        window.location.href = `/api/profiles/${category}/export?name=${encodeURIComponent(name)}`;
    }

    // 프로파일 삭제
    async function deleteProfile(category, name) {
        if (!confirm(`'${name}' 프로파일을 삭제하시겠습니까?`)) return;

        try {
            const response = await fetch(`/api/profiles/${category}/${name}`, {
                method: 'DELETE',
                headers: {
                    'X-CSRFToken': '{{ csrf_token() }}'
                }
            });

            const result = await response.json();

            if (result.success) {
                alert('프로파일이 삭제되었습니다.');
                loadProfiles();
            } else {
                alert('삭제 실패: ' + result.error);
            }
        } catch (error) {
            console.error('삭제 오류:', error);
            alert('프로파일 삭제 중 오류가 발생했습니다.');
        }
    }

    // 새 프로파일 만들기
    function createNewProfile(category) {
        const name = prompt('새 프로파일 이름을 입력하세요:');
        if (!name) return;

        // 기본 설정으로 프로파일 생성
        const defaultConfig = {
            description: "새 프로파일",
            extends: "default"
        };

        fetch(`/api/profiles/${category}`, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'X-CSRFToken': '{{ csrf_token() }}'
            },
            body: JSON.stringify({
                name: name,
                config: defaultConfig
            })
        })
            .then(response => response.json())
            .then(result => {
                if (result.success) {
                    alert('프로파일이 생성되었습니다.');
                    loadProfiles();
                } else {
                    alert('생성 실패: ' + result.error);
                }
            })
            .catch(error => {
                console.error('생성 오류:', error);
                alert('프로파일 생성 중 오류가 발생했습니다.');
            });
    }

    async function runRacadmCommand() {
        const ip = document.getElementById('targetIp').value;
        const user = document.getElementById('targetUser').value;
        const pass = document.getElementById('targetPass').value;
        const cmd = document.getElementById('targetCmd').value;
        const outputPre = document.getElementById('cmdOutput');
        const btn = document.getElementById('btnRunCommand');

        if (!ip || !user || !pass || !cmd) {
            alert('모든 필드를 입력하세요.');
            return;
        }

        // UI Reset
        outputPre.innerText = "Executing...";
        btn.disabled = true;
        btn.innerHTML = '<span class="spinner-border spinner-border-sm me-1"></span>Running...';

        try {
            const response = await fetch('/api/test_racadm', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'X-CSRFToken': '{{ csrf_token() }}'
                },
                body: JSON.stringify({
                    ip: ip,
                    user: user,
                    password: pass,
                    command: cmd
                })
            });

            const result = await response.json();

            if (result.success) {
                // Return code가 0이 아니면 실패로 간주하거나, 그대로 출력
                let displayText = `[Success]\n${result.output}`;
                if (result.return_code !== 0) {
                    displayText = `[Error (Code: ${result.return_code})]\n${result.output}`;
                }
                outputPre.innerText = displayText;
            } else {
                outputPre.innerText = `[Error]\n${result.error}`;
            }

        } catch (error) {
            console.error('Execution error:', error);
            outputPre.innerText = `[System Error]\n${error.message}`;
        } finally {
            btn.disabled = false;
            btn.innerHTML = '<i class="bi bi-play-fill me-1"></i> Run Command';
        }
    }
</script>
{% endblock %}