<?php
/**
 * POST /api/campaign/create   (multipart/form-data)
 *
 * Body:
 *   app_name        — App display name
 *   app_developer   — Developer name
 *   app_link        — Play Store URL (https://play.google.com/store/apps/details?id=...)
 *   app_des         — Description
 *   plan_name       — Silver | Gold | Platinum
 *   app_icon        — file (image/jpeg|png|webp, max 2MB)
 *
 * Inserts into `pub_purchase_history` with status_admin = 0 (transient draft).
 * Returns campaign_id + redirect to checkout.
 */

declare(strict_types=1);
require_once dirname(__DIR__, 2) . '/config/bootstrap.php';

if ($_SERVER['REQUEST_METHOD'] !== 'POST') jsonError('Method not allowed', 405);

$user = Auth::apiRequireLogin();
$pid  = (int)$user['publisher_id'];
Csrf::validate();

RateLimit::hit('campaign:create:' . $pid, 30, 3600, 'Too many campaigns submitted. Try later.');

// ───── Inputs ─────
$appName      = Validator::clean((string)($_POST['app_name'] ?? ''), 100);
$appDeveloper = Validator::clean((string)($_POST['app_developer'] ?? ''), 100);
$appLink      = Validator::clean((string)($_POST['app_link'] ?? ''), 500);
$appDes       = Validator::clean((string)($_POST['app_des'] ?? ''), 2000);
$planName     = Validator::clean((string)($_POST['plan_name'] ?? ''), 50);

// ───── Validation ─────
if (mb_strlen($appName) < 3)        jsonError('App name must be at least 3 characters.');
if (mb_strlen($appDeveloper) < 3)   jsonError('Developer name must be at least 3 characters.');
if (!Validator::playStoreUrl($appLink)) {
    jsonError('Play Store URL must look like https://play.google.com/store/apps/details?id=…');
}
if (mb_strlen($appDes) < 20)        jsonError('Description must be at least 20 characters.');
if (mb_strlen($appDes) > 2000)      jsonError('Description is too long (max 2000 chars).');
if (!Validator::planName($planName)) jsonError('Please select a valid plan.');

// Extract package id from Play Store URL (id=com.example.app)
preg_match('/[?&]id=([a-zA-Z0-9._]+)/', $appLink, $m);
$appPkg = $m[1] ?? '';
if (!Validator::packageId($appPkg)) {
    jsonError('Could not extract a valid package ID from the Play Store URL.');
}

