<?php
// Creates or updates an income entry (an "id" field in the POST body means
// "edit that row"). Mirrors api/expense_save.php — see that file for the
// reasoning; this one drops payment_method_id and posts against incomes.

require_once __DIR__ . '/../includes/auth.php';
require_once __DIR__ . '/../includes/validation.php';

require_login();

if (!current_user_is_admin()) {
    $isAjax = ($_SERVER['HTTP_X_REQUESTED_WITH'] ?? '') === 'XMLHttpRequest';
    if ($isAjax) {
        header('Content-Type: application/json');
        http_response_code(403);
        echo json_encode(['success' => false, 'error' => "Income isn't available on this account."]);
        exit;
    }
    header('Location: ../index.php');
    exit;
}

$isAjax = ($_SERVER['HTTP_X_REQUESTED_WITH'] ?? '') === 'XMLHttpRequest';

function respond_json(array $payload, int $status = 200): void
{
    http_response_code($status);
    header('Content-Type: application/json');
    echo json_encode($payload);
    exit;
}

function respond_redirect(array $errors, array $oldInput): void
{
    $_SESSION['income_form_errors'] = $errors;
    $_SESSION['income_form_old'] = $oldInput;
    header('Location: ../income.php');
    exit;
}

if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    if ($isAjax) {
        respond_json(['success' => false, 'error' => 'Invalid request.'], 405);
    }
    header('Location: ../income.php');
    exit;
}

if (!csrf_verify($_POST['csrf_token'] ?? null)) {
    if ($isAjax) {
        respond_json([
            'success' => false,
            'session_expired' => true,
            'error' => 'Your session expired — please log in again.',
        ], 400);
    }
    respond_redirect([], $_POST);
}

$db = get_db();
$id = (int) ($_POST['id'] ?? 0);
$isEdit = $id > 0;

if ($isEdit) {
    $existsStmt = $db->prepare('SELECT 1 FROM incomes WHERE id = :id');
    $existsStmt->execute(['id' => $id]);
    if (!$existsStmt->fetchColumn()) {
        $message = 'That entry no longer exists — it may have been deleted.';
        if ($isAjax) {
            respond_json(['success' => false, 'error' => $message], 404);
        }
        header('Location: ../income.php');
        exit;
    }
}

$result = validate_income_input($_POST);

if (!empty($result['errors'])) {
    if ($isAjax) {
        respond_json(['success' => false, 'errors' => $result['errors']], 422);
    }
    respond_redirect($result['errors'], $_POST);
}

$data = $result['data'];

if ($isEdit) {
    $stmt = $db->prepare(
        'UPDATE incomes SET income_date = :income_date, amount = :amount, category_id = :category_id, description = :description
         WHERE id = :id'
    );
    $stmt->execute([
        'income_date' => $data['income_date'],
        'amount'      => $data['amount'],
        'category_id' => $data['category_id'],
        'description' => $data['description'],
        'id'          => $id,
    ]);
} else {
    $userId = (int) current_user()['id'];
    $stmt = $db->prepare(
        'INSERT INTO incomes (income_date, amount, category_id, user_id, description)
         VALUES (:income_date, :amount, :category_id, :user_id, :description)'
    );
    $stmt->execute([
        'income_date' => $data['income_date'],
        'amount'      => $data['amount'],
        'category_id' => $data['category_id'],
        'user_id'     => $userId,
        'description' => $data['description'],
    ]);
}

if (!$isAjax) {
    header('Location: ../income.php');
    exit;
}

$categoryStmt = $db->prepare('SELECT name FROM categories WHERE id = :id');
$categoryStmt->execute(['id' => $data['category_id']]);
$categoryName = $categoryStmt->fetchColumn();

// Refresh whichever month income.php currently has open.
$month = resolve_viewed_month($_POST['viewed_month'] ?? null);

respond_json([
    'success' => true,
    'action'  => $isEdit ? 'updated' : 'created',
    'toast'   => $categoryName . ' ' . format_money($data['amount']),
    'summary' => [
        'total_formatted' => format_money(get_month_income_total($month)),
    ],
    'incomes' => array_map('format_recent_income_row', get_month_incomes($month)),
]);
