#!/usr/bin/env php
<?php

declare(strict_types=1);

// Referral administration CLI (no Laravel, no core). Usage:
//   php bin/referrals init
//   php bin/referrals link USER_ID [--url=https://site/register]
//   php bin/referrals stats USER_ID
//   php bin/referrals set-config KEY VALUE   (signup_bonus, commission_percent, commission_cap, register_url)
//   php bin/referrals get-config KEY
//   php bin/referrals list-rewards [USER_ID]
//   php bin/referrals pay REWARD_ID

spl_autoload_register(static function (string $class): void {
    if (str_starts_with($class, 'Referrals\\')) {
        $file = __DIR__ . '/../src/' . str_replace('\\', '/', substr($class, 10)) . '.php';
        if (is_file($file)) {
            require $file;
        }
    }
});

use Referrals\ReferralCodec;
use Referrals\SqliteReferralStore;

$storage = getenv('REFERRALS_DB') ?: __DIR__ . '/../storage/referrals.sqlite';
$store = new SqliteReferralStore($storage);
$codec = new ReferralCodec($store->loadOrCreateSecret());

$command = $argv[1] ?? 'help';
$rest = array_slice($argv, 2);

$fail = static function (string $msg): never {
    fwrite(STDERR, "error: {$msg}\n");
    exit(1);
};

$uid = static function (?string $v) use ($fail): int {
    if ($v === null || !ctype_digit($v) || (int) $v <= 0) {
        $fail('USER_ID must be a positive integer');
    }

    return (int) $v;
};

switch ($command) {
    case 'init':
        $store->init();
        echo "initialized {$storage}\n";
        break;

    case 'link':
        $id = $uid($rest[0] ?? null);
        $url = '';
        foreach ($rest as $arg) {
            if (str_starts_with($arg, '--url=')) {
                $url = substr($arg, 6);
            }
        }
        $url = $url !== '' ? $url : $store->getConfig('register_url', '');
        $code = $codec->encode($id);
        echo $url !== '' ? rtrim($url, '/') . '?ref=' . $code . "\n" : $code . "\n";
        break;

    case 'stats':
        $id = $uid($rest[0] ?? null);
        $stats = $store->statsFor($id);
        echo "referrals: {$stats['referrals']}, qualified: {$stats['qualified']}, earned: {$stats['earned']}, paid: {$stats['paid']}\n";
        break;

    case 'set-config':
        if (count($rest) < 2) {
            $fail('usage: referrals set-config KEY VALUE');
        }
        $allowed = ['signup_bonus', 'commission_percent', 'commission_cap', 'register_url'];
        if (!in_array($rest[0], $allowed, true)) {
            $fail('KEY must be one of: ' . implode(', ', $allowed));
        }
        $store->setConfig($rest[0], (string) $rest[1]);
        echo "{$rest[0]} = {$rest[1]}\n";
        break;

    case 'get-config':
        if (!isset($rest[0])) {
            $fail('usage: referrals get-config KEY');
        }
        echo $store->getConfig($rest[0]) . "\n";
        break;

    case 'list-rewards':
        $rows = $store->rewardsFor(isset($rest[0]) ? $uid($rest[0]) : null);
        if ($rows === []) {
            echo "no rewards\n";
            break;
        }
        printf("%-4s %-10s %-8s %-9s %-8s %-12s %-7s\n", 'id', 'referrer', 'kind', 'amount', 'basis', 'ref', 'status');
        foreach ($rows as $row) {
            printf("%-4d %-10d %-8s %-9s %-8s %-12s %-7s\n", $row['id'], $row['referrer_id'], $row['kind'], $row['amount'], $row['basis'], $row['ref'], $row['status']);
        }
        break;

    case 'pay':
        $id = $uid($rest[0] ?? null);
        if (!$store->markRewardPaid($id)) {
            $fail("reward #{$id} unknown or already paid");
        }
        echo "reward #{$id} marked paid (credit the amount to the wallet manually)\n";
        break;

    default:
        echo "usage: referrals {init|link|stats|set-config|get-config|list-rewards|pay}\n";
        exit($command === 'help' ? 0 : 1);
}
