<?php
/*
 * AIWK Wallet P2P Job Escrow MVP
 * P2P 작업 결제 흐름 예시.
 * 중요: 작업 상태 변경과 잔액 이동은 하나의 트랜잭션 안에서 처리한다.
 */
require_once dirname(__FILE__) . '/wallet_lib.php';

function wallet_job_create($requester_user_id, $title, $description, $price_credit, $fee_credit)
{
    $requester_user_id = wallet_require_user_id($requester_user_id);
    $price_credit = wallet_require_amount($price_credit);
    $fee_credit = (int)$fee_credit;
    if ($fee_credit < 0) throw new Exception(wallet_t('invalid_amount'));
    $job = wallet_table('p2p_job');
    $title_sql = wallet_sql_escape($title);
    $desc_sql = wallet_sql_escape($description);
    sql_query("INSERT INTO `{$job}` (`requester_user_id`, `title`, `description`, `price_credit`, `fee_credit`, `status`) VALUES ({$requester_user_id}, '{$title_sql}', '{$desc_sql}', {$price_credit}, {$fee_credit}, 'OPEN')", true, wallet_db());
    return sql_insert_id(wallet_db());
}

function wallet_job_get_for_update($job_id)
{
    $job_id = (int)$job_id;
    if ($job_id <= 0) throw new Exception(wallet_t('job_not_found'));
    $job = wallet_table('p2p_job');
    $r = sql_fetch("SELECT * FROM `{$job}` WHERE `job_id`={$job_id} FOR UPDATE", true, wallet_db());
    if (!$r) throw new Exception(wallet_t('job_not_found'));
    return $r;
}

/* 작업자 수락: requester의 금액을 AVAILABLE에서 LOCKED로 이동하고 작업 상태를 WORKING으로 변경한다. */
function wallet_job_accept($job_id, $worker_user_id)
{
    $worker_user_id = wallet_require_user_id($worker_user_id);
    $job_id = (int)$job_id;
    $tx_id = wallet_uuid_v4();

    wallet_begin();
    try {
        $r = wallet_job_get_for_update($job_id);
        if ($r['status'] !== 'OPEN') throw new Exception(wallet_t('job_status_invalid'));
        $requester = (int)$r['requester_user_id'];
        if ($requester == $worker_user_id) throw new Exception(wallet_t('same_user'));

        $total = (int)$r['price_credit'] + (int)$r['fee_credit'];
        if ($total <= 0) throw new Exception(wallet_t('invalid_amount'));

        wallet_lock_balance_rows($requester);
        wallet_debit_available($requester, $total);
        wallet_inc_bucket($requester, AIWK_WALLET_BUCKET_LOCKED, $total);
        wallet_add_ledger($tx_id, 'LOCK', $requester, $requester, $total, 0, 'AVAILABLE', AIWK_WALLET_BUCKET_LOCKED, 'P2P 작업 에스크로 잠금: job_id=' . $job_id, 'p2p_job', $job_id);

        $job = wallet_table('p2p_job');
        sql_query("UPDATE `{$job}` SET `worker_user_id`={$worker_user_id}, `status`='WORKING' WHERE `job_id`={$job_id}", true, wallet_db());
        wallet_commit();
        return $tx_id;
    } catch (Exception $e) {
        wallet_rollback();
        throw $e;
    }
}

function wallet_job_submit($job_id, $submit_memo)
{
    $job_id = (int)$job_id;
    wallet_begin();
    try {
        $r = wallet_job_get_for_update($job_id);
        if ($r['status'] !== 'WORKING') throw new Exception(wallet_t('job_status_invalid'));
        $job = wallet_table('p2p_job');
        $memo_sql = wallet_sql_escape($submit_memo);
        sql_query("UPDATE `{$job}` SET `status`='SUBMITTED', `submit_memo`='{$memo_sql}' WHERE `job_id`={$job_id}", true, wallet_db());
        wallet_commit();
        return true;
    } catch (Exception $e) {
        wallet_rollback();
        throw $e;
    }
}

