<?php
declare(strict_types=1);
session_start();
if (!isset($_SESSION['student_id'])) {
    header('Location: student-login.php');
    exit;
}

$studentId=(int)$_SESSION['student_id'];
$name=(string)($_SESSION['student_name']??'Học sinh');

require_once __DIR__.'/../config/database.php';
$pdo=getDbConnection();

$avatarSource='default';
$customAvatarPath='';
$message='';
$error='';

try {
    $stmt=$pdo->prepare("SELECT full_name, avatar_source, custom_avatar_path FROM students WHERE id=? LIMIT 1");
    $stmt->execute([$studentId]);
    $row=$stmt->fetch(PDO::FETCH_ASSOC) ?: [];
    if (!empty($row['full_name'])) $name=(string)$row['full_name'];
    $avatarSource=(string)($row['avatar_source']??'default');
    $customAvatarPath=(string)($row['custom_avatar_path']??'');
} catch (Throwable $e) {
    $error='Chưa đọc được avatar hiện tại.';
}

if (empty($_SESSION['avatar_csrf'])) {
    $_SESSION['avatar_csrf']=bin2hex(random_bytes(32));
}


// Thư viện avatar có sẵn: tự quét folder assets/avatars/presets/.
$presetDir=__DIR__.'/../assets/avatars/presets';
$presetFiles=[];
if (is_dir($presetDir)) {
    foreach (scandir($presetDir) ?: [] as $fileName) {
        if ($fileName==='.' || $fileName==='..') continue;
        if (!preg_match('/\.(png|jpe?g|webp)$/i',$fileName)) continue;
        if (!is_file($presetDir.'/'.$fileName)) continue;
        $presetFiles[]=$fileName;
    }
    natcasesort($presetFiles);
    $presetFiles=array_values($presetFiles);
}


if ($_SERVER['REQUEST_METHOD']==='POST' && ($_POST['action']??'')==='save_preset_avatar') {
    $token=(string)($_POST['csrf_token']??'');
    $presetFile=basename((string)($_POST['preset_file']??''));

    if (!hash_equals((string)$_SESSION['avatar_csrf'],$token)) {
        $error='Phiên làm việc đã thay đổi. Em tải lại trang rồi thử lại.';
    } elseif ($presetFile==='' || !in_array($presetFile,$presetFiles,true)) {
        $error='Avatar đã chọn không hợp lệ.';
    } else {
        $presetPath='assets/avatars/presets/'.$presetFile;
        try {
            $oldPath=$customAvatarPath;
            $up=$pdo->prepare("UPDATE students SET avatar_source='preset', custom_avatar_path=? WHERE id=?");
            $up->execute([$presetPath,$studentId]);

            // Nếu trước đó là ảnh học sinh tải lên, xóa file cũ sau khi lưu preset thành công.
            if ($avatarSource==='upload' && $oldPath!=='' && str_starts_with($oldPath,'uploads/student-avatars/')) {
                $oldFile=__DIR__.'/../'.$oldPath;
                if (is_file($oldFile)) @unlink($oldFile);
            }

            header('Location: student-avatar.php?saved=1');
            exit;
        } catch (Throwable $e) {
            $error='Chưa lưu được avatar đã chọn.';
        }
    }
}


