<?php
/**
 * PayPal Checkout return/cancel handler.
 *
 * The order is CREATED in new-submission.php; the buyer approves at PayPal and
 * is sent back here. We CAPTURE server-side and only then fulfill the
 * submission — and only if PayPal reports COMPLETED for the exact amount we
 * expected. Nothing the browser sends is trusted to mean "paid".
 */
require_once('common.php');
require_once('checklogin.php');            // poet must be logged in
require_once(__DIR__ . '/paypal_rest.php');
require_once(__DIR__ . '/credits.php');    // credits_grant()

$poet_id = (int)($_SESSION['poet_id'] ?? 0);
$action  = $_GET['action'] ?? '';

/* ---- Buyer cancelled at PayPal: discard the pending entry + its upload ---- */
if ($action === 'cancel') {
    $pending_id = (int)($_GET['pending'] ?? 0);
    $stmt = $pdo->prepare("SELECT attachment FROM sm_paypal_pending WHERE id = :id AND poet_id = :p AND status = 'created'");
    $stmt->execute([':id' => $pending_id, ':p' => $poet_id]);
    if ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
        $file = __DIR__ . '/attachments/' . basename((string)$row['attachment']);
        if ($row['attachment'] !== '' && is_file($file)) { @unlink($file); }
        $pdo->prepare("UPDATE sm_paypal_pending SET status = 'canceled' WHERE id = :id")
            ->execute([':id' => $pending_id]);
    }
    header('Location: new-submission.php?cancel-payment');
    exit;
}

/* ---- Buyer approved: capture and verify --------------------------------- */
if ($action === 'return') {
    $pending_id = (int)($_GET['pending'] ?? 0);
    $order_id   = (string)($_GET['token'] ?? '');   // PayPal appends ?token=<orderID>

    $stmt = $pdo->prepare("SELECT * FROM sm_paypal_pending WHERE id = :id AND poet_id = :p");
    $stmt->execute([':id' => $pending_id, ':p' => $poet_id]);
    $pending = $stmt->fetch(PDO::FETCH_ASSOC);

    // Must exist, still be awaiting capture, and match the order we created.
    if (!$pending || $pending['status'] !== 'created'
        || $order_id === '' || $pending['paypal_order_id'] !== $order_id) {
        header('Location: my-submissions.php');
        exit;
    }

    try {
        $facts = pp_capture_facts(pp_capture_order($pdo, $order_id));

        $amount_ok = number_format((float)$pending['expected_amount'], 2, '.', '')
                   === number_format((float)$facts['amount'], 2, '.', '');
        $verified  = $facts['completed']
                   && $amount_ok
                   && $facts['currency'] === $pending['currency']
                   && (string)$facts['custom_id'] === (string)$pending['id'];

        if (!$verified) {
            error_log('paypal capture NOT verified for pending ' . $pending['id'] . ': ' . json_encode($facts));
            $pdo->prepare("UPDATE sm_paypal_pending SET status = 'failed' WHERE id = :id")
                ->execute([':id' => $pending['id']]);
            header('Location: new-submission.php?payment-failed');
            exit;
        }

        // Fulfil everything the poet paid for, atomically, so a crash can't
        // leave a paid-but-missing submission.
        $pdo->beginTransaction();

        // 1) The submission itself. Any paid submission is marked 'paid' so it
        //    floats to the top of the editors' slush pile.
        $ins = $pdo->prepare("INSERT INTO sm_submissions
            (poetid, title, editionid, type, body, attachment, bio_comments, date_submitted, status, ip_address, ptype)
            VALUES (:poetid, :title, :eid, 'Poetry', '', :att, :bio, NOW(), 0, :ip, 'paid')");
        $ins->execute([
            ':poetid' => (int)$pending['poet_id'],
            ':title'  => (string)$pending['title'],
            ':eid'    => (int)$pending['edition_id'],
            ':att'    => (string)$pending['attachment'],
            ':bio'    => (string)($pending['bio_comments'] ?? ''),
            ':ip'     => (string)$pending['ip_address'],
        ]);
        $sid = (int)$pdo->lastInsertId();

        // 2) A contest fee covered by a credit — consumption was deferred from
        //    new-submission.php because the poet also had a PayPal amount to pay.
        if (!empty($pending['apply_credit'])) {
            credits_grant($pdo, (int)$pending['poet_id'], -1,
                'Used on submission #' . $sid . ' (contest entry)', null, $sid);
        }

        $pdo->prepare("UPDATE sm_paypal_pending SET status = 'captured', captured_submission_id = :sid WHERE id = :id")
            ->execute([':sid' => $sid, ':id' => $pending['id']]);
        $pdo->commit();

        // Contest or regular edition? Only affects the confirmation wording.
        $is_contest = false;
        try {
            $ce = $pdo->prepare("SELECT is_contest FROM sm_editions WHERE id = :e");
            $ce->execute([':e' => (int)$pending['edition_id']]);
            if ($er = $ce->fetch(PDO::FETCH_ASSOC)) {
                $is_contest = (bool)$er['is_contest'];
            }
        } catch (Throwable $e) { /* default: treat as a plain submission */ }

        header('Location: my-submissions.php?success-payment=1&entry=' . ($is_contest ? 'contest' : 'free'));
        exit;

    } catch (Throwable $e) {
        if ($pdo->inTransaction()) $pdo->rollBack();
        error_log('paypal return capture error (pending ' . $pending['id'] . '): ' . $e->getMessage());
        header('Location: new-submission.php?payment-error');
        exit;
    }
}

/* ---- Anything else ------------------------------------------------------- */
header('Location: new-submission.php');
exit;
