<?php
// syncPayments.php

// DEBUG: show PHP errors (remove or lower in production)
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);

header("Content-Type: application/json");
header("Access-Control-Allow-Origin", "*");
header("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
header("Access-Control-Allow-Headers", "Content-Type");

if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
    http_response_code(204);
    echo json_encode(["status" => "ok", "message" => "OPTIONS"]);
    exit;
}

// Include config.php which creates $pdo
require_once __DIR__ . '/../../config.php';

$method    = $_SERVER['REQUEST_METHOD'];
$direction = isset($_GET['direction']) ? strtolower($_GET['direction']) : null;

if ($direction === null && $method !== 'OPTIONS') {
    http_response_code(400);
    echo json_encode(["error" => "Missing 'direction' parameter (pull|push)."]);
    exit;
}

try {
    if ($method === 'GET' && $direction === 'pull') {
        pullPayments($pdo);
        exit;
    }

    if ($method === 'POST' && $direction === 'push') {
        $raw  = file_get_contents('php://input');
        $data = json_decode($raw, true);

        if (!is_array($data)) {
            http_response_code(400);
            echo json_encode(["error" => "Invalid JSON payload"]);
            exit;
        }

        syncPayments($pdo, $data);
        exit;
    }

    http_response_code(405);
    echo json_encode([
        "error"     => "Method/direction not allowed",
        "method"    => $method,
        "direction" => $direction
    ]);
} catch (Exception $e) {
    http_response_code(500);
    echo json_encode([
        "error"   => "Server error",
        "details" => $e->getMessage()
    ]);
}

/**
 * GET: send all payments to desktop.
 * Must match PaymentSyncDto in PaymentsSync.cs:
 *  Id, Uuid, ContractId, InvoiceNumber,
 *  PaymentDate, Amount, Method, Reference, Notes,
 *  IsDeleted, LastModified, CreatedAt
 */
function pullPayments(PDO $pdo)
{
    $stmt = $pdo->query("
        SELECT
            Id,
            Uuid,
            ContractId,
            InvoiceNumber,
            PaymentDate,
            Amount,
            Method,
            Reference,
            Notes,
            IsDeleted,
            LastModified,
            CreatedAt
        FROM ClientPayments
        ORDER BY Id
    ");
    $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
    echo json_encode($rows);
}

/**
 * POST: receive payments from desktop.
 *
 * Rules:
 *  - Desktop sends LastModified as ISO string.
 *  - Server stores LastModified as TEXT (exactly as sent).
 *  - If local LastModified is newer or equal (string compare), skip update.
 *  - Always ensure referenced ContractId exists (same as old syncPayments).
 */
function syncPayments(PDO $pdo, array $payments)
{
    $pdo->beginTransaction();

    // Existing payment's LastModified
    $select = $pdo->prepare("
        SELECT LastModified
        FROM ClientPayments
        WHERE Id = :Id
    ");

    // Insert new payment
    $insert = $pdo->prepare("
        INSERT INTO ClientPayments
        (Id, Uuid, ContractId, InvoiceNumber,
         PaymentDate, Amount, Method, Reference, Notes,
         IsDeleted, LastModified, CreatedAt)
        VALUES
        (:Id, :Uuid, :ContractId, :InvoiceNumber,
         :PaymentDate, :Amount, :Method, :Reference, :Notes,
         :IsDeleted, :LastModified, :CreatedAt)
    ");

    // Update existing payment
    $update = $pdo->prepare("
        UPDATE ClientPayments
        SET Uuid         = :Uuid,
            ContractId   = :ContractId,
            InvoiceNumber= :InvoiceNumber,
            PaymentDate  = :PaymentDate,
            Amount       = :Amount,
            Method       = :Method,
            Reference    = :Reference,
            Notes        = :Notes,
            IsDeleted    = :IsDeleted,
            LastModified = :LastModified,
            CreatedAt    = :CreatedAt
        WHERE Id = :Id
    ");

    // Ensure contract exists (same as old syncPayments)
    $checkContract = $pdo->prepare("SELECT COUNT(*) FROM ClientContracts WHERE Id = ?");

    $count = 0;

    foreach ($payments as $p) {
        $id = isset($p['Id']) ? (int)$p['Id'] : null;
        if ($id === null) {
            continue;
        }

        $contractId = isset($p['ContractId']) ? (int)$p['ContractId'] : 0;

        // Skip if contract does not exist
        $checkContract->execute([$contractId]);
        if ($checkContract->fetchColumn() == 0) {
            continue;
        }

        $uuid    = $p['Uuid']          ?? null;
        $invoice = $p['InvoiceNumber'] ?? null;
        $date    = $p['PaymentDate']   ?? date('Y-m-d');
        $amount  = isset($p['Amount']) && $p['Amount'] !== ''
            ? (float)$p['Amount'] : 0;
        $method  = $p['Method']    ?? null;
        $ref     = $p['Reference'] ?? null;
        $notes   = $p['Notes']     ?? null;
        $isDel   = !empty($p['IsDeleted']) ? 1 : 0;
        $created = $p['CreatedAt'] ?? date('Y-m-d H:i:s');

        // Incoming LastModified from desktop (ISO string)
        $incomingLast = $p['LastModified'] ?? null;
        if ($incomingLast === null) {
            $incomingLast = gmdate('Y-m-d\TH:i:s\Z');
        }

        // Compare with local text LastModified
        $select->execute([':Id' => $id]);
        $row = $select->fetch(PDO::FETCH_ASSOC);

        if (!$row) {
            // New payment → INSERT
            $insert->execute([
                ':Id'           => $id,
                ':Uuid'         => $uuid,
                ':ContractId'   => $contractId,
                ':InvoiceNumber'=> $invoice,
                ':PaymentDate'  => $date,
                ':Amount'       => $amount,
                ':Method'       => $method,
                ':Reference'    => $ref,
                ':Notes'        => $notes,
                ':IsDeleted'    => $isDel,
                ':LastModified' => $incomingLast,
                ':CreatedAt'    => $created,
            ]);

            $count++;
            continue;
        }

        $localLast = $row['LastModified'] ?? null;

        if (!empty($localLast) &&
            strcmp($localLast, $incomingLast) >= 0) {
            // Local row newer or equal → skip
            continue;
        }

        // Desktop newer → UPDATE
        $update->execute([
            ':Id'           => $id,
            ':Uuid'         => $uuid,
            ':ContractId'   => $contractId,
            ':InvoiceNumber'=> $invoice,
            ':PaymentDate'  => $date,
            ':Amount'       => $amount,
            ':Method'       => $method,
            ':Reference'    => $ref,
            ':Notes'        => $notes,
            ':IsDeleted'    => $isDel,
            ':LastModified' => $incomingLast,
            ':CreatedAt'    => $created,
        ]);

        $count++;
    }

    $pdo->commit();

    echo json_encode([
        "status" => "ok",
        "entity" => "payments",
        "synced" => $count
    ]);
}