if ($_SERVER['REQUEST_METHOD']==='POST' && ($_POST['action']??'')==='save_builder_avatar') {
    $token=(string)($_POST['csrf_token']??'');
    $baseId=(string)($_POST['builder_base']??'');
    $hairId=(string)($_POST['builder_hair']??'');

    if (!hash_equals((string)$_SESSION['avatar_csrf'],$token)) {
        $error='Phiên làm việc đã thay đổi. Em tải lại trang rồi thử lại.';
    } else {
        $builderDir=__DIR__.'/../assets/avatars/builder';
        $manifestFile=$builderDir.'/manifest.json';
        $manifest=is_file($manifestFile) ? json_decode((string)file_get_contents($manifestFile),true) : null;
        $bases=is_array($manifest) ? ($manifest['categories']['base']['items']??[]) : [];
        $hairs=is_array($manifest) ? ($manifest['categories']['hair']['items']??[]) : [];

        $baseItem=null; $hairItem=null;
        foreach ($bases as $item) if (($item['id']??'')===$baseId) { $baseItem=$item; break; }
        foreach ($hairs as $item) if (($item['id']??'')===$hairId) { $hairItem=$item; break; }

        if (!$baseItem || !$hairItem) {
            $error='Nhân vật đã chọn không hợp lệ.';
        } else {
            $safeImage=function(string $path) {
                if (!is_file($path)) return null;
                $info=@getimagesize($path);
                $mime=(string)($info['mime']??'');
                if ($mime==='image/png') return @imagecreatefrompng($path);
                if ($mime==='image/jpeg') return @imagecreatefromjpeg($path);
                if ($mime==='image/webp' && function_exists('imagecreatefromwebp')) return @imagecreatefromwebp($path);
                return null;
            };

            $basePath=$builderDir.'/base/'.basename((string)$baseItem['file']);
            $hairPath=$builderDir.'/hair/'.basename((string)$hairItem['file']);
            $baseImg=$safeImage($basePath);
            $hairImg=$safeImage($hairPath);

            if (!$baseImg || !$hairImg) {
                if ($baseImg) imagedestroy($baseImg);
                if ($hairImg) imagedestroy($hairImg);
                $error='Chưa tạo được nhân vật. Em thử lại nhé.';
            } else {
                $size=320;
                $canvas=imagecreatetruecolor($size,$size);
                $white=imagecolorallocate($canvas,255,255,255);
                imagefill($canvas,0,0,$white);

                imagealphablending($canvas,true);
                $bw=imagesx($baseImg); $bh=imagesy($baseImg);
                imagecopyresampled($canvas,$baseImg,0,0,0,0,$size,$size,$bw,$bh);

                $fit=is_array($hairItem['fit']??null) ? $hairItem['fit'] : [];
                $scale=(float)($fit['scale']??0.84);
                $offsetX=(float)($fit['offset_x']??0);
                $offsetY=(float)($fit['offset_y']??-14);

                // Các thông số fit được căn trên khung 360px của Teacher Builder.
                $ratio=$size/360;
                $drawW=(int)round($size*$scale);
                $drawH=(int)round($size*$scale);
                $drawX=(int)round(($size-$drawW)/2 + $offsetX*$ratio);
                $drawY=(int)round(($size-$drawH)/2 + $offsetY*$ratio);

                $hw=imagesx($hairImg); $hh=imagesy($hairImg);
                imagecopyresampled($canvas,$hairImg,$drawX,$drawY,0,0,$drawW,$drawH,$hw,$hh);

                $uploadDir=__DIR__.'/../uploads/student-avatars';
                if (!is_dir($uploadDir) && !mkdir($uploadDir,0755,true) && !is_dir($uploadDir)) {
                    $error='Chưa tạo được thư mục lưu avatar.';
                } else {
                    $filename='student_'.$studentId.'_builder_'.bin2hex(random_bytes(8)).'.jpg';
                    $target=$uploadDir.'/'.$filename;
                    $relativePath='uploads/student-avatars/'.$filename;
                    $saved=imagejpeg($canvas,$target,82);

                    if (!$saved) {
                        @unlink($target);
                        $error='Chưa lưu được nhân vật.';
                    } else {
                        try {
                            $oldPath=$customAvatarPath;
                            $up=$pdo->prepare("UPDATE students SET avatar_source='upload', custom_avatar_path=? WHERE id=?");
                            $up->execute([$relativePath,$studentId]);

                            if ($oldPath!=='' && str_starts_with($oldPath,'uploads/student-avatars/')) {
                                $oldFile=__DIR__.'/../'.$oldPath;
                                if (is_file($oldFile)) @unlink($oldFile);
                            }

                            imagedestroy($canvas);
                            imagedestroy($baseImg);
                            imagedestroy($hairImg);
                            header('Location: student-avatar.php?saved=1');
                            exit;
                        } catch (Throwable $e) {
                            @unlink($target);
                            $error='Chưa lưu được nhân vật.';
                        }
                    }
                }

                if (is_resource($canvas) || $canvas instanceof GdImage) @imagedestroy($canvas);
                if (is_resource($baseImg) || $baseImg instanceof GdImage) @imagedestroy($baseImg);
                if (is_resource($hairImg) || $hairImg instanceof GdImage) @imagedestroy($hairImg);
            }
        }
    }
}