/* 요청자 승인: LOCKED에서 작업자/플랫폼으로 지급하고 작업 상태를 DONE으로 변경한다. */
function wallet_job_complete($job_id, $platform_user_id)
{
    $job_id = (int)$job_id;
    $platform_user_id = $platform_user_id ? (int)$platform_user_id : AIWK_WALLET_PLATFORM_USER_ID;
    $tx_id = wallet_uuid_v4();

    wallet_begin();
    try {
        $r = wallet_job_get_for_update($job_id);
        if ($r['status'] !== 'SUBMITTED') throw new Exception(wallet_t('job_status_invalid'));
        $requester = (int)$r['requester_user_id'];
        $worker = (int)$r['worker_user_id'];
        $amount = (int)$r['price_credit'];
        $fee = (int)$r['fee_credit'];
        $total = $amount + $fee;

        wallet_lock_balance_rows($requester);
        wallet_lock_balance_rows($worker);
        if ($platform_user_id > 0 && $fee > 0) wallet_lock_balance_rows($platform_user_id);

        $rows = wallet_get_balances($requester);
        if ((int)$rows['LOCKED'] < $total) throw new Exception(wallet_t('insufficient_balance'));

        wallet_inc_bucket($requester, AIWK_WALLET_BUCKET_LOCKED, -$total);
        wallet_inc_bucket($worker, AIWK_WALLET_BUCKET_PAID, $amount);
        if ($platform_user_id > 0 && $fee > 0) {
            wallet_inc_bucket($platform_user_id, AIWK_WALLET_BUCKET_PAID, $fee);
        }

        wallet_add_ledger($tx_id, 'ESCROW_RELEASE', $requester, $worker, $amount, $fee, AIWK_WALLET_BUCKET_LOCKED, AIWK_WALLET_BUCKET_PAID, 'P2P 작업 승인 지급: job_id=' . $job_id, 'p2p_job', $job_id);

        $job = wallet_table('p2p_job');
        sql_query("UPDATE `{$job}` SET `status`='DONE' WHERE `job_id`={$job_id}", true, wallet_db());
        wallet_commit();
        return $tx_id;
    } catch (Exception $e) {
        wallet_rollback();
        throw $e;
    }
}

/* 취소: WORKING/SUBMITTED 상태에서 LOCKED 금액을 requester의 PAID로 되돌린다. */
function wallet_job_cancel($job_id)
{
    $job_id = (int)$job_id;
    $tx_id = wallet_uuid_v4();

    wallet_begin();
    try {
        $r = wallet_job_get_for_update($job_id);
        if ($r['status'] !== 'WORKING' && $r['status'] !== 'SUBMITTED') throw new Exception(wallet_t('job_status_invalid'));
        $requester = (int)$r['requester_user_id'];
        $total = (int)$r['price_credit'] + (int)$r['fee_credit'];

        wallet_lock_balance_rows($requester);
        $rows = wallet_get_balances($requester);
        if ((int)$rows['LOCKED'] < $total) throw new Exception(wallet_t('insufficient_balance'));

        wallet_inc_bucket($requester, AIWK_WALLET_BUCKET_LOCKED, -$total);
        wallet_inc_bucket($requester, AIWK_WALLET_BUCKET_PAID, $total);
        wallet_add_ledger($tx_id, 'UNLOCK', $requester, $requester, $total, 0, AIWK_WALLET_BUCKET_LOCKED, AIWK_WALLET_BUCKET_PAID, 'P2P 작업 취소 잠금 해제: job_id=' . $job_id, 'p2p_job', $job_id);

        $job = wallet_table('p2p_job');
        sql_query("UPDATE `{$job}` SET `status`='CANCELLED' WHERE `job_id`={$job_id}", true, wallet_db());
        wallet_commit();
        return $tx_id;
    } catch (Exception $e) {
        wallet_rollback();
        throw $e;
    }
}
