<?php

declare(strict_types=1);

/**
 * 推薦技師相片：將前端裁切／塗抹後的 data URL 轉存為縮圖 JPEG（減少 K 數）。
 * 直幅人像，輸出最長邊上限 600px、品質 82。
 */

function fate_masseur_photo_dir(): string
{
    return dirname(__DIR__) . DIRECTORY_SEPARATOR . 'uploads' . DIRECTORY_SEPARATOR . 'masseurs';
}

/**
 * 解析 data:image/(jpeg|png|webp);base64,...
 *
 * @return array{ok:bool,bytes:string,error:?string}
 */
function fate_masseur_parse_photo_data_url(string $dataUrl): array
{
    $raw = trim($dataUrl);
    if ($raw === '') {
        return ['ok' => false, 'bytes' => '', 'error' => null]; // 視為「未提供相片」
    }
    if (!preg_match('#^data:(image/(?:jpeg|png|webp));base64,(.+)$#i', $raw, $m)) {
        return ['ok' => false, 'bytes' => '', 'error' => '相片格式不正確（僅支援 JPEG／PNG／WebP）。'];
    }
    $bytes = base64_decode($m[2], true);
    if ($bytes === false || $bytes === '') {
        return ['ok' => false, 'bytes' => '', 'error' => '無法解碼相片資料。'];
    }
    if (strlen($bytes) > 4 * 1024 * 1024) {
        return ['ok' => false, 'bytes' => '', 'error' => '相片過大（請縮小或降低品質）。'];
    }

    return ['ok' => true, 'bytes' => $bytes, 'error' => null];
}

/**
 * 將圖片位元組縮圖並存檔，回傳 web 相對路徑（uploads/masseurs/xxx.jpg）。
 *
 * @return array{ok:bool,error:?string,rel:?string}
 */
function fate_masseur_save_photo_bytes(string $bytes, int $maxEdge = 600): array
{
    if ($bytes === '') {
        return ['ok' => false, 'error' => '沒有相片資料。', 'rel' => null];
    }
    if (!function_exists('imagecreatetruecolor')) {
        return ['ok' => false, 'error' => '伺服器未啟用 GD 圖片函式，無法處理相片。', 'rel' => null];
    }

    $src = @imagecreatefromstring($bytes);
    if ($src === false) {
        return ['ok' => false, 'error' => '無法讀取相片（格式可能不支援）。', 'rel' => null];
    }
    $sw = imagesx($src);
    $sh = imagesy($src);
    if ($sw < 1 || $sh < 1) {
        imagedestroy($src);

        return ['ok' => false, 'error' => '相片尺寸無效。', 'rel' => null];
    }

    $scale = min(1.0, $maxEdge / max($sw, $sh));
    $dw = max(1, (int) round($sw * $scale));
    $dh = max(1, (int) round($sh * $scale));

    $dst = imagecreatetruecolor($dw, $dh);
    if ($dst === false) {
        imagedestroy($src);

        return ['ok' => false, 'error' => '無法建立輸出相片。', 'rel' => null];
    }
    imagecopyresampled($dst, $src, 0, 0, 0, 0, $dw, $dh, $sw, $sh);
    imagedestroy($src);

    $dir = fate_masseur_photo_dir();
    if (!is_dir($dir) && !@mkdir($dir, 0775, true) && !is_dir($dir)) {
        imagedestroy($dst);

        return ['ok' => false, 'error' => '無法建立上傳目錄（請確認 fate/uploads/masseurs 可寫入）。', 'rel' => null];
    }

    $basename = 'm_' . bin2hex(random_bytes(8)) . '.jpg';
    $destFs = $dir . DIRECTORY_SEPARATOR . $basename;
    if (!imagejpeg($dst, $destFs, 82)) {
        imagedestroy($dst);

        return ['ok' => false, 'error' => '無法儲存相片檔。', 'rel' => null];
    }
    imagedestroy($dst);

    return ['ok' => true, 'error' => null, 'rel' => 'uploads/masseurs/' . $basename];
}

