<?php
/**
 * 가사 직접 입력 및 수정 폼 페이지
 */

require_once __DIR__ . '/config/config.php';
require_once __DIR__ . '/includes/db.php';
require_once __DIR__ . '/includes/functions.php';
require_once __DIR__ . '/includes/auth.php';
require_once __DIR__ . '/includes/layout.php';
requireAdmin();

$pdo = getDBConnection();
$songId = isset($_GET['song_id']) ? intval($_GET['song_id']) : (isset($_GET['id']) ? intval($_GET['id']) : 0);

if ($songId <= 0) {
    renderHeader('오류');
    ?>
    <div class="alert-box alert-danger">
        <div class="alert-icon"><i class="fas fa-exclamation-triangle"></i></div>
        <div class="alert-content">
            <h3>잘못된 접근</h3>
            <p>유효하지 않은 곡 ID입니다.</p>
        </div>
    </div>
    <a href="index.php" class="btn btn-secondary">홈으로 돌아가기</a>
    <?php
    renderFooter();
    exit;
}

// 1. 곡 기본 정보 조회
$songStmt = $pdo->prepare("
    SELECT id, title, artist, album, duration, cover_hash, metadata_updated_at, updated_at
    FROM songs
    WHERE id = :id AND is_missing = 0
");
$songStmt->execute([':id' => $songId]);
$song = $songStmt->fetch();

if (!$song) {
    renderHeader('오류');
    ?>
    <div class="alert-box alert-danger">
        <div class="alert-icon"><i class="fas fa-exclamation-triangle"></i></div>
        <div class="alert-content">
            <h3>존재하지 않는 곡</h3>
            <p>스캔 목록에서 해당 곡을 찾을 수 없습니다.</p>
        </div>
    </div>
    <a href="index.php" class="btn btn-secondary">홈으로 돌아가기</a>
    <?php
    renderFooter();
    exit;
}

// 2. 기존 가사 정보 조회
$lyricsStmt = $pdo->prepare("SELECT lyrics_text FROM lyrics WHERE song_id = :song_id");
$lyricsStmt->execute([':song_id' => $songId]);
$lyrics = $lyricsStmt->fetch();
$currentLyrics = $lyrics ? $lyrics['lyrics_text'] : '';
$songTitle = trim(ensureUtf8String($song['title'] ?? ''));
$artistText = trim(artistName($song['artist'] ?? ''));
$albumText = trim(albumName($song['album'] ?? ''));
$songDuration = max(0, (int)($song['duration'] ?? 0));
$lyricsSearchParts = array_values(array_filter([$artistText, $songTitle, '가사'], static function ($value) {
    return trim((string)$value) !== '';
}));
$lyricsSearchQuery = implode(' ', $lyricsSearchParts);
$encodedLyricsSearch = rawurlencode($lyricsSearchQuery);
$hasLyrics = trim((string)$currentLyrics) !== '';
$lyricsSearchLinks = [
    ['label' => '네이버', 'icon' => 'fa-solid fa-magnifying-glass', 'url' => 'https://search.naver.com/search.naver?query=' . $encodedLyricsSearch],
    ['label' => '구글', 'icon' => 'fa-brands fa-google', 'url' => 'https://www.google.com/search?q=' . $encodedLyricsSearch],
    ['label' => '멜론', 'icon' => 'fa-solid fa-music', 'url' => 'https://www.melon.com/search/total/index.htm?q=' . $encodedLyricsSearch],
    ['label' => '벅스', 'icon' => 'fa-solid fa-headphones', 'url' => 'https://music.bugs.co.kr/search/integrated?q=' . $encodedLyricsSearch],
    ['label' => '지니', 'icon' => 'fa-solid fa-record-vinyl', 'url' => 'https://www.genie.co.kr/search/searchMain?query=' . $encodedLyricsSearch],
];

renderHeader($song['title'] . ' 가사 편집', 'all');
?>

<div class="lyrics-edit-page">
    <div class="lyrics-edit-shell">
        <header class="lyrics-edit-hero">
            <div class="lyrics-edit-art">
                <img src="<?php echo h(coverUrl($song)); ?>" alt="" width="96" height="96" onerror="this.onerror=null;this.src='assets/img/default-cover.svg';">
            </div>
            <div class="lyrics-edit-title-block">
                <span class="section-kicker">가사 편집</span>
                <h1 class="page-main-title">가사 입력 / 수정</h1>
                <p class="page-subtitle">
                    <strong><?php echo h($song['title']); ?></strong>
                    <span><?php echo h(artistName($song['artist'] ?? '')); ?></span>
                    <?php if (!empty($song['album'])): ?><span><?php echo h(albumName($song['album'])); ?></span><?php endif; ?>
                </p>
            </div>
            <a href="song.php?id=<?php echo h($song['id']); ?>" class="btn btn-secondary lyrics-edit-back">
                <i class="fas fa-arrow-left"></i> 곡 상세
            </a>
        </header>

        <!-- 저장 결과 토스트 (AJAX 응답 표시용) -->
        <div id="lyrics-save-toast" class="lyrics-save-toast" role="status" aria-live="polite"></div>

        <section class="lyrics-helper-card"
                 data-lyrics-helper
                 data-title="<?php echo h($songTitle); ?>"
                 data-artist="<?php echo h($artistText); ?>"
                 data-album="<?php echo h($albumText); ?>"
                 data-search-query="<?php echo h($lyricsSearchQuery); ?>">
            <div class="lyrics-helper-heading">
                <div>
                    <span class="section-kicker">가사 검색 도우미</span>
                    <h2>웹에서 확인하고 붙여넣기</h2>
                    <p>외부 사이트의 가사는 직접 확인 후 개인 이용 범위에서 등록해 주세요. 이 기능은 자동 수집이 아니라 검색과 붙여넣기를 도와주는 기능입니다.</p>
                </div>
                <span class="lyrics-status-badge <?php echo $hasLyrics ? 'has-lyrics' : 'no-lyrics'; ?>">
                    <i class="fas <?php echo $hasLyrics ? 'fa-check-circle' : 'fa-circle-exclamation'; ?>"></i>
                    <?php echo $hasLyrics ? '가사 있음' : '가사 없음'; ?>
                </span>
            </div>

            <div class="lyrics-helper-meta">
                <div><span>곡명</span><strong><?php echo h($songTitle !== '' ? $songTitle : '제목 없음'); ?></strong></div>
                <div><span>아티스트</span><strong><?php echo h($artistText !== '' ? $artistText : '아티스트 없음'); ?></strong></div>
                <div><span>앨범</span><strong><?php echo h($albumText !== '' ? $albumText : '앨범 없음'); ?></strong></div>
                <div class="lyrics-helper-query"><span>검색어</span><strong id="lyrics-search-query"><?php echo h($lyricsSearchQuery); ?></strong></div>
            </div>

            <div class="lyrics-search-actions" aria-label="외부 가사 검색">
                <?php foreach ($lyricsSearchLinks as $link): ?>
                    <a class="btn btn-secondary lyrics-search-link"
                       href="<?php echo h($link['url']); ?>"
                       target="_blank"
                       rel="noopener noreferrer">
                        <i class="<?php echo h($link['icon']); ?>" aria-hidden="true"></i>
                        <?php echo h($link['label']); ?>에서 검색
                    </a>
                <?php endforeach; ?>
            </div>

            <div class="lyrics-helper-shortcuts">
                <a href="admin/metadata_quality.php?filter=missing_lyrics" class="btn btn-secondary btn-sm">
                    <i class="fas fa-list-check"></i> 가사 없는 곡 보기
                </a>
                <button type="button" class="btn btn-secondary btn-sm" id="lyrics-copy-query-btn">
                    <i class="fas fa-copy"></i> 검색어 복사
                </button>
            </div>
        </section>

        <section class="lyrics-editor-card">
            <!-- 가사 저장 폼 (PJAX 이동 후 AJAX 처리 / 비PJAX 시 일반 POST 폴백) -->
            <form action="lyrics_save.php" method="POST" id="lyrics-save-form" class="lyrics-editor-form">
                <input type="hidden" name="song_id" value="<?php echo h($song['id']); ?>">
                <?php echo csrfInput(); ?>

                <div class="lyrics-editor-heading">
                    <div>
                        <h2>가사 본문</h2>
                        <p>줄바꿈은 그대로 저장됩니다. HTML은 실행되지 않고 안전하게 표시됩니다.</p>
                    </div>
                    <span class="lyrics-editor-count" id="lyrics-char-count">0자</span>
                </div>

                <div class="lyrics-tool-actions" aria-label="가사 입력 도구">
                    <button type="button" class="btn btn-secondary" id="lyrics-paste-btn">
                        <i class="fas fa-clipboard"></i> 클립보드에서 붙여넣기
                    </button>
                    <button type="button" class="btn btn-secondary" id="lyrics-paste-clean-btn">
                        <i class="fas fa-wand-magic-sparkles"></i> 붙여넣고 정리
                    </button>
                    <button type="button" class="btn btn-secondary" id="lyrics-clean-btn">
                        <i class="fas fa-broom"></i> 가사 정리
                    </button>
                    <button type="button" class="btn btn-secondary" id="lyrics-preview-refresh-btn">
                        <i class="fas fa-eye"></i> 미리보기 갱신
                    </button>
                    <button type="button" class="btn btn-secondary" id="lyrics-reset-btn">
                        <i class="fas fa-rotate-left"></i> 초기화
                    </button>
                </div>

                <section class="lyrics-lrc-card" data-song-duration="<?php echo h($songDuration); ?>" aria-labelledby="lyrics-lrc-title">
                    <div class="lyrics-lrc-heading">
                        <div>
                            <span class="section-kicker">LRC 자동 생성</span>
                            <h3 id="lyrics-lrc-title">텍스트 가사를 싱크 가사 초안으로 변환</h3>
                            <p>일반 가사를 줄 단위로 나누고 곡 재생시간에 맞춰 LRC 시간 태그를 자동 배분합니다. 저장하면 전체화면 플레이어에서 실시간 가사로 표시됩니다.</p>
                        </div>
                        <span class="lyrics-lrc-mode" id="lyrics-lrc-mode">일반 가사</span>
                    </div>
                    <div class="lyrics-lrc-options">
                        <label>
                            <span>시작 시간</span>
                            <input type="number" id="lyrics-lrc-start" min="0" max="600" step="0.5" value="0">
                            <small>초</small>
                        </label>
                        <label>
                            <span>끝 여백</span>
                            <input type="number" id="lyrics-lrc-end-padding" min="0" max="60" step="0.5" value="4">
                            <small>초</small>
                        </label>
                    </div>
                    <div class="lyrics-lrc-actions" aria-label="LRC 도구">
                        <button type="button" class="btn btn-secondary" id="lyrics-lrc-generate-btn">
                            <i class="fas fa-clock"></i> LRC 초안 생성
                        </button>
                        <button type="button" class="btn btn-secondary" id="lyrics-lrc-stamp-btn">
                            <i class="fas fa-location-crosshairs"></i> 커서 줄 현재 시간 찍기
                        </button>
                        <button type="button" class="btn btn-secondary" id="lyrics-lrc-minus-btn">
                            <i class="fas fa-minus"></i> 전체 -0.5초
                        </button>
                        <button type="button" class="btn btn-secondary" id="lyrics-lrc-plus-btn">
                            <i class="fas fa-plus"></i> 전체 +0.5초
                        </button>
                        <button type="button" class="btn btn-secondary" id="lyrics-lrc-strip-btn">
                            <i class="fas fa-align-left"></i> 시간태그 제거
                        </button>
                    </div>
                    <p class="lyrics-lrc-status" id="lyrics-lrc-status" role="status" aria-live="polite">
                        LRC가 아닌 일반 가사는 기존처럼 줄바꿈 가사로 저장됩니다.
                    </p>
                </section>

                <div class="lyrics-workspace">
                    <div class="form-group lyrics-editor-field">
                        <label for="lyrics_text">가사 텍스트</label>
                        <textarea name="lyrics_text" id="lyrics_text" class="form-control lyrics-editor-textarea"
                                  data-original-lyrics="<?php echo h($currentLyrics); ?>"
                                  placeholder="여기에 가사를 한 줄씩 입력해 주세요."><?php echo h($currentLyrics); ?></textarea>
                        <p class="lyrics-helper-note" id="lyrics-helper-message" role="status" aria-live="polite">
                            클립보드 자동 붙여넣기가 실패하면 직접 Ctrl+V로 붙여넣은 뒤 “가사 정리”를 눌러 주세요.
                        </p>
                    </div>

                    <aside class="lyrics-preview-card" aria-labelledby="lyrics-preview-title">
                        <div class="lyrics-preview-head">
                            <div>
                                <h3 id="lyrics-preview-title">저장 전 미리보기</h3>
                                <p id="lyrics-preview-stats">0줄 · 0자</p>
                            </div>
                            <span class="lyrics-preview-pill">줄바꿈 유지</span>
                        </div>
                        <div class="lyrics-preview-body" id="lyrics-preview-body">등록된 가사가 없습니다.</div>
                    </aside>
                </div>

                <div class="actions-row lyrics-edit-actions">
                    <a href="song.php?id=<?php echo h($song['id']); ?>" class="btn btn-secondary">
                        <i class="fas fa-xmark"></i> 취소
                    </a>
                    <button type="submit" class="btn btn-primary" id="lyrics-save-btn">
                        <i class="fas fa-save"></i> 저장 완료
                    </button>
                </div>
            </form>
        </section>

        <!-- 가사가 이미 존재할 경우에만 삭제 폼(POST) 노출 -->
        <?php if ($currentLyrics !== ''): ?>
            <section class="lyrics-delete-card">
                <div>
                    <h2><i class="fas fa-trash-alt"></i> 가사 삭제</h2>
                    <p>이 곡에 저장된 가사 데이터를 완전히 삭제하고 초기화합니다.</p>
                </div>
                <form action="lyrics_delete.php" method="POST" id="lyrics-delete-form">
                    <input type="hidden" name="song_id" value="<?php echo h($song['id']); ?>">
                    <?php echo csrfInput(); ?>
                    <button type="submit" class="btn btn-danger" id="lyrics-delete-btn">
                        <i class="fas fa-trash"></i> 삭제 실행
                    </button>
                </form>
            </section>
        <?php endif; ?>
    </div>
</div>

<script>
/**
 * MelonLiteInitLyricsPage
 * PJAX 이동 후 app-navigation.js의 initPage()에서 자동 호출됨.
 * 가사 저장/삭제 폼을 AJAX 처리로 전환하여 재생 중단 방지.
 */
window.MelonLiteInitLyricsPage = function () {
    var saveForm = document.getElementById('lyrics-save-form');
    var deleteForm = document.getElementById('lyrics-delete-form');
    var toast = document.getElementById('lyrics-save-toast');
    var saveBtn = document.getElementById('lyrics-save-btn');
    var deleteBtn = document.getElementById('lyrics-delete-btn');
    var lyricsTextarea = document.getElementById('lyrics_text');
    var charCount = document.getElementById('lyrics-char-count');
    var previewBody = document.getElementById('lyrics-preview-body');
    var previewStats = document.getElementById('lyrics-preview-stats');
    var helperMessage = document.getElementById('lyrics-helper-message');
    var pasteBtn = document.getElementById('lyrics-paste-btn');
    var pasteCleanBtn = document.getElementById('lyrics-paste-clean-btn');
    var cleanBtn = document.getElementById('lyrics-clean-btn');
    var previewRefreshBtn = document.getElementById('lyrics-preview-refresh-btn');
    var resetBtn = document.getElementById('lyrics-reset-btn');
    var lrcCard = document.querySelector('.lyrics-lrc-card');
    var lrcMode = document.getElementById('lyrics-lrc-mode');
    var lrcStatus = document.getElementById('lyrics-lrc-status');
    var lrcStartInput = document.getElementById('lyrics-lrc-start');
    var lrcEndPaddingInput = document.getElementById('lyrics-lrc-end-padding');
    var lrcGenerateBtn = document.getElementById('lyrics-lrc-generate-btn');
    var lrcStampBtn = document.getElementById('lyrics-lrc-stamp-btn');
    var lrcMinusBtn = document.getElementById('lyrics-lrc-minus-btn');
    var lrcPlusBtn = document.getElementById('lyrics-lrc-plus-btn');
    var lrcStripBtn = document.getElementById('lyrics-lrc-strip-btn');
    var copyQueryBtn = document.getElementById('lyrics-copy-query-btn');
    var helperCard = document.querySelector('[data-lyrics-helper]');
    var songDuration = lrcCard ? Math.max(0, parseFloat(lrcCard.getAttribute('data-song-duration') || '0') || 0) : 0;

    function updateCounter() {
        if (!lyricsTextarea || !charCount) return;
        charCount.textContent = lyricsTextarea.value.length.toLocaleString('ko-KR') + '자';
    }

    function setHelperMessage(message, isError) {
        if (!helperMessage) return;
        helperMessage.textContent = message || '';
        helperMessage.classList.toggle('is-error', Boolean(isError));
    }

    function normalizeLyricsText(text) {
        text = String(text || '');
        text = text.replace(/\r\n?/g, '\n');
        text = text.replace(/[\u00a0\u1680\u180e\u2000-\u200b\u202f\u205f\u3000]/g, ' ');
        text = text.replace(/\t/g, ' ');
        text = text.replace(/<script[\s\S]*?<\/script>/gi, '');
        text = text.replace(/<style[\s\S]*?<\/style>/gi, '');
        text = text.replace(/<[^>]+>/g, '');
        text = text.split('\n').map(function (line) {
            return line.replace(/[ \t]+$/g, '').replace(/[ ]{3,}/g, '  ');
        }).join('\n');
        text = text.replace(/\n{3,}/g, '\n\n');
        return text.trim();
    }

    function lyricsStats(text) {
        text = String(text || '');
        var lines = text === '' ? 0 : text.split('\n').length;
        return lines.toLocaleString('ko-KR') + '줄 · ' + text.length.toLocaleString('ko-KR') + '자';
    }

    function isLrcText(text) {
        return /\[\d{1,2}:\d{2}(?:[.:]\d{1,3})?\]/.test(String(text || ''));
    }

    function parseLrcTime(minutes, seconds, fraction) {
        var min = parseInt(minutes || '0', 10);
        var sec = parseInt(seconds || '0', 10);
        var msText = String(fraction || '0');
        var ms = parseInt((msText + '000').slice(0, 3), 10);
        var total = (Math.max(0, min) * 60) + Math.max(0, sec) + (Math.max(0, ms) / 1000);
        return Number.isFinite(total) ? total : 0;
    }

    function formatLrcTime(totalSeconds) {
        var total = Math.max(0, Number(totalSeconds) || 0);
        var minutes = Math.floor(total / 60);
        var seconds = Math.floor(total % 60);
        var hundredths = Math.floor((total - Math.floor(total)) * 100);
        return '[' +
            String(minutes).padStart(2, '0') + ':' +
            String(seconds).padStart(2, '0') + '.' +
            String(hundredths).padStart(2, '0') +
        ']';
    }

    function stripLrcTags(text) {
        return String(text || '')
            .replace(/\[(?:ti|ar|al|by|offset|length):[^\]]*\]\s*/gi, '')
            .split(/\r?\n/)
            .map(function (line) {
                return line.replace(/\[\d{1,2}:\d{2}(?:[.:]\d{1,3})?\]/g, '').trim();
            })
            .filter(function (line) { return line !== ''; })
            .join('\n');
    }

    function parseLrcLines(text) {
        var rows = [];
        String(text || '').split(/\r?\n/).forEach(function (rawLine) {
            var matches = Array.from(rawLine.matchAll(/\[(\d{1,2}):(\d{2})(?:[.:](\d{1,3}))?\]/g));
            if (!matches.length) return;
            var body = rawLine.replace(/\[[^\]]+\]/g, '').trim();
            matches.forEach(function (match) {
                rows.push({
                    time: parseLrcTime(match[1], match[2], match[3]),
                    text: body
                });
            });
        });
        rows.sort(function (a, b) { return a.time - b.time; });
        return rows;
    }

    function renderLrcPreview(text) {
        if (!previewBody) return false;
        var rows = parseLrcLines(text);
        if (!rows.length) return false;
        previewBody.textContent = '';
        previewBody.classList.remove('is-empty');
        previewBody.classList.add('is-lrc-preview');
        rows.slice(0, 120).forEach(function (row) {
            var line = document.createElement('div');
            line.className = 'lyrics-lrc-preview-line';
            var time = document.createElement('span');
            time.textContent = formatLrcTime(row.time).replace('[', '').replace(']', '');
            var body = document.createElement('strong');
            body.textContent = row.text || '...';
            line.append(time, body);
            previewBody.appendChild(line);
        });
        if (rows.length > 120) {
            var more = document.createElement('p');
            more.className = 'lyrics-lrc-preview-more';
            more.textContent = '외 ' + (rows.length - 120).toLocaleString('ko-KR') + '줄';
            previewBody.appendChild(more);
        }
        return true;
    }

    function setLrcStatus(message, isError) {
        if (!lrcStatus) return;
        lrcStatus.textContent = message || '';
        lrcStatus.classList.toggle('is-error', Boolean(isError));
    }

    function updateLrcMode(text) {
        if (!lrcMode) return;
        var synced = isLrcText(text);
        lrcMode.textContent = synced ? 'LRC 싱크 가사' : '일반 가사';
        lrcMode.classList.toggle('is-lrc', synced);
    }

    function plainLyricLinesFromTextarea() {
        var text = lyricsTextarea ? lyricsTextarea.value || '' : '';
        if (isLrcText(text)) text = stripLrcTags(text);
        return normalizeLyricsText(text)
            .split('\n')
            .map(function (line) { return line.trim(); })
            .filter(function (line) { return line !== ''; });
    }

    function generateLrcDraft() {
        if (!lyricsTextarea) return;
        var lines = plainLyricLinesFromTextarea();
        if (!lines.length) {
            setLrcStatus('LRC로 변환할 가사 줄이 없습니다.', true);
            lyricsTextarea.focus();
            return;
        }
        var start = Math.max(0, parseFloat(lrcStartInput && lrcStartInput.value ? lrcStartInput.value : '0') || 0);
        var endPadding = Math.max(0, parseFloat(lrcEndPaddingInput && lrcEndPaddingInput.value ? lrcEndPaddingInput.value : '4') || 0);
        var duration = songDuration > 0 ? songDuration : Math.max(lines.length * 4, start + endPadding + lines.length * 3);
        var usable = Math.max(lines.length, duration - start - endPadding);
        var interval = lines.length > 1 ? usable / (lines.length - 1) : 0;
        var lrc = lines.map(function (line, index) {
            return formatLrcTime(start + (interval * index)) + line;
        }).join('\n');
        lyricsTextarea.value = lrc;
        updatePreview();
        lyricsTextarea.focus();
        setLrcStatus('LRC 초안을 생성했습니다. 필요하면 현재 시간 찍기 또는 ±0.5초로 보정한 뒤 저장하세요.');
    }

    function shiftLrcTimes(delta) {
        if (!lyricsTextarea) return;
        var text = lyricsTextarea.value || '';
        if (!isLrcText(text)) {
            setLrcStatus('먼저 LRC 초안을 생성해 주세요.', true);
            return;
        }
        lyricsTextarea.value = text.replace(/\[(\d{1,2}):(\d{2})(?:[.:](\d{1,3}))?\]/g, function (_, min, sec, frac) {
            return formatLrcTime(parseLrcTime(min, sec, frac) + delta);
        });
        updatePreview();
        setLrcStatus(delta < 0 ? '전체 시간 태그를 0.5초 앞당겼습니다.' : '전체 시간 태그를 0.5초 늦췄습니다.');
    }

    function getTextareaCurrentLineRange() {
        if (!lyricsTextarea) return null;
        var value = lyricsTextarea.value || '';
        var pos = lyricsTextarea.selectionStart || 0;
        var start = value.lastIndexOf('\n', Math.max(0, pos - 1)) + 1;
        var end = value.indexOf('\n', pos);
        if (end === -1) end = value.length;
        return { start: start, end: end, text: value.slice(start, end), value: value };
    }

    function stampCurrentLineWithPlayerTime() {
        if (!lyricsTextarea) return;
        var audio = document.getElementById('audio-player');
        if (!audio || !Number.isFinite(audio.currentTime)) {
            setLrcStatus('현재 재생 위치를 읽을 수 없습니다. 곡을 재생한 뒤 다시 시도해 주세요.', true);
            return;
        }
        var range = getTextareaCurrentLineRange();
        if (!range) return;
        var body = range.text.replace(/\[\d{1,2}:\d{2}(?:[.:]\d{1,3})?\]/g, '').trim();
        if (!body) {
            setLrcStatus('시간을 찍을 가사 줄에 커서를 놓아 주세요.', true);
            return;
        }
        var nextLine = formatLrcTime(audio.currentTime) + body;
        lyricsTextarea.value = range.value.slice(0, range.start) + nextLine + range.value.slice(range.end);
        lyricsTextarea.setSelectionRange(range.start, range.start + nextLine.length);
        updatePreview();
        lyricsTextarea.focus();
        setLrcStatus('커서가 있는 줄에 현재 재생 위치를 적용했습니다.');
    }

    function stripLrcFromTextarea() {
        if (!lyricsTextarea) return;
        if (!isLrcText(lyricsTextarea.value || '')) {
            setLrcStatus('제거할 시간 태그가 없습니다.');
            return;
        }
        lyricsTextarea.value = stripLrcTags(lyricsTextarea.value);
        updatePreview();
        setLrcStatus('LRC 시간 태그를 제거하고 일반 가사로 되돌렸습니다.');
    }

    function updatePreview() {
        if (!lyricsTextarea) return;
        var value = lyricsTextarea.value || '';
        updateCounter();
        if (previewStats) previewStats.textContent = lyricsStats(value);
        updateLrcMode(value);
        if (!previewBody) return;
        previewBody.classList.remove('is-lrc-preview');
        if (value.trim() === '') {
            previewBody.textContent = '등록된 가사가 없습니다.';
            previewBody.classList.add('is-empty');
        } else if (renderLrcPreview(value)) {
            previewBody.classList.remove('is-empty');
        } else {
            previewBody.textContent = value;
            previewBody.classList.remove('is-empty');
        }
    }

    function cleanTextarea() {
        if (!lyricsTextarea) return;
        var before = lyricsTextarea.value || '';
        var after = normalizeLyricsText(before);
        lyricsTextarea.value = after;
        updatePreview();
        setHelperMessage('가사를 정리했습니다. 저장 전 미리보기를 확인해 주세요.');
    }

    function insertClipboardText(shouldClean) {
        if (!lyricsTextarea) return;
        if (!navigator.clipboard || typeof navigator.clipboard.readText !== 'function') {
            setHelperMessage('이 브라우저에서는 자동 붙여넣기를 사용할 수 없습니다. 직접 Ctrl+V로 붙여넣어 주세요.', true);
            lyricsTextarea.focus();
            return;
        }
        navigator.clipboard.readText()
            .then(function (text) {
                if (!text || !String(text).trim()) {
                    setHelperMessage('클립보드에 붙여넣을 텍스트가 없습니다.', true);
                    lyricsTextarea.focus();
                    return;
                }
                lyricsTextarea.value = shouldClean ? normalizeLyricsText(text) : String(text).replace(/\r\n?/g, '\n');
                updatePreview();
                lyricsTextarea.focus();
                setHelperMessage(shouldClean ? '클립보드 내용을 붙여넣고 정리했습니다.' : '클립보드 내용을 붙여넣었습니다.');
            })
            .catch(function () {
                setHelperMessage('브라우저 권한 문제로 자동 붙여넣기를 사용할 수 없습니다. 직접 Ctrl+V로 붙여넣어 주세요.', true);
                lyricsTextarea.focus();
            });
    }

    function copySearchQuery() {
        var query = helperCard ? helperCard.getAttribute('data-search-query') : '';
        if (!query) return;
        if (navigator.clipboard && typeof navigator.clipboard.writeText === 'function') {
            navigator.clipboard.writeText(query)
                .then(function () { setHelperMessage('검색어를 복사했습니다.'); })
                .catch(function () { setHelperMessage('검색어 복사에 실패했습니다. 직접 선택해서 복사해 주세요.', true); });
        } else {
            setHelperMessage('이 브라우저에서는 검색어 자동 복사를 사용할 수 없습니다.', true);
        }
    }

    function showToast(msg, isError) {
        if (!toast) return;
        toast.textContent = msg;
        toast.classList.toggle('is-error', Boolean(isError));
        toast.style.display = 'block';
        clearTimeout(toast._hideTimer);
        toast._hideTimer = setTimeout(function () { toast.style.display = 'none'; }, 3000);
    }

    function navigatePjax(url) {
        if (window.MelonLiteNavigate) {
            try {
                window.MelonLiteNavigate(new URL(url, window.location.href), { push: true });
                return true;
            } catch (e) {}
        }
        return false;
    }

    function submitFormAjax(form, btn, confirmMsg) {
        if (!form) return;
        // 중복 바인딩 방지
        if (form.__lyricsAjaxBound) return;
        form.__lyricsAjaxBound = true;

        form.addEventListener('submit', function (e) {
            if (confirmMsg && !window.confirm(confirmMsg)) {
                e.preventDefault();
                return;
            }
            e.preventDefault();

            var formData = new FormData(form);
            // CSRF 토큰 자동 포함 (layout.php에서 이미 hidden input으로 삽입됨)
            // 혹시 없으면 window.APP_CSRF_TOKEN에서 보충
            if (!formData.get('csrf_token') && window.APP_CSRF_TOKEN) {
                formData.append('csrf_token', window.APP_CSRF_TOKEN);
            }

            if (btn) {
                btn.disabled = true;
                btn.setAttribute('data-original-text', btn.innerHTML);
                btn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> 처리 중...';
            }

            fetch(form.action, {
                method: 'POST',
                headers: {
                    'X-Requested-With': 'XMLHttpRequest',
                    'Accept': 'application/json'
                },
                credentials: 'same-origin',
                body: formData
            })
            .then(function (res) { return res.json(); })
            .then(function (data) {
                if (btn) {
                    btn.disabled = false;
                    var orig = btn.getAttribute('data-original-text');
                    if (orig) btn.innerHTML = orig;
                }
                if (data.success) {
                    var updatedSongId = parseInt(data.song_id || (data.data && data.data.song_id) || formData.get('song_id') || 0, 10);
                    var updatedLyrics = data.lyrics || (data.data && data.data.lyrics) || '';
                    window.dispatchEvent(new CustomEvent('melonlite:lyrics-updated', {
                        detail: {
                            song_id: updatedSongId,
                            lyrics: updatedLyrics,
                            has_lyrics: Boolean(data.has_lyrics || (data.data && data.data.has_lyrics)),
                            updated_at: data.updated_at || (data.data && data.data.updated_at) || ''
                        }
                    }));
                    if (window.AppPlayer && typeof window.AppPlayer.refreshLyrics === 'function') {
                        window.AppPlayer.refreshLyrics(updatedSongId, true);
                    }
                    showToast(data.message || '완료되었습니다.');
                    // 성공 후 PJAX로 song.php 이동 (재생 유지)
                    var redirectUrl = data.redirect || ('song.php?id=' + (formData.get('song_id') || ''));
                    setTimeout(function () {
                        if (!navigatePjax(redirectUrl)) {
                            window.location.href = redirectUrl;
                        }
                    }, 600);
                } else {
                    showToast(data.message || '오류가 발생했습니다.', true);
                }
            })
            .catch(function (err) {
                if (btn) {
                    btn.disabled = false;
                    var orig = btn.getAttribute('data-original-text');
                    if (orig) btn.innerHTML = orig;
                }
                console.error('Lyrics form submit error:', err);
                showToast('요청 처리 중 오류가 발생했습니다.', true);
            });
        });
    }

    if (lyricsTextarea && !lyricsTextarea.__lyricsCounterBound) {
        lyricsTextarea.__lyricsCounterBound = true;
        lyricsTextarea.addEventListener('input', updateCounter);
        lyricsTextarea.addEventListener('input', function () {
            clearTimeout(lyricsTextarea.__lyricsPreviewTimer);
            lyricsTextarea.__lyricsPreviewTimer = setTimeout(updatePreview, 160);
        });
        lyricsTextarea.addEventListener('paste', function () {
            clearTimeout(lyricsTextarea.__lyricsPreviewTimer);
            lyricsTextarea.__lyricsPreviewTimer = setTimeout(updatePreview, 80);
        });
        updateCounter();
        updatePreview();
    }

    if (pasteBtn && pasteBtn.dataset.bound !== '1') {
        pasteBtn.dataset.bound = '1';
        pasteBtn.addEventListener('click', function () { insertClipboardText(false); });
    }
    if (pasteCleanBtn && pasteCleanBtn.dataset.bound !== '1') {
        pasteCleanBtn.dataset.bound = '1';
        pasteCleanBtn.addEventListener('click', function () { insertClipboardText(true); });
    }
    if (cleanBtn && cleanBtn.dataset.bound !== '1') {
        cleanBtn.dataset.bound = '1';
        cleanBtn.addEventListener('click', cleanTextarea);
    }
    if (previewRefreshBtn && previewRefreshBtn.dataset.bound !== '1') {
        previewRefreshBtn.dataset.bound = '1';
        previewRefreshBtn.addEventListener('click', updatePreview);
    }
    if (resetBtn && resetBtn.dataset.bound !== '1') {
        resetBtn.dataset.bound = '1';
        resetBtn.addEventListener('click', function () {
            if (!lyricsTextarea) return;
            lyricsTextarea.value = lyricsTextarea.getAttribute('data-original-lyrics') || '';
            updatePreview();
            setHelperMessage('처음 불러온 가사로 되돌렸습니다.');
        });
    }
    if (lrcGenerateBtn && lrcGenerateBtn.dataset.bound !== '1') {
        lrcGenerateBtn.dataset.bound = '1';
        lrcGenerateBtn.addEventListener('click', generateLrcDraft);
    }
    if (lrcStampBtn && lrcStampBtn.dataset.bound !== '1') {
        lrcStampBtn.dataset.bound = '1';
        lrcStampBtn.addEventListener('click', stampCurrentLineWithPlayerTime);
    }
    if (lrcMinusBtn && lrcMinusBtn.dataset.bound !== '1') {
        lrcMinusBtn.dataset.bound = '1';
        lrcMinusBtn.addEventListener('click', function () { shiftLrcTimes(-0.5); });
    }
    if (lrcPlusBtn && lrcPlusBtn.dataset.bound !== '1') {
        lrcPlusBtn.dataset.bound = '1';
        lrcPlusBtn.addEventListener('click', function () { shiftLrcTimes(0.5); });
    }
    if (lrcStripBtn && lrcStripBtn.dataset.bound !== '1') {
        lrcStripBtn.dataset.bound = '1';
        lrcStripBtn.addEventListener('click', stripLrcFromTextarea);
    }
    if (copyQueryBtn && copyQueryBtn.dataset.bound !== '1') {
        copyQueryBtn.dataset.bound = '1';
        copyQueryBtn.addEventListener('click', copySearchQuery);
    }

    submitFormAjax(saveForm, saveBtn, null);
    submitFormAjax(deleteForm, deleteBtn, '정말로 이 곡의 가사를 삭제하시겠습니까?');
};

// DOMContentLoaded (일반 전체 로드) 또는 PJAX 이동 즉시 초기화
(function () {
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', window.MelonLiteInitLyricsPage);
    } else {
        window.MelonLiteInitLyricsPage();
    }
})();
</script>

<?php
renderFooter();
?>