if ($_SERVER['REQUEST_METHOD']==='POST' && ($_POST['action']??'')==='upload_avatar') {
    $token=(string)($_POST['csrf_token']??'');
    if (!hash_equals((string)$_SESSION['avatar_csrf'],$token)) {
        $error='Phiên làm việc đã thay đổi. Em tải lại trang rồi thử lại.';
    } elseif (!isset($_FILES['avatar_file']) || !is_array($_FILES['avatar_file'])) {
        $error='Em hãy chọn một ảnh.';
    } else {
        $file=$_FILES['avatar_file'];
        $uploadError=(int)($file['error']??UPLOAD_ERR_NO_FILE);
        if ($uploadError!==UPLOAD_ERR_OK) {
            $error='Chưa tải được ảnh. Em thử lại nhé.';
        } elseif ((int)($file['size']??0)>3*1024*1024) {
            $error='Ảnh gốc tối đa 3 MB.';
        } else {
            $tmp=(string)($file['tmp_name']??'');
            $finfo=new finfo(FILEINFO_MIME_TYPE);
            $mime=$tmp!=='' ? (string)$finfo->file($tmp) : '';
            if (!in_array($mime,['image/jpeg','image/png','image/webp'],true) || @getimagesize($tmp)===false) {
                $error='Chỉ nhận ảnh JPG, PNG hoặc WEBP.';
            } else {
                $sourceImage=null;
                if ($mime==='image/jpeg') $sourceImage=@imagecreatefromjpeg($tmp);
                elseif ($mime==='image/png') $sourceImage=@imagecreatefrompng($tmp);
                elseif ($mime==='image/webp' && function_exists('imagecreatefromwebp')) $sourceImage=@imagecreatefromwebp($tmp);

                if (!$sourceImage) {
                    $error='Không xử lý được ảnh này. Em thử ảnh JPG hoặc PNG nhé.';
                } else {
                    $uploadDir=__DIR__.'/../uploads/student-avatars';
                    if (!is_dir($uploadDir) && !mkdir($uploadDir,0755,true) && !is_dir($uploadDir)) {
                        $error='Chưa tạo được thư mục lưu avatar.';
                    } else {
                        $srcW=imagesx($sourceImage); $srcH=imagesy($sourceImage);
                        $side=min($srcW,$srcH); $srcX=(int)(($srcW-$side)/2); $srcY=(int)(($srcH-$side)/2);
                        $size=320;
                        $avatarImage=imagecreatetruecolor($size,$size);
                        imagecopyresampled($avatarImage,$sourceImage,0,0,$srcX,$srcY,$size,$size,$side,$side);
                        $filename='student_'.$studentId.'_'.bin2hex(random_bytes(8)).'.jpg';
                        $target=$uploadDir.'/'.$filename;
                        $relativePath='uploads/student-avatars/'.$filename;
                        $quality=74; $saved=imagejpeg($avatarImage,$target,$quality);
                        clearstatcache(true,$target);
                        while ($saved && is_file($target) && filesize($target)>150*1024 && $quality>42) {
                            $quality-=6; $saved=imagejpeg($avatarImage,$target,$quality); clearstatcache(true,$target);
                        }
                        imagedestroy($avatarImage); imagedestroy($sourceImage);
                        if (!$saved || !is_file($target) || filesize($target)>150*1024) {
                            @unlink($target); $error='Ảnh chưa nén được đủ nhỏ. Em thử ảnh khác nhé.';
                        } else {
                            try {
                                $oldPath=$customAvatarPath;
                                $up=$pdo->prepare("UPDATE students SET avatar_source='upload', custom_avatar_path=? WHERE id=?");
                                $up->execute([$relativePath,$studentId]);
                                if ($oldPath!=='' && str_starts_with($oldPath,'uploads/student-avatars/')) {
                                    $oldFile=__DIR__.'/../'.$oldPath;
                                    if (is_file($oldFile)) @unlink($oldFile);
                                }
                                header('Location: student-avatar.php?saved=1'); exit;
                            } catch (Throwable $e) {
                                @unlink($target); $error='Chưa lưu được avatar.';
                            }
                        }
                    }
                }
            }
        }
    }
}
if (isset($_GET['saved'])) $message='Đã đổi avatar.';