/** 預設頭像子目錄（uploads/masseurs/defaults/）。 */
function fate_masseur_default_photo_dir(): string
{
    return fate_masseur_photo_dir() . DIRECTORY_SEPARATOR . 'defaults';
}

/** @return 'female'|'male'|'other'|null */
function fate_masseur_default_avatar_gender_norm(string $gender): ?string
{
    $g = strtolower(trim($gender));
    if ($g === '女' || $g === 'f' || $g === 'female') {
        return 'female';
    }
    if ($g === '男' || $g === 'm' || $g === 'male') {
        return 'male';
    }
    if ($g === 'other' || $g === '其他') {
        return 'other';
    }

    return null;
}

function fate_masseur_default_avatar_settings_key(string $gender): ?string
{
    return match (fate_masseur_default_avatar_gender_norm($gender)) {
        'female' => 'default_avatar_female',
        'male' => 'default_avatar_male',
        'other' => 'default_avatar_other',
        default => null,
    };
}

/** 設定檔內預設頭像相對路徑（空＝未設定）。 */
function fate_masseur_default_avatar_rel(string $gender): ?string
{
    $key = fate_masseur_default_avatar_settings_key($gender);
    if ($key === null) {
        return null;
    }
    require_once __DIR__ . DIRECTORY_SEPARATOR . 'fate_masseur_rewards.php';
    $s = fate_masseur_rewards_settings();
    $rel = isset($s[$key]) ? trim((string) $s[$key]) : '';
    if ($rel === '' || str_contains($rel, '..') || !str_starts_with(str_replace('\\', '/', $rel), 'uploads/masseurs/')) {
        return null;
    }
    $fs = dirname(__DIR__) . DIRECTORY_SEPARATOR . str_replace('/', DIRECTORY_SEPARATOR, $rel);

    return is_file($fs) ? str_replace('\\', '/', $rel) : null;
}

/** 前台／後台 web 路徑（./uploads/...）。 */
function fate_masseur_photo_public_url(?string $rel): ?string
{
    $r = str_replace('\\', '/', trim((string) $rel));
    if ($r === '' || str_contains($r, '..')) {
        return null;
    }

    return './' . ltrim($r, '/');
}

/** 後台 admin/ 目錄預覽用（可附檔案 mtime 避免快取舊圖）。 */
function fate_masseur_photo_admin_url(?string $rel, bool $cacheBust = true): ?string
{
    $r = str_replace('\\', '/', trim((string) $rel));
    if ($r === '' || str_contains($r, '..') || !str_starts_with($r, 'uploads/masseurs/')) {
        return null;
    }

    $url = '../' . ltrim($r, '/');
    if ($cacheBust) {
        $fs = dirname(__DIR__) . DIRECTORY_SEPARATOR . str_replace('/', DIRECTORY_SEPARATOR, $r);
        if (is_file($fs)) {
            $url .= '?v=' . (string) filemtime($fs);
        }
    }

    return $url;
}

function fate_masseur_default_avatar_public_url(string $gender): ?string
{
    $rel = fate_masseur_default_avatar_rel($gender);
    if ($rel === null) {
        $g = fate_masseur_default_avatar_gender_norm($gender);
        if ($g === 'other') {
            $rel = fate_masseur_default_avatar_rel('female') ?? fate_masseur_default_avatar_rel('male');
        }
    }

    return $rel !== null ? fate_masseur_photo_public_url($rel) : null;
}

/**
 * 自訂相片優先；無則依性別使用後台預設頭像。
 */
function fate_masseur_resolve_photo_public_url(?string $customRel, string $gender): ?string
{
    $custom = fate_masseur_photo_public_url($customRel);
    if ($custom !== null) {
        return $custom;
    }

    return fate_masseur_default_avatar_public_url($gender);
}

/**
 * 後台儲存預設頭像（data URL → JPEG）。
 *
 * @return array{ok:bool,error:?string,rel:?string}
 */