// ───── Lookup plan from DB ─────
$pdo = db();
$planStmt = $pdo->prepare("
    SELECT plan_name, total_users, plan_testing_days, coin_per_day,
           COALESCE(price_inr, 0) AS price_inr
    FROM tester_pkg_plans
    WHERE LOWER(plan_name) = LOWER(?)
    LIMIT 1
");
$planStmt->execute([$planName]);
$plan = $planStmt->fetch();
if (!$plan) jsonError('Selected plan does not exist.', 404);

$totalUsers      = (int)$plan['total_users'];
$planTestingDays = (int)$plan['plan_testing_days'];
$perUserCoins    = $planTestingDays * (int)$plan['coin_per_day'];

// ───── File upload ─────
if (empty($_FILES['app_icon']) || $_FILES['app_icon']['error'] === UPLOAD_ERR_NO_FILE) {
    jsonError('Please upload an app icon.');
}
$check = Validator::uploadedImage($_FILES['app_icon']);
if (!$check['ok']) jsonError($check['error']);

// ───── Save the icon ─────
$datedDir = date('Y/m');
$targetDir = UPLOADS_PATH . '/app-icons/' . $datedDir;
if (!is_dir($targetDir) && !mkdir($targetDir, 0755, true) && !is_dir($targetDir)) {
    Logger::error('Could not create icon dir', ['dir' => $targetDir]);
    jsonError('Server upload directory unavailable.', 500);
}

$randName = bin2hex(random_bytes(8)) . '_' . time() . '.' . $check['ext'];
$relPath  = $datedDir . '/' . $randName;
$absPath  = $targetDir . '/' . $randName;

// Resize to 512×512 max, square (uses GD)
$resizeOk = resizeIcon($_FILES['app_icon']['tmp_name'], $absPath, $check['mime'], (int)env('APP_ICON_RESIZE', 512));
if (!$resizeOk) {
    // Fallback: just move the original
    if (!move_uploaded_file($_FILES['app_icon']['tmp_name'], $absPath)) {
        Logger::error('Icon move failed', ['from' => $_FILES['app_icon']['tmp_name'], 'to' => $absPath]);
        jsonError('Could not save uploaded icon.', 500);
    }
}

// ───── Insert into pub_purchase_history (status_admin = 0 = transient draft) ─────
try {
    $stmt = $pdo->prepare("
        INSERT INTO pub_purchase_history
          (publisher_id, app_logo, app_icon_path, app_title, app_pkg, app_developername,
           app_des, plan_name, plan_testing_days, per_user_coins, total_users,
           completed_users, status_admin, created_at)
        VALUES (?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0, 0, NOW())
    ");
    $stmt->execute([
        $pid,
        $relPath,
        $appName,
        $appPkg,
        $appDeveloper,
        $appDes,
        $plan['plan_name'],
        $planTestingDays,
        $perUserCoins,
        $totalUsers,
    ]);
    $campaignId = (int)$pdo->lastInsertId();
} catch (Throwable $e) {
    @unlink($absPath);
    Logger::error('Campaign insert failed', ['error' => $e->getMessage()]);
    jsonError('Could not save campaign. Please try again.', 500);
}

Logger::audit($pid, 'campaign_created', 'campaign', $campaignId, [
    'plan'     => $plan['plan_name'],
    'app_pkg'  => $appPkg,
    'app_name' => $appName,
]);

jsonSuccess('Campaign created. Continue to checkout.', [
    'campaign_id' => $campaignId,
    'redirect'    => '/dashboard/checkout?cid=' . $campaignId,
]);


// ─────────────────────────────────────────────────────────────
// Helpers
// ─────────────────────────────────────────────────────────────

/**
 * Resize an uploaded image to a square (max $size × $size) and save.
 * Returns true on success, false on any failure (caller should fallback).
 */
function resizeIcon(string $srcPath, string $dstPath, string $mime, int $size): bool
{
    if (!extension_loaded('gd')) return false;

    $src = match ($mime) {
        'image/jpeg' => @imagecreatefromjpeg($srcPath),
        'image/png'  => @imagecreatefrompng($srcPath),
        'image/webp' => function_exists('imagecreatefromwebp') ? @imagecreatefromwebp($srcPath) : false,
        default      => false,
    };
    if (!$src) return false;

    $w = imagesx($src);
    $h = imagesy($src);
    if ($w <= 0 || $h <= 0) {
        imagedestroy($src);
        return false;
    }

    // Crop to square (centered)
    $sq = min($w, $h);
    $sx = (int)(($w - $sq) / 2);
    $sy = (int)(($h - $sq) / 2);

    $out = imagecreatetruecolor($size, $size);
    // Preserve transparency for PNG/WEBP
    imagealphablending($out, false);
    imagesavealpha($out, true);
    $transparent = imagecolorallocatealpha($out, 0, 0, 0, 127);
    imagefilledrectangle($out, 0, 0, $size, $size, $transparent);

    imagecopyresampled($out, $src, 0, 0, $sx, $sy, $size, $size, $sq, $sq);

    $ok = match ($mime) {
        'image/jpeg' => imagejpeg($out, $dstPath, 88),
        'image/png'  => imagepng($out, $dstPath, 8),
        'image/webp' => function_exists('imagewebp') && imagewebp($out, $dstPath, 88),
        default      => false,
    };

    imagedestroy($src);
    imagedestroy($out);
    return (bool)$ok;
}