$avatarUrl='';
if ($avatarSource==='upload' && $customAvatarPath!=='' && str_starts_with($customAvatarPath,'uploads/student-avatars/')) {
    $avatarUrl='../'.ltrim($customAvatarPath,'/');
} elseif ($avatarSource==='preset' && $customAvatarPath!=='' && str_starts_with($customAvatarPath,'assets/avatars/presets/')) {
    $avatarUrl='../'.ltrim($customAvatarPath,'/');
}

$pageTitle=''; $pageSubtitle=''; $activeStudentNav='profile';
include __DIR__.'/../includes/student-layout-start.php';
?>
<style>
.student-header{display:none!important}
.student-content{padding:10px 14px calc(100px + env(safe-area-inset-bottom))!important}
.avatar-page{max-width:520px;margin:0 auto;color:#0b4f9c}
.avatar-top{display:flex;align-items:center;justify-content:space-between;margin-bottom:14px}
.avatar-back{width:44px;height:44px;display:grid;place-items:center;border:1px solid #cfe4f5;border-radius:14px;background:#fff;color:#0b4f9c;text-decoration:none;font-size:25px;font-weight:900}
.avatar-title{margin:0;font-size:22px;font-weight:900;letter-spacing:.01em}
.avatar-spacer{width:44px}
.avatar-preview{display:flex;flex-direction:column;align-items:center;padding:20px 16px 18px;border:1px solid #cfe4f5;border-radius:20px;background:#eef7ff;box-shadow:0 6px 14px rgba(29,80,116,.05)}
.avatar-circle{width:118px;height:118px;display:grid;place-items:center;border:5px solid #fff;border-radius:50%;background:#fff;box-shadow:0 5px 16px rgba(29,80,116,.12);overflow:hidden;font-size:58px}
.avatar-circle img{width:100%;height:100%;object-fit:cover}
.avatar-name{margin-top:10px;font-size:18px;font-weight:900;color:#315d82}
.avatar-actions{display:grid;gap:12px;margin-top:14px}
.avatar-option{display:grid;grid-template-columns:52px minmax(0,1fr) 24px;align-items:center;gap:12px;min-height:78px;padding:12px 14px;border:1px solid #d4e3ee;border-radius:18px;background:#fff;color:#0b4f9c;text-decoration:none;box-shadow:0 5px 16px rgba(29,80,116,.06);cursor:pointer;text-align:left;width:100%}
.avatar-option__icon{width:48px;height:48px;display:grid;place-items:center;border-radius:14px;background:#eef7ff;font-size:26px}
.avatar-option__title{display:block;font-size:17px;font-weight:900}
.avatar-option__text{display:block;margin-top:3px;color:#315d82;font-size:13.5px;font-weight:700;line-height:1.3}
.avatar-option__arrow{font-size:25px;font-weight:900;text-align:right}
.avatar-note{margin:12px 2px 0;padding:10px 12px;border-radius:12px;background:#fff8e8;color:#7a5b13;font-size:13px;font-weight:700}
.avatar-message{margin-bottom:10px;padding:10px 12px;border-radius:12px;background:#eefaf4;color:#137a48;font-weight:800}
.avatar-error{margin-bottom:10px;padding:10px 12px;border-radius:12px;background:#fff2f0;color:#b42318;font-weight:800}
.student-nav__item{color:#315d82!important}.student-nav__item.is-active{color:#0b4f9c!important}.student-nav__item.is-active .student-nav__icon{background:#eef7ff!important}.student-nav__label{font-size:12.5px!important;font-weight:850!important}

/* Builder thử nghiệm: Base + Hair */
.builder-panel{display:none;margin-top:14px;padding:14px;border:1px solid #cfe4f5;border-radius:20px;background:#fff;box-shadow:0 5px 16px rgba(29,80,116,.06)}
.builder-panel.is-open{display:block}
.builder-title{margin:0 0 10px;font-size:18px;font-weight:900;color:#0b4f9c}
.builder-stage{position:relative;width:220px;height:220px;margin:0 auto 14px;border-radius:22px;background:#eef7ff;overflow:hidden;border:1px solid #cfe4f5}
.builder-layer{position:absolute;inset:0;width:100%;height:100%;object-fit:contain}
#builderHair{transform-origin:center center;transition:transform .16s ease}
.builder-section{margin-top:12px}
.builder-section__title{margin:0 0 8px;font-size:14px;font-weight:900;color:#315d82}
.builder-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:8px}
.builder-choice{padding:7px 4px;border:1px solid #d4e3ee;border-radius:12px;background:#fff;color:#315d82;font-size:11px;font-weight:800;cursor:pointer}
.builder-choice.is-selected{border:2px solid #0b4f9c;background:#eef7ff;color:#0b4f9c}
.builder-thumb{display:block;width:100%;aspect-ratio:1/1;object-fit:contain;margin-bottom:4px;border-radius:8px;background:#f7fbff}
.builder-help{margin:10px 0 0;text-align:center;color:#5d7891;font-size:12px;font-weight:700}
.builder-workspace{display:grid;grid-template-columns:minmax(0,1fr) 132px;gap:12px;align-items:start}
.builder-preview-side{position:sticky;top:12px}
.builder-preview-side .builder-stage{width:100%;height:auto;aspect-ratio:1/1;margin:0 0 10px}
.builder-actions{display:flex;justify-content:center;margin-top:0}
.builder-save{width:100%;min-height:46px;border:0;border-radius:13px;background:#0b4f9c;color:#fff;font-size:14px;font-weight:900;cursor:pointer}.builder-save:disabled{opacity:.45;cursor:not-allowed}
.builder-options-side{min-width:0}
@media(max-width:390px){.builder-workspace{grid-template-columns:minmax(0,1fr) 112px;gap:8px}.builder-save{font-size:12.5px;padding:0 6px}}
@media(max-width:390px){.builder-stage{width:205px;height:205px}.builder-grid{grid-template-columns:repeat(3,minmax(0,1fr))}}

.preset-panel{display:none;margin-top:14px;padding:14px;border:1px solid #cfe4f5;border-radius:20px;background:#fff;box-shadow:0 5px 16px rgba(29,80,116,.06)}
.preset-panel.is-open{display:block}
.preset-title{margin:0 0 10px;color:#0b4f9c;font-size:18px;font-weight:900}
.preset-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:10px}
.preset-choice{position:relative;padding:6px;border:2px solid transparent;border-radius:16px;background:#f7fbff;cursor:pointer}
.preset-choice.is-selected{border-color:#0b4f9c;background:#eef7ff}
.preset-choice img{display:block;width:100%;aspect-ratio:1/1;object-fit:cover;border-radius:12px;background:#fff}
.preset-check{position:absolute;right:8px;top:8px;width:25px;height:25px;display:none;place-items:center;border:2px solid #fff;border-radius:50%;background:#0b4f9c;color:#fff;font-size:14px;font-weight:900}
.preset-choice.is-selected .preset-check{display:grid}
.preset-actions{display:flex;justify-content:flex-end;gap:8px;margin-top:12px}
.preset-save{min-height:42px;padding:0 16px;border:0;border-radius:12px;background:#0b4f9c;color:#fff;font-weight:900;cursor:pointer}
.preset-save:disabled{opacity:.45;cursor:not-allowed}
.preset-empty{padding:14px;border-radius:12px;background:#f7fbff;color:#5d7891;text-align:center;font-size:13px;font-weight:700}
@media(max-width:390px){.preset-grid{grid-template-columns:repeat(3,minmax(0,1fr))}}

</style>
<div class="avatar-page">
    <div class="avatar-top">
        <a class="avatar-back" href="student-profile.php" aria-label="Quay lại">‹</a>
        <h1 class="avatar-title">My Avatar</h1>
        <span class="avatar-spacer"></span>
    </div>

    <?php if ($message!==''): ?><div class="avatar-message"><?= htmlspecialchars($message,ENT_QUOTES,'UTF-8') ?></div><?php endif; ?>
    <?php if ($error!==''): ?><div class="avatar-error"><?= htmlspecialchars($error,ENT_QUOTES,'UTF-8') ?></div><?php endif; ?>

    <section class="avatar-preview">
        <div class="avatar-circle">
            <?php if ($avatarUrl!==''): ?><img src="<?= htmlspecialchars($avatarUrl,ENT_QUOTES,'UTF-8') ?>" alt="Avatar"><?php else: ?><span aria-hidden="true">👤</span><?php endif; ?>
        </div>
        <div class="avatar-name"><?= htmlspecialchars($name,ENT_QUOTES,'UTF-8') ?></div>
    </section>

    <div class="avatar-actions">
        <button type="button" class="avatar-option" id="uploadAvatarButton">
            <span class="avatar-option__icon">📷</span>
            <span><span class="avatar-option__title">Tải hình lên</span><span class="avatar-option__text">Dùng ảnh từ điện thoại hoặc máy tính.</span></span>
            <span class="avatar-option__arrow">›</span>
        </button>
        <button type="button" class="avatar-option" id="openPresetButton">
            <span class="avatar-option__icon">🙂</span>
            <span><span class="avatar-option__title">Chọn avatar</span><span class="avatar-option__text">Chọn một mẫu avatar có sẵn.</span></span>
            <span class="avatar-option__arrow">›</span>
        </button>
        <button type="button" class="avatar-option" id="openBuilderButton">
            <span class="avatar-option__icon">✨</span>
            <span><span class="avatar-option__title">Tạo nhân vật</span><span class="avatar-option__text">Tự chọn tóc, khuôn mặt, trang phục và phụ kiện.</span></span>
            <span class="avatar-option__arrow">›</span>
        </button>
    </div>
    <section class="preset-panel" id="presetPanel">
        <h2 class="preset-title">Chọn avatar</h2>
        <?php if (!$presetFiles): ?>
            <div class="preset-empty">Chưa có avatar mẫu trong thư viện.</div>
        <?php else: ?>
            <div class="preset-grid" id="presetGrid">
                <?php foreach ($presetFiles as $presetFile): ?>
                    <?php $presetPath='assets/avatars/presets/'.$presetFile; ?>
                    <button type="button"
                            class="preset-choice<?= ($avatarSource==='preset' && $customAvatarPath===$presetPath) ? ' is-selected' : '' ?>"
                            data-preset="<?= htmlspecialchars($presetFile,ENT_QUOTES,'UTF-8') ?>">
                        <img src="../<?= htmlspecialchars($presetPath,ENT_QUOTES,'UTF-8') ?>" alt="Avatar">
                        <span class="preset-check">✓</span>
                    </button>
                <?php endforeach; ?>
            </div>
            <form method="post" id="presetSaveForm">
                <input type="hidden" name="action" value="save_preset_avatar">
                <input type="hidden" name="csrf_token" value="<?= htmlspecialchars((string)$_SESSION['avatar_csrf'],ENT_QUOTES,'UTF-8') ?>">
                <input type="hidden" name="preset_file" id="presetFileInput"
                       value="<?= ($avatarSource==='preset') ? htmlspecialchars(basename($customAvatarPath),ENT_QUOTES,'UTF-8') : '' ?>">
                <div class="preset-actions">
                    <button type="submit" class="preset-save" id="presetSaveButton"<?= $avatarSource==='preset' ? '' : ' disabled' ?>>Lưu avatar</button>
                </div>
            </form>
        <?php endif; ?>
    </section>

    <section class="builder-panel" id="builderPanel">
        <h2 class="builder-title">Tạo nhân vật</h2>
        <div class="builder-workspace">
            <div class="builder-options-side">
                <div class="builder-section" style="margin-top:0">
                    <div class="builder-section__title">Khuôn mặt</div>
                    <div class="builder-grid" id="baseChoices"></div>
                </div>
                <div class="builder-section">
                    <div class="builder-section__title">Tóc</div>
                    <div class="builder-grid" id="hairChoices"></div>
                </div>
                <p class="builder-help">Chọn khuôn mặt và kiểu tóc em thích.</p>
            </div>

            <div class="builder-preview-side">
                <div class="builder-stage" aria-label="Xem trước nhân vật">
                    <img class="builder-layer" id="builderBase" alt="">
                    <img class="builder-layer" id="builderHair" alt="">
                </div>
                <form method="post" id="builderSaveForm">
                    <input type="hidden" name="action" value="save_builder_avatar">
                    <input type="hidden" name="csrf_token" value="<?= htmlspecialchars((string)$_SESSION['avatar_csrf'],ENT_QUOTES,'UTF-8') ?>">
                    <input type="hidden" name="builder_base" id="builderBaseInput" value="">
                    <input type="hidden" name="builder_hair" id="builderHairInput" value="">
                    <div class="builder-actions">
                        <button type="submit" class="builder-save" id="builderSaveButton" disabled>Lưu avatar</button>
                    </div>
                </form>
            </div>
        </div>
    </section>
</div>
<form id="avatarUploadForm" method="post" enctype="multipart/form-data" hidden>
    <input type="hidden" name="action" value="upload_avatar">
    <input type="hidden" name="csrf_token" value="<?= htmlspecialchars((string)$_SESSION['avatar_csrf'],ENT_QUOTES,'UTF-8') ?>">
    <input type="file" id="avatarFileInput" name="avatar_file" accept="image/jpeg,image/png,image/webp">
</form>
<script>
const uploadButton=document.getElementById('uploadAvatarButton');
const uploadInput=document.getElementById('avatarFileInput');
const uploadForm=document.getElementById('avatarUploadForm');
uploadButton?.addEventListener('click',()=>uploadInput?.click());
uploadInput?.addEventListener('change',()=>{ if(uploadInput.files?.length) uploadForm?.submit(); });


const presetButton=document.getElementById('openPresetButton');
const presetPanel=document.getElementById('presetPanel');
const presetFileInput=document.getElementById('presetFileInput');
const presetSaveButton=document.getElementById('presetSaveButton');

presetButton?.addEventListener('click',()=>{
    presetPanel?.classList.toggle('is-open');
    if(presetPanel?.classList.contains('is-open')){
        document.getElementById('builderPanel')?.classList.remove('is-open');
        presetPanel.scrollIntoView({behavior:'smooth',block:'nearest'});
    }
});

document.querySelectorAll('.preset-choice').forEach(choice=>{
    choice.addEventListener('click',()=>{
        document.querySelectorAll('.preset-choice').forEach(x=>x.classList.remove('is-selected'));
        choice.classList.add('is-selected');
        if(presetFileInput) presetFileInput.value=choice.dataset.preset||'';
        if(presetSaveButton) presetSaveButton.disabled=!presetFileInput?.value;
    });
});

const builderButton=document.getElementById('openBuilderButton');
const builderPanel=document.getElementById('builderPanel');
const builderBase=document.getElementById('builderBase');
const builderHair=document.getElementById('builderHair');
const baseChoices=document.getElementById('baseChoices');
const hairChoices=document.getElementById('hairChoices');
const builderRoot='../assets/avatars/builder/';
const builderBaseInput=document.getElementById('builderBaseInput');
const builderHairInput=document.getElementById('builderHairInput');
const builderSaveButton=document.getElementById('builderSaveButton');

async function openAvatarBuilder(){
    presetPanel?.classList.remove('is-open');
    builderPanel.classList.add('is-open');
    builderPanel.scrollIntoView({behavior:'smooth',block:'start'});
    if (builderPanel.dataset.loaded==='1') return;
    try{
        const response=await fetch(builderRoot+'manifest.json',{cache:'no-store'});
        if(!response.ok) throw new Error('manifest');
        const manifest=await response.json();
        const bases=manifest?.categories?.base?.items || [];
        const hairs=manifest?.categories?.hair?.items || [];
        let selectedBase=manifest?.defaults?.base || bases[0]?.id || '';
        let selectedHair=manifest?.defaults?.hair || hairs[0]?.id || '';

        const render=()=>{
            const base=bases.find(x=>x.id===selectedBase);
            const hair=hairs.find(x=>x.id===selectedHair);
            builderBase.src=base ? builderRoot+'base/'+base.file : '';
            builderHair.src=hair ? builderRoot+'hair/'+hair.file : '';

            const fit=hair?.fit || {};
            const scale=Number(fit.scale ?? 0.84);

            // GV căn tóc trên khung 360px. Student preview nhỏ hơn,
            // nên offset phải đổi theo đúng tỉ lệ khung hiển thị.
            const teacherStageSize=360;
            const studentStageSize=builderBase.getBoundingClientRect().width || 220;
            const positionRatio=studentStageSize/teacherStageSize;
            const offsetX=Number(fit.offset_x ?? 0)*positionRatio;
            const offsetY=Number(fit.offset_y ?? -14)*positionRatio;

            builderHair.style.transform=`translate(${offsetX}px, ${offsetY}px) scale(${scale})`;

            if(builderBaseInput) builderBaseInput.value=selectedBase;
            if(builderHairInput) builderHairInput.value=selectedHair;
            if(builderSaveButton) builderSaveButton.disabled=!(selectedBase && selectedHair);

            baseChoices.querySelectorAll('.builder-choice').forEach(b=>b.classList.toggle('is-selected',b.dataset.id===selectedBase));
            hairChoices.querySelectorAll('.builder-choice').forEach(b=>b.classList.toggle('is-selected',b.dataset.id===selectedHair));
        };

        bases.forEach(item=>{
            const b=document.createElement('button');
            b.type='button'; b.className='builder-choice'; b.dataset.id=item.id;
            b.innerHTML='<img class="builder-thumb" src="'+builderRoot+'base/'+item.file+'" alt=""><span>'+item.label+'</span>';
            b.addEventListener('click',()=>{selectedBase=item.id; render();});
            baseChoices.appendChild(b);
        });
        hairs.forEach(item=>{
            const b=document.createElement('button');
            b.type='button'; b.className='builder-choice'; b.dataset.id=item.id;
            b.innerHTML='<img class="builder-thumb" src="'+builderRoot+'hair/'+item.file+'" alt=""><span>'+item.label+'</span>';
            b.addEventListener('click',()=>{selectedHair=item.id; render();});
            hairChoices.appendChild(b);
        });
        render();
        window.addEventListener('resize',render,{passive:true});
        builderPanel.dataset.loaded='1';
    }catch(e){
        builderPanel.innerHTML='<div class="avatar-error">Chưa đọc được thư viện avatar. Kiểm tra manifest.json và các folder base/hair.</div>';
    }
}
builderButton?.addEventListener('click',openAvatarBuilder);

</script>
<?php include __DIR__.'/../includes/student-layout-end.php'; ?>
