<?php

declare(strict_types=1);

/**
 * N 幣歷程查詢：以 fate_reward_ledger 為紀錄來源（FATE 站內發放與扣回）。
 * 提供會員自查與後台全站查詢、合計、與中文動作標籤。
 */

require_once __DIR__ . DIRECTORY_SEPARATOR . 'fate_masseur_rewards.php';
require_once __DIR__ . DIRECTORY_SEPARATOR . 'fate_store_masseurs.php';
require_once __DIR__ . DIRECTORY_SEPARATOR . 'fate_ncoin_settings.php';

/** @return array<string,string> action => 中文說明 */
function fate_ncoin_action_labels(): array
{
    $n = fate_ncoin_display_name();

    return [
        'masseur_create' => '推薦技師建檔',
        'review' => '發表評論',
        'vote_like' => '技師點讚',
        'forum_thread' => '發表論壇主題',
        'forum_post' => '論壇回文',
        'forum_paid_buy' => '購買付費文章',
        'forum_paid_sell' => '付費文章售出',
        'ncoin_transfer_out' => $n . '轉出',
        'ncoin_transfer_in' => $n . '轉入',
        'store_recommend_fixed' => '推薦店家',
        'store_recommend_mobile' => '非定點服務',
        'tag_pick' => '技師標籤點選',
        'crowd_store_closed' => '回報店家歇業',
        'crowd_store_renamed' => '回報店家更名',
        'crowd_masseur_left_store' => '回報技師已離店',
        'admin_grant' => '管理員發放',
    ];
}

/** @return list<string> */
function fate_ncoin_debit_actions(): array
{
    return ['forum_paid_buy', 'ncoin_transfer_out'];
}

function fate_ncoin_action_label(string $action): string
{
    $map = fate_ncoin_action_labels();

    return $map[$action] ?? $action;
}

/** 帳本列是否為支出（扣款）。 */
function fate_ncoin_ledger_is_debit(string $action, int $amount): bool
{
    if ($amount < 0) {
        return true;
    }

    return in_array($action, fate_ncoin_debit_actions(), true);
}

/**
 * 帳本列的有效增減（已扣回視為 0）。
 */
function fate_ncoin_ledger_signed_amount(array $row): int
{
    if (!empty($row['reverted'])) {
        return 0;
    }
    $amount = (int) ($row['amount'] ?? 0);
    $action = (string) ($row['action'] ?? '');
    if ($amount < 0) {
        return $amount;
    }
    if (fate_ncoin_ledger_is_debit($action, $amount)) {
        return -abs($amount);
    }

    return abs($amount);
}

/** 列表顯示用 N 幣字串（+10／-10；已扣回獎勵仍顯示 +原額）。 */
function fate_ncoin_format_ledger_amount(array $row): string
{
    if (!empty($row['reverted'])) {
        return '+' . number_format(abs((int) ($row['amount'] ?? 0)));
    }
    $signed = fate_ncoin_ledger_signed_amount($row);
    if ($signed > 0) {
        return '+' . number_format($signed);
    }
    if ($signed < 0) {
        return '-' . number_format(abs($signed));
    }

    return '0';
}

/** @return 'credit'|'debit'|'reverted' */
function fate_ncoin_ledger_amount_kind(array $row): string
{
    if (!empty($row['reverted'])) {
        return 'reverted';
    }

    return fate_ncoin_ledger_signed_amount($row) < 0 ? 'debit' : 'credit';
}

/** 套用狀態（寫入會員表／主站）的可讀文字。 */
function fate_ncoin_applied_label(array $row): string
{
    $local = !empty($row['applied_local']);
    $spa = !empty($row['applied_spa']);
    if ($local && $spa) {
        return '會員表＋主站';
    }
    if ($local) {
        return '會員表';
    }
    if ($spa) {
        return '主站';
    }

    return '未入帳';
}

/**
 * 取得單一會員的 N 幣歷程。
 *
 * @return list<array<string,mixed>>
 */