function fate_masseur_save_default_avatar(string $gender, string $dataUrl): array
{
    $g = fate_masseur_default_avatar_gender_norm($gender);
    $key = fate_masseur_default_avatar_settings_key($gender);
    if ($g === null || $key === null) {
        return ['ok' => false, 'error' => '性別參數無效。', 'rel' => null];
    }
    $parsed = fate_masseur_parse_photo_data_url($dataUrl);
    if ($parsed['error'] !== null) {
        return ['ok' => false, 'error' => $parsed['error'], 'rel' => null];
    }
    if (!$parsed['ok'] || $parsed['bytes'] === '') {
        return ['ok' => false, 'error' => '請上傳並套用相片。', 'rel' => null];
    }

    $dir = fate_masseur_default_photo_dir();
    if (!is_dir($dir) && !@mkdir($dir, 0775, true) && !is_dir($dir)) {
        return ['ok' => false, 'error' => '無法建立預設頭像目錄。', 'rel' => null];
    }

    $basename = 'default_' . $g . '.jpg';
    $rel = 'uploads/masseurs/defaults/' . $basename;
    $destFs = $dir . DIRECTORY_SEPARATOR . $basename;

    $saved = fate_masseur_save_photo_bytes($parsed['bytes']);
    if (!$saved['ok'] || ($saved['rel'] ?? '') === '') {
        return ['ok' => false, 'error' => $saved['error'] ?? '無法處理相片。', 'rel' => null];
    }

    $tmpFs = dirname(__DIR__) . DIRECTORY_SEPARATOR . str_replace('/', DIRECTORY_SEPARATOR, (string) $saved['rel']);
    if (!@rename($tmpFs, $destFs)) {
        if (!@copy($tmpFs, $destFs)) {
            @unlink($tmpFs);

            return ['ok' => false, 'error' => '無法寫入預設頭像檔。', 'rel' => null];
        }
        @unlink($tmpFs);
    }

    require_once __DIR__ . DIRECTORY_SEPARATOR . 'fate_masseur_rewards.php';
    $oldRel = fate_masseur_default_avatar_rel($g);
    if ($oldRel !== null && $oldRel !== $rel) {
        fate_masseur_delete_photo_file($oldRel);
    }

    if (!fate_masseur_rewards_save([$key => $rel])['ok']) {
        return ['ok' => false, 'error' => '相片已存檔，但無法寫入設定（請檢查 fate/data 權限）。', 'rel' => $rel];
    }

    return ['ok' => true, 'error' => null, 'rel' => $rel];
}

/** @return array{ok:bool,error:?string} */
function fate_masseur_clear_default_avatar(string $gender): array
{
    $g = fate_masseur_default_avatar_gender_norm($gender);
    $key = fate_masseur_default_avatar_settings_key($gender);
    if ($g === null || $key === null) {
        return ['ok' => false, 'error' => '性別參數無效。'];
    }
    $rel = fate_masseur_default_avatar_rel($g);
    if ($rel !== null) {
        fate_masseur_delete_photo_file($rel);
    }
    require_once __DIR__ . DIRECTORY_SEPARATOR . 'fate_masseur_rewards.php';
    if (!fate_masseur_rewards_save([$key => ''])['ok']) {
        return ['ok' => false, 'error' => '無法更新設定。'];
    }

    return ['ok' => true, 'error' => null];
}

/** 刪除既有相片實體檔（容錯）。 */
function fate_masseur_delete_photo_file(?string $rel): void
{
    $r = str_replace('\\', '/', trim((string) $rel));
    if ($r === '' || str_contains($r, '..') || !str_starts_with($r, 'uploads/masseurs/')) {
        return;
    }
    $fs = dirname(__DIR__) . DIRECTORY_SEPARATOR . str_replace('/', DIRECTORY_SEPARATOR, $r);
    if (is_file($fs)) {
        @unlink($fs);
    }
}
