<?php

$response = array();

require_once __DIR__ . '/catchexception.php';
require_once __DIR__ . '/db_config.php';
require_once __DIR__ . '/sales_payload_helper.php';
require_once __DIR__ . '/sales_insert_helper.php';
require_once __DIR__ . '/fcm_helper.php';

try {
    $devicecode = urldecode($_POST['paradevicecode'] ?? '');
    $imeino = urldecode($_POST['paraimeino'] ?? '');
    $salescount = urldecode($_POST['parasalescount'] ?? '1');
    $billdate = urldecode($_POST['parabilldate'] ?? '');

    if ($imeino === '' || $devicecode === '') {
        echo json_encode(array(
            'success' => 0,
            'message' => 'Required field(s) is missing',
        ));
        mch_db_release($con);
        exit;
    }

    try {
        $salesPayload = mch_normalize_sales_payload($_POST['salesarray'] ?? '');
        $salesItemPayload = mch_normalize_sales_payload($_POST['salesitem'] ?? '');
    } catch (InvalidArgumentException $e) {
        echo json_encode(array(
            'success' => 0,
            'message' => $e->getMessage(),
        ));
        mch_db_release($con);
        exit;
    }

    $salesRows = $salesPayload['JSonObject'] ?? array();
    $salesItemRows = $salesItemPayload['JSonObject'] ?? array();

    if (!is_array($salesRows) || count($salesRows) === 0) {
        echo json_encode(array(
            'success' => 0,
            'message' => 'Sales data is empty',
        ));
        mch_db_release($con);
        exit;
    }

    $branchMapping = mch_get_branch_mapping($con, $imeino);
    if ($branchMapping === null) {
        echo json_encode(array(
            'success' => 0,
            'message' => 'Device mapping not found',
        ));
        mch_db_release($con);
        exit;
    }

    if ($billdate === '' && !empty($salesRows[0]['transactiondate'])) {
        $billdate = $salesRows[0]['transactiondate'];
    }

    date_default_timezone_set('Australia/Melbourne');
    $syncDate = number_format(strtotime(date('Y-m-d H:i:s')) * 1000, 0, '.', '');

    pg_query($con, 'BEGIN');

    $nextNumbers = mch_get_next_sales_numbers($con, $imeino, $billdate);
    $transactionno = $nextNumbers['transactionno'];
    $voucherno = $nextNumbers['voucherno'];
    $sequenceno = $nextNumbers['sequenceno'];

    $logSql = "INSERT INTO tbluserlog(userid, originator, createdtime, \"Action\") VALUES ($1,$2,now(),$3) RETURNING autonum";
    $logRes = mch_pg_query_params($con, $logSql, array($devicecode, 'Insert Sales After Save', 'Insert'));
    $makerId = 0;
    if ($logRes && pg_num_rows($logRes) > 0) {
        $logRow = pg_fetch_row($logRes);
        $makerId = $logRow[0];
    }

    $sale = $salesRows[0];
    $sale['branchcode'] = mch_array_get($sale, 'branchcode', $branchMapping['branchcode']);
    $sale['devicecode'] = mch_array_get($sale, 'devicecode', $imeino);
    $sale['transactiondate'] = mch_array_get($sale, 'transactiondate', $billdate);

    $saleInsert = mch_insert_sale_record($con, $sale, $transactionno, $voucherno, $sequenceno, $makerId, $syncDate);
    if (mch_pg_query_failed($saleInsert)) {
        pg_query($con, 'ROLLBACK');
        echo json_encode(array(
            'success' => 0,
            'message' => 'Failed to insert sales record',
        ));
        mch_db_release($con);
        exit;
    }

    $insertedItems = 0;
    foreach ($salesItemRows as $item) {
        $item['branchcode'] = mch_array_get($item, 'branchcode', $sale['branchcode']);
        $item['devicecode'] = mch_array_get($item, 'devicecode', $imeino);
        $itemRes = mch_insert_sale_item_record(
            $con,
            $item,
            $transactionno,
            $voucherno,
            $sequenceno,
            $sale['transactiondate'],
            $syncDate
        );
        if (mch_pg_query_failed($itemRes)) {
            pg_query($con, 'ROLLBACK');
            echo json_encode(array(
                'success' => 0,
                'message' => 'Failed to insert sales item records',
            ));
            mch_db_release($con);
            exit;
        }
        $insertedItems++;
    }

    if ($insertedItems === 0) {
        pg_query($con, 'ROLLBACK');
        echo json_encode(array(
            'success' => 0,
            'message' => 'Failed to insert sales item records',
        ));
        mch_db_release($con);
        exit;
    }

    $syncDetailsSql = "INSERT INTO tblsyncdetails (imeino, syncdate, synctype, devicecode) VALUES ($1, now(), 'SalesAfterSave', $2)";
    $syncRes = mch_pg_query_params($con, $syncDetailsSql, array($imeino, $devicecode));
    if (mch_pg_query_failed($syncRes)) {
        pg_query($con, 'ROLLBACK');
        echo json_encode(array(
            'success' => 0,
            'message' => 'Failed to insert sync details',
        ));
        mch_db_release($con);
        exit;
    }

    $commitRes = pg_query($con, 'COMMIT');
    if (mch_pg_query_failed($commitRes)) {
        echo json_encode(array(
            'success' => 0,
            'message' => 'Failed to commit transaction',
        ));
        mch_db_release($con);
        exit;
    }

    $printJson = mch_build_print_json(
        $con,
        $transactionno,
        $voucherno,
        $imeino,
        $sale['branchcode']
    );
    $printJsonString = json_encode($printJson, JSON_UNESCAPED_UNICODE);

    $fcmToken = mch_get_device_fcm_token($con, $imeino);
    $notificationResult = array('success' => false, 'message' => 'No FCM token');
    if (!empty($fcmToken)) {
        $fcmData = array(
            'type' => 'sales_after_save',
            'transactionno' => (string)$transactionno,
            'voucherno' => (string)$voucherno,
            'grandtotal' => (string)mch_array_get($sale, 'grandtotal', '0'),
        );
        if ($printJsonString !== false && strlen($printJsonString) <= 3500) {
            $fcmData['printJson'] = $printJsonString;
        }
        $notificationResult = mch_send_fcm_notification(
            $fcmToken,
            'Sale Saved',
            'Bill #' . $voucherno . ' saved successfully',
            $fcmData,
            true
        );
    }

    $responsePayload = mch_build_sync_response($transactionno, $voucherno, 1);
    $responsePayload['success'] = 1;
    $responsePayload['message'] = 'Inserted successfully';
    $responsePayload['transactionno'] = (string)$transactionno;
    $responsePayload['voucherno'] = (string)$voucherno;
    $responsePayload['sequenceno'] = (string)$sequenceno;
    $responsePayload['printJson'] = $printJson;
    $responsePayload['notification'] = $notificationResult;

    echo json_encode($responsePayload, JSON_UNESCAPED_UNICODE);
    mch_db_release($con);
} catch (Exception $e) {
    if (isset($con) && $con) {
        @pg_query($con, 'ROLLBACK');
        mch_db_release($con);
    }
    echo json_encode(array(
        'success' => 0,
        'message' => $e->getMessage(),
    ));
}
