<?php
// syncContracts.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') {
        pullContracts($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;
        }

        syncContracts($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 contracts to desktop.
 * Must match ContractSyncDto in ContractsSync.cs.
 */
function pullContracts(PDO $pdo)
{
    $stmt = $pdo->query("
        SELECT
            Id,
            ClientId,
            PlotId,
            OriginalPrice,
            DiscountCode,
            DiscountType,
            DiscountValue,
            DiscountAmount,
            FinalPrice,
            PlanType,
            PlanMonths,
            MonthlyAmount,
            Status,
            CreatedAt,
            ContractId,
            LastModified AS LastModified
        FROM ClientContracts
        ORDER BY Id
    ");
    $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
    echo json_encode($rows);
}

/**
 * Map contract Status to Plots.Status.
 * Plots.Status codes: 0 = Available, 1 = Sold, 2 = Pending.
 *
 * Example contract semantics:
 *  - 0 / "New" / "Draft"  => plot Available (0)
 *  - 1 / "Active"         => plot Pending (2)
 *  - 2 / "Completed"      => plot Sold (1)
 */
function mapContractStatusToPlotStatus($contractStatus): int
{
    if ($contractStatus === null || $contractStatus === '') {
        return 0;
    }

    $s = strtolower((string)$contractStatus);

    // Numeric contract status
    if (ctype_digit($s)) {
        $n = (int)$s;
        if ($n === 2) {
            // Completed contract => Sold plot
            return 1;
        }
        if ($n === 1) {
            // Active contract => Pending plot
            return 2;
        }
        // Any other numeric (e.g. 0) => Available
        return 0;
    }

    // Textual contract status
    if ($s === 'completed' || $s === 'finished' || $s === 'paid') {
        return 1; // Sold
    }
    if ($s === 'active' || $s === 'ongoing') {
        return 2; // Pending
    }

    // Default: plot stays Available
    return 0;
}

/**
 * POST: receive contracts from desktop.
 */
function syncContracts(PDO $pdo, array $contracts)
{
    $pdo->beginTransaction();

    // Check existing contract's last modified
    $select = $pdo->prepare("
        SELECT LastModified
        FROM ClientContracts
        WHERE Id = :Id
    ");

    // Insert new contract
    $insert = $pdo->prepare("
        INSERT INTO ClientContracts
        (Id, ClientId, PlotId,
         OriginalPrice, DiscountCode, DiscountType, DiscountValue, DiscountAmount,
         FinalPrice, PlanType, PlanMonths, MonthlyAmount,
         Status, CreatedAt, ContractId, LastModified)
        VALUES
        (:Id, :ClientId, :PlotId,
         :OriginalPrice, :DiscountCode, :DiscountType, :DiscountValue, :DiscountAmount,
         :FinalPrice, :PlanType, :PlanMonths, :MonthlyAmount,
         :Status, :CreatedAt, :ContractId, :LastModified)
    ");

    // Update existing contract
    $update = $pdo->prepare("
        UPDATE ClientContracts
        SET ClientId       = :ClientId,
            PlotId         = :PlotId,
            OriginalPrice  = :OriginalPrice,
            DiscountCode   = :DiscountCode,
            DiscountType   = :DiscountType,
            DiscountValue  = :DiscountValue,
            DiscountAmount = :DiscountAmount,
            FinalPrice     = :FinalPrice,
            PlanType       = :PlanType,
            PlanMonths     = :PlanMonths,
            MonthlyAmount  = :MonthlyAmount,
            Status         = :Status,
            CreatedAt      = :CreatedAt,
            ContractId     = :ContractId,
            LastModified   = :LastModified
        WHERE Id = :Id
    ");

    // Update related plot (status, client link, buyer name)
    $updatePlot = $pdo->prepare("
        UPDATE Plots
        SET Status    = :Status,
            ClientId  = :ClientId,
            BuyerName = :BuyerName
        WHERE Id = :PlotId
    ");

    $count = 0;

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

        $clientId = isset($c['ClientId']) ? (int)$c['ClientId'] : 0;
        $plotId   = isset($c['PlotId'])   ? (int)$c['PlotId']   : 0;

        // prices come as strings from desktop
        $origPrice  = isset($c['OriginalPrice']) && $c['OriginalPrice'] !== ''
            ? (float)$c['OriginalPrice'] : 0.0;
        $discCode   = $c['DiscountCode'] ?? null;
        $discType   = $c['DiscountType'] ?? null;
        $discValue  = isset($c['DiscountValue']) && $c['DiscountValue'] !== ''
            ? (float)$c['DiscountValue'] : null;
        $discAmount = isset($c['DiscountAmount']) && $c['DiscountAmount'] !== ''
            ? (float)$c['DiscountAmount'] : 0.0;
        $finalPrice = isset($c['FinalPrice']) && $c['FinalPrice'] !== ''
            ? (float)$c['FinalPrice'] : 0.0;

        $planType   = $c['PlanType'] ?? 'Full';
        $planMonths = isset($c['PlanMonths']) ? (int)$c['PlanMonths'] : null;
        $monthlyAmt = isset($c['MonthlyAmount']) && $c['MonthlyAmount'] !== ''
            ? (float)$c['MonthlyAmount'] : null;

        $status     = $c['Status'] ?? 'Active';
        $createdAt  = $c['CreatedAt'] ?? date('Y-m-d H:i:s');
        $contractId = $c['ContractId'] ?? null;

        // Incoming LastModified from desktop (ISO text)
        $incomingLast = $c['LastModified'] ?? null;
        if ($incomingLast === null) {
            $incomingLast = gmdate('Y-m-d\TH:i:s\Z');
        }
        $incomingTime = strtotime($incomingLast);
        if ($incomingTime === false) {
            $incomingTime = time();
        }
        $incomingLastMysql = gmdate('Y-m-d H:i:s', $incomingTime);

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

        // Map contract status to plot status (for Plots.Status)
        $plotStatus = mapContractStatusToPlotStatus($status);

        if (!$row) {
            // New contract → INSERT
            $insert->execute([
                ':Id'            => $id,
                ':ClientId'      => $clientId,
                ':PlotId'        => $plotId,
                ':OriginalPrice' => $origPrice,
                ':DiscountCode'  => $discCode,
                ':DiscountType'  => $discType,
                ':DiscountValue' => $discValue,
                ':DiscountAmount'=> $discAmount,
                ':FinalPrice'    => $finalPrice,
                ':PlanType'      => $planType,
                ':PlanMonths'    => $planMonths,
                ':MonthlyAmount' => $monthlyAmt,
                ':Status'        => $status,
                ':CreatedAt'     => $createdAt,
                ':ContractId'    => $contractId,
                ':LastModified'  => $incomingLastMysql,
            ]);

            // Mark plot according to contract
            $updatePlot->execute([
                ':Status'   => $plotStatus,
                ':ClientId' => $clientId,
                ':BuyerName'=> null,
                ':PlotId'   => $plotId,
            ]);

            $count++;
            continue;
        }

        $serverLast = $row['LastModified'] ?? null;
        if (!empty($serverLast)) {
            $serverTime = strtotime($serverLast);
            if ($serverTime !== false && $incomingTime <= $serverTime) {
                // Server newer or equal → skip
                continue;
            }
        }

        // Desktop newer → UPDATE
        $update->execute([
            ':Id'            => $id,
            ':ClientId'      => $clientId,
            ':PlotId'        => $plotId,
            ':OriginalPrice' => $origPrice,
            ':DiscountCode'  => $discCode,
            ':DiscountType'  => $discType,
            ':DiscountValue' => $discValue,
            ':DiscountAmount'=> $discAmount,
            ':FinalPrice'    => $finalPrice,
            ':PlanType'      => $planType,
            ':PlanMonths'    => $planMonths,
            ':MonthlyAmount' => $monthlyAmt,
            ':Status'        => $status,
            ':CreatedAt'     => $createdAt,
            ':ContractId'    => $contractId,
            ':LastModified'  => $incomingLastMysql,
        ]);

        // Update plot status/client link based on latest contract status
        $updatePlot->execute([
            ':Status'   => $plotStatus,
            ':ClientId' => $clientId,
            ':BuyerName'=> null,
            ':PlotId'   => $plotId,
        ]);

        $count++;
    }

    $pdo->commit();

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