function fate_ncoin_history_for_member(PDO $pdo, int $memberId, int $limit = 20, int $offset = 0): array
{
    fate_reward_ledger_ensure_table($pdo);
    if ($memberId <= 0) {
        return [];
    }
    $limit = max(1, min(200, $limit));
    $offset = max(0, $offset);
    try {
        $st = $pdo->prepare(
            'SELECT * FROM `fate_reward_ledger` WHERE `member_id` = ? ORDER BY `id` DESC LIMIT ' . $limit . ' OFFSET ' . $offset
        );
        $st->execute([$memberId]);
        $rows = $st->fetchAll(PDO::FETCH_ASSOC);

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

/** 會員紀錄總筆數（分頁用）。 */
function fate_ncoin_history_count_for_member(PDO $pdo, int $memberId): int
{
    fate_reward_ledger_ensure_table($pdo);
    if ($memberId <= 0) {
        return 0;
    }
    try {
        $st = $pdo->prepare('SELECT COUNT(*) FROM `fate_reward_ledger` WHERE `member_id` = ?');
        $st->execute([$memberId]);

        return (int) $st->fetchColumn();
    } catch (Throwable) {
        return 0;
    }
}

/**
 * 會員 N 幣歷程合計。
 *
 * @return array{earned:int,reverted:int,net:int,count:int}
 */
function fate_ncoin_history_summary_for_member(PDO $pdo, int $memberId): array
{
    fate_reward_ledger_ensure_table($pdo);
    $empty = ['earned' => 0, 'reverted' => 0, 'spent' => 0, 'net' => 0, 'count' => 0];
    if ($memberId <= 0) {
        return $empty;
    }
    try {
        $st = $pdo->prepare(
            'SELECT
                COUNT(*) AS cnt,
                COALESCE(SUM(CASE WHEN `reverted` = 1 THEN ABS(`amount`) ELSE 0 END), 0) AS reverted,
                COALESCE(SUM(
                    CASE
                        WHEN `reverted` = 1 THEN 0
                        WHEN `amount` < 0 THEN ABS(`amount`)
                        WHEN `action` IN (\'forum_paid_buy\', \'ncoin_transfer_out\') THEN ABS(`amount`)
                        ELSE 0
                    END
                ), 0) AS spent,
                COALESCE(SUM(
                    CASE
                        WHEN `reverted` = 1 THEN 0
                        WHEN `amount` < 0 THEN 0
                        WHEN `action` IN (\'forum_paid_buy\', \'ncoin_transfer_out\') THEN 0
                        ELSE ABS(`amount`)
                    END
                ), 0) AS earned,
                COALESCE(SUM(
                    CASE
                        WHEN `reverted` = 1 THEN 0
                        WHEN `amount` < 0 THEN `amount`
                        WHEN `action` IN (\'forum_paid_buy\', \'ncoin_transfer_out\') THEN -ABS(`amount`)
                        ELSE ABS(`amount`)
                    END
                ), 0) AS net
             FROM `fate_reward_ledger` WHERE `member_id` = ?'
        );
        $st->execute([$memberId]);
        $r = $st->fetch(PDO::FETCH_ASSOC);
        if (!is_array($r)) {
            return $empty;
        }

        return [
            'earned' => (int) $r['earned'],
            'reverted' => (int) $r['reverted'],
            'spent' => (int) ($r['spent'] ?? 0),
            'net' => (int) $r['net'],
            'count' => (int) $r['cnt'],
        ];
    } catch (Throwable) {
        return $empty;
    }
}

/**
 * 後台：全站 N 幣歷程（含會員名稱），可選依會員或動作過濾。
 *
 * @return list<array<string,mixed>>
 */
/**
 * 組出後台查詢的 WHERE 片段與參數（list 與 count 共用）。
 *
 * @return array{where:string, params:list<mixed>}
 */
function fate_ncoin_history_build_where(?string $memberQt, string $keyword, string $action): array
{
    $conds = [];
    $params = [];
    $kw = trim($keyword);
    if ($kw !== '') {
        if ($memberQt !== null) {
            $conds[] = '(mb.`username` LIKE ? OR mb.`display_name` LIKE ? OR l.`member_id` = ?)';
            $params[] = '%' . $kw . '%';
            $params[] = '%' . $kw . '%';
            $params[] = ctype_digit($kw) ? (int) $kw : -1;
        } else {
            $conds[] = 'l.`member_id` = ?';
            $params[] = ctype_digit($kw) ? (int) $kw : -1;
        }
    }
    $act = trim($action);
    if ($act !== '' && isset(fate_ncoin_action_labels()[$act])) {
        $conds[] = 'l.`action` = ?';
        $params[] = $act;
    }

    return [
        'where' => $conds !== [] ? 'WHERE ' . implode(' AND ', $conds) . ' ' : '',
        'params' => $params,
    ];
}

function fate_ncoin_history_all(PDO $pdo, string $keyword = '', string $action = '', int $limit = 50, int $offset = 0): array
{
    fate_reward_ledger_ensure_table($pdo);
    $limit = max(1, min(500, $limit));
    $offset = max(0, $offset);
    $memberQt = fate_masseur_member_table_qualified();

    $sql = 'SELECT l.*, ';
    $sql .= $memberQt !== null
        ? "COALESCE(NULLIF(TRIM(mb.`display_name`), ''), mb.`username`, CONCAT('會員#', l.`member_id`)) AS member_name "
        : "CONCAT('會員#', l.`member_id`) AS member_name ";
    $sql .= 'FROM `fate_reward_ledger` l ';
    if ($memberQt !== null) {
        $sql .= "LEFT JOIN $memberQt mb ON mb.`id` = l.`member_id` ";
    }
    $wb = fate_ncoin_history_build_where($memberQt, $keyword, $action);
    $sql .= $wb['where'];
    $sql .= 'ORDER BY l.`id` DESC LIMIT ' . $limit . ' OFFSET ' . $offset;

    try {
        $st = $pdo->prepare($sql);
        $st->execute($wb['params']);
        $rows = $st->fetchAll(PDO::FETCH_ASSOC);

        return is_array($rows) ? $rows : [];
    } catch (Throwable) {
        try {
            $st = $pdo->query('SELECT * FROM `fate_reward_ledger` ORDER BY `id` DESC LIMIT ' . $limit . ' OFFSET ' . $offset);

            return $st !== false ? $st->fetchAll(PDO::FETCH_ASSOC) : [];
        } catch (Throwable) {
            return [];
        }
    }
}

/** 後台查詢結果總筆數（分頁用）。 */
function fate_ncoin_history_all_count(PDO $pdo, string $keyword = '', string $action = ''): int
{
    fate_reward_ledger_ensure_table($pdo);
    $memberQt = fate_masseur_member_table_qualified();
    $wb = fate_ncoin_history_build_where($memberQt, $keyword, $action);

    $sql = 'SELECT COUNT(*) FROM `fate_reward_ledger` l ';
    if ($memberQt !== null) {
        $sql .= "LEFT JOIN $memberQt mb ON mb.`id` = l.`member_id` ";
    }
    $sql .= $wb['where'];

    try {
        $st = $pdo->prepare($sql);
        $st->execute($wb['params']);

        return (int) $st->fetchColumn();
    } catch (Throwable) {
        return 0;
    }
}

/**
 * 後台：全站合計。
 *
 * @return array{earned:int,reverted:int,net:int,count:int}
 */
function fate_ncoin_history_totals(PDO $pdo): array
{
    fate_reward_ledger_ensure_table($pdo);
    $empty = ['earned' => 0, 'reverted' => 0, 'spent' => 0, 'net' => 0, 'count' => 0];
    try {
        $st = $pdo->query(
            'SELECT COUNT(*) AS cnt,
                COALESCE(SUM(CASE WHEN `reverted` = 1 THEN ABS(`amount`) ELSE 0 END), 0) AS reverted,
                COALESCE(SUM(
                    CASE
                        WHEN `reverted` = 1 THEN 0
                        WHEN `amount` < 0 THEN ABS(`amount`)
                        WHEN `action` IN (\'forum_paid_buy\', \'ncoin_transfer_out\') THEN ABS(`amount`)
                        ELSE 0
                    END
                ), 0) AS spent,
                COALESCE(SUM(
                    CASE
                        WHEN `reverted` = 1 THEN 0
                        WHEN `amount` < 0 THEN 0
                        WHEN `action` IN (\'forum_paid_buy\', \'ncoin_transfer_out\') THEN 0
                        ELSE ABS(`amount`)
                    END
                ), 0) AS earned,
                COALESCE(SUM(
                    CASE
                        WHEN `reverted` = 1 THEN 0
                        WHEN `amount` < 0 THEN `amount`
                        WHEN `action` IN (\'forum_paid_buy\', \'ncoin_transfer_out\') THEN -ABS(`amount`)
                        ELSE ABS(`amount`)
                    END
                ), 0) AS net
             FROM `fate_reward_ledger`'
        );
        $r = $st !== false ? $st->fetch(PDO::FETCH_ASSOC) : null;
        if (!is_array($r)) {
            return $empty;
        }

        return [
            'earned' => (int) $r['earned'],
            'reverted' => (int) $r['reverted'],
            'spent' => (int) ($r['spent'] ?? 0),
            'net' => (int) $r['net'],
            'count' => (int) $r['cnt'],
        ];
    } catch (Throwable) {
        return $empty;
    }
}
