<?php

declare(strict_types=1);

/**
 * 會員收藏技師：收藏／取消、體驗狀態、公開清單設定。
 */

require_once __DIR__ . DIRECTORY_SEPARATOR . 'fate_store_masseurs.php';
require_once __DIR__ . DIRECTORY_SEPARATOR . 'fate_member_profile.php';

function fate_masseur_favorite_tables_ddl(): array
{
    return [
        <<<'SQL'
CREATE TABLE IF NOT EXISTS `fate_masseur_favorites` (
  `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
  `member_id` INT UNSIGNED NOT NULL,
  `masseur_id` INT UNSIGNED NOT NULL,
  `favorited_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `is_experienced` TINYINT NOT NULL DEFAULT 0,
  `experienced_at` DATETIME NULL DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `uq_member_masseur` (`member_id`, `masseur_id`),
  KEY `idx_masseur` (`masseur_id`),
  KEY `idx_member_fav` (`member_id`, `favorited_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
SQL,
    ];
}

function fate_masseur_favorite_ensure_tables(PDO $pdo): void
{
    static $done = false;
    if ($done) {
        return;
    }
    fate_masseur_ensure_tables($pdo);
    fate_member_profile_ensure_table($pdo);
    try {
        foreach (fate_masseur_favorite_tables_ddl() as $ddl) {
            $pdo->exec($ddl);
        }
        $pdo->exec(
            'ALTER TABLE `fate_store_masseurs` ADD COLUMN IF NOT EXISTS `favorite_count` INT UNSIGNED NOT NULL DEFAULT 0 AFTER `dislike_count`'
        );
        $pdo->exec(
            'ALTER TABLE `fate_site_member_profiles` ADD COLUMN IF NOT EXISTS `masseur_favorites_public` TINYINT NOT NULL DEFAULT 0'
        );
        $done = true;
    } catch (Throwable) {
        try {
            $cols = $pdo->query("SHOW COLUMNS FROM `fate_store_masseurs` LIKE 'favorite_count'")->fetchAll();
            if ($cols === []) {
                $pdo->exec('ALTER TABLE `fate_store_masseurs` ADD COLUMN `favorite_count` INT UNSIGNED NOT NULL DEFAULT 0 AFTER `dislike_count`');
            }
            $pcols = $pdo->query("SHOW COLUMNS FROM `fate_site_member_profiles` LIKE 'masseur_favorites_public'")->fetchAll();
            if ($pcols === []) {
                $pdo->exec('ALTER TABLE `fate_site_member_profiles` ADD COLUMN `masseur_favorites_public` TINYINT NOT NULL DEFAULT 0');
            }
            $done = true;
        } catch (Throwable) {
        }
    }
}

function fate_masseur_favorite_recount(PDO $pdo, int $masseurId): void
{
    if ($masseurId <= 0) {
        return;
    }
    fate_masseur_favorite_ensure_tables($pdo);
    try {
        $st = $pdo->prepare(
            'UPDATE `fate_store_masseurs` m SET `favorite_count` = (
                SELECT COUNT(*) FROM `fate_masseur_favorites` f WHERE f.`masseur_id` = m.`id`
             ) WHERE m.`id` = ?'
        );
        $st->execute([$masseurId]);
    } catch (Throwable) {
    }
}

/** @param list<int> $masseurIds @return array<int,int> */
function fate_masseur_favorite_counts_map(PDO $pdo, array $masseurIds): array
{
    fate_masseur_favorite_ensure_tables($pdo);
    $ids = array_values(array_unique(array_filter(array_map('intval', $masseurIds), static fn (int $id): bool => $id > 0)));
    if ($ids === []) {
        return [];
    }
    $place = implode(',', array_fill(0, count($ids), '?'));
    $out = [];
    try {
        $st = $pdo->prepare("SELECT `id`, `favorite_count` FROM `fate_store_masseurs` WHERE `id` IN ($place)");
        $st->execute($ids);
        foreach ($st->fetchAll(PDO::FETCH_ASSOC) as $row) {
            $out[(int) $row['id']] = (int) ($row['favorite_count'] ?? 0);
        }
    } catch (Throwable) {
        return [];
    }

    return $out;
}

/** @param list<int> $masseurIds @return array<int,bool> */
function fate_masseur_favorite_viewer_map(PDO $pdo, int $memberId, array $masseurIds): array
{
    fate_masseur_favorite_ensure_tables($pdo);
    if ($memberId <= 0) {
        return [];
    }
    $ids = array_values(array_unique(array_filter(array_map('intval', $masseurIds), static fn (int $id): bool => $id > 0)));
    if ($ids === []) {
        return [];
    }
    $place = implode(',', array_fill(0, count($ids), '?'));
    $out = [];
    try {
        $st = $pdo->prepare("SELECT `masseur_id` FROM `fate_masseur_favorites` WHERE `member_id` = ? AND `masseur_id` IN ($place)");
        $st->execute(array_merge([$memberId], $ids));
        foreach ($st->fetchAll(PDO::FETCH_ASSOC) as $row) {
            $out[(int) $row['masseur_id']] = true;
        }
    } catch (Throwable) {
        return [];
    }

    return $out;
}

/** @return array{ok:bool,favorited:bool,error:?string} */
function fate_masseur_favorite_toggle(PDO $pdo, int $memberId, int $masseurId): array
{
    fate_masseur_favorite_ensure_tables($pdo);
    if ($memberId <= 0) {
        return ['ok' => false, 'favorited' => false, 'error' => '請先登入。'];
    }
    if ($masseurId <= 0) {
        return ['ok' => false, 'favorited' => false, 'error' => '技師無效。'];
    }
    $masseur = fate_masseur_get($pdo, $masseurId);
    if ($masseur === null || (int) ($masseur['is_hidden'] ?? 0) === 1) {
        return ['ok' => false, 'favorited' => false, 'error' => '找不到技師。'];
    }
    try {
        $chk = $pdo->prepare('SELECT `id` FROM `fate_masseur_favorites` WHERE `member_id` = ? AND `masseur_id` = ? LIMIT 1');
        $chk->execute([$memberId, $masseurId]);
        $existing = $chk->fetchColumn();
        if ($existing !== false) {
            $pdo->prepare('DELETE FROM `fate_masseur_favorites` WHERE `id` = ?')->execute([(int) $existing]);
            fate_masseur_favorite_recount($pdo, $masseurId);

            return ['ok' => true, 'favorited' => false, 'error' => null];
        }
        $pdo->prepare(
            'INSERT INTO `fate_masseur_favorites` (`member_id`, `masseur_id`, `favorited_at`, `is_experienced`)
             VALUES (?, ?, NOW(), 0)'
        )->execute([$memberId, $masseurId]);
        fate_masseur_favorite_recount($pdo, $masseurId);

        return ['ok' => true, 'favorited' => true, 'error' => null];
    } catch (Throwable $e) {
        return ['ok' => false, 'favorited' => false, 'error' => '操作失敗：' . $e->getMessage()];
    }
}

/** @return array{ok:bool,error:?string} */
function fate_masseur_favorite_set_experienced(PDO $pdo, int $memberId, int $masseurId, bool $experienced): array
{
    fate_masseur_favorite_ensure_tables($pdo);
    if ($memberId <= 0) {
        return ['ok' => false, 'error' => '請先登入。'];
    }
    if ($masseurId <= 0) {
        return ['ok' => false, 'error' => '技師無效。'];
    }
    try {
        $st = $pdo->prepare(
            'UPDATE `fate_masseur_favorites`
             SET `is_experienced` = ?, `experienced_at` = CASE WHEN ? = 1 THEN COALESCE(`experienced_at`, NOW()) ELSE NULL END
             WHERE `member_id` = ? AND `masseur_id` = ?'
        );
        $flag = $experienced ? 1 : 0;
        $st->execute([$flag, $flag, $memberId, $masseurId]);
        if ($st->rowCount() === 0) {
            return ['ok' => false, 'error' => '請先收藏此技師。'];
        }

        return ['ok' => true, 'error' => null];
    } catch (Throwable $e) {
        return ['ok' => false, 'error' => '更新失敗：' . $e->getMessage()];
    }
}

function fate_member_favorites_public_get(PDO $pdo, int $memberId): bool
{
    fate_masseur_favorite_ensure_tables($pdo);
    if ($memberId <= 0) {
        return false;
    }
    try {
        $st = $pdo->prepare('SELECT `masseur_favorites_public` FROM `fate_site_member_profiles` WHERE `member_id` = ? LIMIT 1');
        $st->execute([$memberId]);
        $v = $st->fetchColumn();

        return (int) $v === 1;
    } catch (Throwable) {
        return false;
    }
}

/** @return array{ok:bool,error:?string} */
function fate_member_favorites_public_set(PDO $pdo, int $memberId, bool $isPublic): array
{
    fate_masseur_favorite_ensure_tables($pdo);
    if ($memberId <= 0) {
        return ['ok' => false, 'error' => '會員無效。'];
    }
    $flag = $isPublic ? 1 : 0;
    try {
        $pdo->prepare(
            'INSERT INTO `fate_site_member_profiles` (`member_id`, `avatar_rel`, `masseur_favorites_public`)
             VALUES (?, \'\', ?)
             ON DUPLICATE KEY UPDATE `masseur_favorites_public` = VALUES(`masseur_favorites_public`)'
        )->execute([$memberId, $flag]);

        return ['ok' => true, 'error' => null];
    } catch (Throwable $e) {
        return ['ok' => false, 'error' => '儲存失敗：' . $e->getMessage()];
    }
}

/** @return list<array<string,mixed>> */
function fate_masseur_favorites_list_for_member(PDO $pdo, int $memberId): array
{
    fate_masseur_favorite_ensure_tables($pdo);
    if ($memberId <= 0) {
        return [];
    }
    try {
        $st = $pdo->prepare(
            'SELECT f.`id` AS `favorite_id`, f.`favorited_at`, f.`is_experienced`, f.`experienced_at`,
                    m.`id` AS `masseur_id`, m.`name`, m.`gender`, m.`photo_rel`, m.`spa_store_id`, m.`favorite_count`,
                    s.`store_name`, s.`city_name`, s.`district_name`
             FROM `fate_masseur_favorites` f
             INNER JOIN `fate_store_masseurs` m ON m.`id` = f.`masseur_id` AND m.`is_hidden` = 0
             LEFT JOIN `spa_store_snapshots` s ON s.`spa_store_id` = m.`spa_store_id`
             WHERE f.`member_id` = ?
             ORDER BY f.`favorited_at` DESC, f.`id` DESC'
        );
        $st->execute([$memberId]);
        $rows = $st->fetchAll(PDO::FETCH_ASSOC);
    } catch (Throwable) {
        return [];
    }

    return is_array($rows) ? $rows : [];
}

/**
 * @return array{ok:bool,error:?string,member:array{display_name:string,username:string}|null,items:list<array<string,mixed>>}
 */
function fate_masseur_favorites_public_for_member(PDO $pdo, int $memberId): array
{
    $empty = ['ok' => false, 'error' => '此會員的收藏清單未公開。', 'member' => null, 'items' => []];
    if ($memberId <= 0) {
        return $empty;
    }
    if (!fate_member_favorites_public_get($pdo, $memberId)) {
        return $empty;
    }
    $memberQt = fate_masseur_member_table_qualified();
    $displayName = '會員 #' . $memberId;
    $username = '';
    try {
        $ms = $pdo->prepare("SELECT `username`, `display_name` FROM {$memberQt} WHERE `id` = ? LIMIT 1");
        $ms->execute([$memberId]);
        $mr = $ms->fetch(PDO::FETCH_ASSOC);
        if (is_array($mr)) {
            $username = trim((string) ($mr['username'] ?? ''));
            $dn = trim((string) ($mr['display_name'] ?? ''));
            if ($dn !== '') {
                $displayName = $dn;
            } elseif ($username !== '') {
                $displayName = $username;
            }
        }
    } catch (Throwable) {
    }
    $items = fate_masseur_favorites_list_for_member($pdo, $memberId);

    return [
        'ok' => true,
        'error' => null,
        'member' => ['display_name' => $displayName, 'username' => $username],
        'items' => $items,
    ];
}

function fate_masseur_favorites_delete_for_masseur(PDO $pdo, int $masseurId): void
{
    if ($masseurId <= 0) {
        return;
    }
    fate_masseur_favorite_ensure_tables($pdo);
    try {
        $pdo->prepare('DELETE FROM `fate_masseur_favorites` WHERE `masseur_id` = ?')->execute([$masseurId]);
    } catch (Throwable) {
    }
}
