<?php
/**
 * POST /api/auth/register.php
 * Body: { email, password, account_type, full_name|business_name, phone? }
 */

require_once __DIR__ . '/../config/database.php';
require_once __DIR__ . '/../includes/response.php';
require_once __DIR__ . '/../includes/auth.php';
require_once __DIR__ . '/../includes/mailer.php';
require_once __DIR__ . '/../includes/settings.php';

only_post_allowed();

$input = get_json_input();

$missing = validate_required($input, ['email', 'password', 'account_type']);
if ($missing) {
    send_error('Missing required fields.', 422, $missing);
}

$email       = filter_var(trim($input['email']), FILTER_VALIDATE_EMAIL);
$password    = (string) $input['password'];
$accountType = $input['account_type'];
$phone       = trim($input['phone'] ?? '');
$city        = trim($input['city'] ?? '');
$country     = trim($input['country'] ?? '');

if (!$email) {
    send_error('Please provide a valid email address.', 422);
}

if (strlen($password) < 8) {
    send_error('Password must be at least 8 characters.', 422);
}

if (!in_array($accountType, ['personal', 'business'], true)) {
    send_error('account_type must be "personal" or "business".', 422);
}

// Type-specific required name field
if ($accountType === 'personal') {
    $missingName = validate_required($input, ['full_name']);
    if ($missingName) {
        send_error('Full name is required for a personal account.', 422);
    }
} else {
    $missingName = validate_required($input, ['business_name']);
    if ($missingName) {
        send_error('Business name is required for a business account.', 422);
    }
}

$pdo = Database::connect();

// Check for duplicate email
$stmt = $pdo->prepare('SELECT id FROM users WHERE email = ? LIMIT 1');
$stmt->execute([$email]);
if ($stmt->fetch()) {
    send_error('An account with this email already exists.', 409);
}

$passwordHash = password_hash($password, PASSWORD_BCRYPT);

try {
    $pdo->beginTransaction();

    $stmt = $pdo->prepare(
        'INSERT INTO users (email, password_hash, phone, account_type) VALUES (?, ?, ?, ?)'
    );
    $stmt->execute([$email, $passwordHash, $phone ?: null, $accountType]);
    $userId = (int) $pdo->lastInsertId();

    if ($accountType === 'personal') {
        $stmt = $pdo->prepare('INSERT INTO personal_profiles (user_id, full_name, city, country) VALUES (?, ?, ?, ?)');
        $stmt->execute([$userId, trim($input['full_name']), $city ?: null, $country ?: null]);
    } else {
        $trialDays = (int) get_setting($pdo, 'business_trial_days', '90');
        $trialEndsAt = date('Y-m-d', strtotime("+$trialDays days"));
        $stmt = $pdo->prepare(
            'INSERT INTO business_profiles (user_id, business_name, city, country, trial_ends_at) VALUES (?, ?, ?, ?, ?)'
        );
        $stmt->execute([$userId, trim($input['business_name']), $city ?: null, $country ?: null, $trialEndsAt]);
    }

    // Initialize loyalty balance
    $stmt = $pdo->prepare('INSERT INTO loyalty_points (user_id, points_balance) VALUES (?, 0)');
    $stmt->execute([$userId]);

    // Email verification: account is created but stays unusable (can't log
    // in) until the link below is clicked. See migration_v2's backfill note
    // for why this only applies to accounts created from this point on.
    $rawToken = bin2hex(random_bytes(32));
    $tokenHash = hash('sha256', $rawToken);
    $expiresAt = date('Y-m-d H:i:s', strtotime('+48 hours'));
    $stmt = $pdo->prepare('INSERT INTO email_verifications (user_id, token_hash, expires_at) VALUES (?, ?, ?)');
    $stmt->execute([$userId, $tokenHash, $expiresAt]);

    $pdo->commit();
} catch (Throwable $e) {
    $pdo->rollBack();
    send_error('Registration failed. Please try again.', 500, APP_ENV === 'local' ? [$e->getMessage()] : []);
}

// APP_URL points to wherever /public is web-accessible from (the live site
// serves /public's contents directly at the domain/subdomain root - see
// README "works under a subdomain pointed straight at public/" - so no
// "/public" segment belongs in this link; adding one 404s in that setup).
$verifyLink = APP_URL . '/verify-email.html?token=' . $rawToken;
$mailResult = send_email(
    $email,
    'Verify your Ragreen account',
    "Welcome to Ragreen!\n\nPlease verify your email address to activate your account:\n$verifyLink\n\nThis link expires in 48 hours.\n\nIf you didn't create this account, you can ignore this email."
);

$response = [
    'user' => [
        'id'           => $userId,
        'email'        => $email,
        'account_type' => $accountType,
    ],
];
// Local dev has no real mail server - surface the link directly so the flow is testable.
if (APP_ENV === 'local') {
    $response['dev_verify_link'] = $verifyLink;
}

$message = 'Account created! Check your email for a verification link before logging in.';
if (!$mailResult['ok']) {
    // The account exists but the email genuinely didn't go out - tell the
    // person plainly rather than pretending it's on its way. They can use
    // "Resend verification email" once the mail configuration is fixed.
    $message = 'Account created, but we could not send the verification email right now. '
             . 'Please try "Resend verification email" on the login page shortly, or contact support.';
}

send_json(true, $message, $response, 201);
