= '2023-01-01 00:00:00' AND invoices_details_has_how_pay.date_time < '2023-04-01 00:00:00' AND invoices_status_id = 1 AND invoices_details_has_how_pay.how_pay_id IN (1,2,3,4,5,6,7,8,9,10) SQL; $result = mysqli_query($db, $invoicesSumQuery); $sum = mysqli_fetch_assoc($result); if (!$sum) { die('sum could not be calculated'); } $sum = $sum['sum']; $bondsSumQuery = <<= '2023-01-01 00:00:00' AND bonds_details_has_how_pay.date_time < '2023-04-01 00:00:00' AND bonds_status_id = 1 AND branch_id IN (2,3,4,5,6,7,8,10,11,12) SQL; $result = mysqli_query($db, $bondsSumQuery); $sum = mysqli_fetch_assoc($result); if (!$sum) { die('sum could not be calculated'); } $sum = $sum['sum']; */ echo "
";

function inSubsetSum(array $a, float $t, array &$memo = []) : ?array {
    $s = array_reduce($memo, function (?float $carry, array $value) {
        return $carry + $value[1];
    });

    if ($s === $t) {
        return $memo;
    }

    if ($s >= $t) {
        return null;
    }

    $len = count($a);
    $keys = array_keys($a);
    for ($i = 0; $i < $len; ++$i) {
        $k = $keys[$i];
        $v = $a[$k];
        $rem = array_slice($a, $i + 1, null, true);
        $memo = array_merge($memo, [[$k, $v]]);
        $res = inSubsetSum($rem, $t, $memo);
        if ($res !== null) {
            return $res;
        }
    }

    return null;
}

function subsetSum(array $a, float $t) : ?array {
    $subset = inSubsetSum($a, $t);
    $result = [];
    foreach ($subset as $_ => [$k, $v]) {
        $result[$k] = $v;
    }
    return $result;
}

$invoiceQuery = <<= '2023-01-01 00:00:00' AND
        -- invoices_details_has_how_pay.date_time < '2023-04-01 00:00:00' AND
        invoices_status_id = 1 AND
        invoices_details.branch_id IN (2,3,4,5,6,7,8,10,11,12) AND
        invoices.id = 192501
    ORDER BY invoices_details_has_how_pay.date_time DESC
SQL;
$result = mysqli_query($db, $invoiceQuery);
$error = mysqli_error($db);
if ($error) {
    echo $error;
    die;
}
$invoiceData = mysqli_fetch_all($result, MYSQLI_ASSOC);
$invoiceDiscountQuery = << ['1501', 0],
    '3'  => ['0701', 0],
    '4'  => ['2901', 0],
    '5'  => ['0602', 0],
    '6'  => ['KM01', 0],
    '7'  => ['VS01', 0],
    '8'  => ['VS02', 0],
    '9'  => ['PT07', 0],
    '12' => ['2902', 0],
    '13' => ['1502', 0],
];

$countQuery = << ($precision - 1); --$i) {
        $val = round($val, $i);
    }
    return number_format($val, 2);
}

$bundleQuery = <<bind_param('i', $invoiceId);
    $stmt->execute();
    $error = mysqli_error($db);
    if ($error) {
        echo $error;
        die;
    }
    $result = $stmt->get_result();
    $result = mysqli_fetch_all($result, MYSQLI_ASSOC);
    if (count($result) == 0) {
        return 0.0;
    }
    return $result[0]['discount'];
}

function processInvoice(array &$data, int $serviceCount) : array {
    global $db;
    global $invoiceDiscountQuery;
    global $countQuery;
    global $year;
    global $letter;
    global $finalInvoiceData;
    global $branchData;

    $detailsId = $data['invoice_details_id'];
    $serviceId = $data['services_id'];
    $data['discount'] = 0;
    $stmt = mysqli_prepare($db, $invoiceDiscountQuery);
    $stmt->bind_param('ii', $serviceId, $detailsId);
    $stmt->execute();
    $error = mysqli_error($db);
    if ($error) {
        echo $error;
        die;
    }

    $result = $stmt->get_result();

    $discountData = mysqli_fetch_all($result, MYSQLI_ASSOC);

    $invoiceDiscounts = [];
    foreach ($discountData as &$discount) {
        // NOTE: this is for home visit services
        if ($discount['service_id'] == 0) {
            $countStmt = mysqli_prepare($db, $countQuery);
            $countStmt->bind_param('i', $data['invoices_id']);
            $countStmt->execute();
            $error = mysqli_error($db);
            if ($error) {
                echo $error;
                die;
            }
            $countResult = $countStmt->get_result();
            $countResult = mysqli_fetch_all($countResult, MYSQLI_ASSOC);
            $data['discount'] += $discount['total_discount'] / floatval($countResult[0]['count']);
            $discount['discount'] = $discount['total_discount'] / floatval($countResult[0]['count']);
        } else {
            $data['discount'] += $discount['discount'];
        }
        $invoiceDiscounts[] = [
            'reason' => $discount['reason'],
            'discount' => $discount['discount'],
        ];
    }

    $totalAfterDiscount = $data['price'] * $serviceCount - $data['discount'];
    $vat = $data['branch_id'] == 9 ? 0.0 : 15.0;
    $totalAfterDiscountVat = $totalAfterDiscount * ($vat / 100);

    $bData = &$branchData[$data['branch_id']];
    $branchCode = $bData[0];
    $bData[1] += 1;
    $invoiceNumber = $bData[1];
    $number = "{$year}{$letter}{$branchCode}";
    $number .= str_pad("$invoiceNumber", 7, '0', STR_PAD_LEFT);
    
    $total = $totalAfterDiscount + $totalAfterDiscountVat;
    $total = round($total, 2);
    if ($total <= $data['pay']) {
        $data['price_no_vat'] = roundMoney($data['price']);
        $data['total_discount'] = roundMoney($data['discount']);
        $data['total_after_discount'] = roundMoney($totalAfterDiscount);
        $data['vat'] = roundMoney($totalAfterDiscountVat);
        $total = $totalAfterDiscount + $totalAfterDiscountVat;
        $data['total'] = roundMoney($total);
    } else {
        echo ("WELCOME TO HELL");
        var_dump([
            'total' => $totalAfterDiscount + $totalAfterDiscountVat,
            'pay' => $data['pay'],
        ]);
        var_dump($data);
        die;
    }

    return [
        'branch_id' => $data['branch_id'],
        'invoices_id' => $data['invoices_id'],
        'book_id' => $data['book_id'],
        'tretment_id' => $data['tretment_id'],
        'number' => $number,
        'date_time' => $data['date_time'],
        'service_id' => $data['services_id'],
        'price_no_vat' => $data['price_no_vat'],
        'total_discount' => $data['total_discount'],
        'total_after_discount' => $data['total_after_discount'],
        'vat_rate' => $vat,
        'vat' => $data['vat'],
        'total' => $data['total'],
        'quantity' => $serviceCount,
        'how_pay_id' => $data['how_pay_id'],
        'discount_details' => $invoiceDiscounts,
    ];
}

$invoicesTotals = [];

foreach ($invoiceData as &$data) {
    // TODO: fix service bundles (where service_id == 0)
    if ($data['services_id'] == 0) {
        $stmt = mysqli_prepare($db, $bundleQuery);
        $stmt->bind_param('i', $data['book_id']);
        $stmt->execute();
        $result = $stmt->get_result();
        $bundleData = mysqli_fetch_all($result, MYSQLI_ASSOC);

        foreach ($bundleData as $bundle) {
            $c += 1;
            $d = $data;
            $serviceId = $bundle['services_id'];
            $count = $bundle['how_many'];
            $price = $bundle['price'];
            $d['services_id'] = $serviceId;
            $d['price'] = $price;
            $dd = processInvoice($d, $count);
            $id = $d['invoices_id'];
            $invoicesTotals["{$id}"]['total'] += $dd['total_discount'];
            $invoicesTotals["{$id}"]['service_count'] = $count;
            $invoicesTotals["{$id}"]['indices'][] = count($finalInvoiceData);
            $finalInvoiceData[] = $dd;
        }
    } else {
        $id = $data['invoices_id'];
        $dd = processInvoice($data, 1);
        $invoicesTotals["{$id}"]['total'] += $dd['total_discount'];
        $invoicesTotals["{$id}"]['service_count'] = 1;
        $invoicesTotals["{$id}"]['indices'][] = count($finalInvoiceData);
        $finalInvoiceData[] = $dd;
    }
}

foreach ($invoicesTotals as $id => $d) {
    $total = $d['total'];
    $indices = $d['indices'];
    $count = $d['service_count'];
    $originalTotal = getTotalDiscount($id);
    if ($originalTotal != $total) {
        $diff = bcsub($originalTotal, $total, 2);
        foreach ($indices as $index) {
            $total = $finalInvoiceData[$index]['total'];
            $mod = bcmod($total, 1, 2);
            if ($mod == $diff) {
                $discount = $finalInvoiceData[$index]['total_discount'];
                $discount += $diff;

                $price = $finalInvoiceData[$index]['price_no_vat'];
                $totalAfterDiscount = $price * $count - $discount;
                $totalAfterDiscountVat = $totalAfterDiscount * ($finalInvoiceData[$index]['vat_rate'] / 100);

                $totalAfterDiscount = roundMoney($price - $discount);
                $vat = roundMoney($totalAfterDiscountVat);
                $total = roundMoney($totalAfterDiscount + $totalAfterDiscountVat);


                $finalInvoiceData[$index]['total_discount'] = $discount;
                $finalInvoiceData[$index]['total_after_discount'] = $totalAfterDiscount;
                $finalInvoiceData[$index]['vat'] = $vat;
                $finalInvoiceData[$index]['total'] = $total;
                $discountDetails = $finalInvoiceData[$index]['discount_details'];
                if ($discountDetails && count($discountDetails) > 0) {
                    $discountDetails[0]['discount'] = $discount;
                    $finalInvoiceData[$index]['discount_details'] = $discountDetails;
                }
                break;
            } else {
                echo "WTH";
                die;
            }
        }
    }
}

var_dump($finalInvoiceData);
die;

$sum = 0.0;
$desired = 4695115.53;

$subset = [];

$reached_desired = false;

foreach ($invoiceData as &$data) {
    if ($sum == $desired) {
        $reached_desired = true;
        break;
    } else if ($sum < $desired) {
        $sum += $data['pay'];
        $subset[$key] = $bond;
        continue;
    }
    break;
}

$sahabiInvoicesTables = << $bond) {
    $bData = &$branchData[$bond['branch_id']];
    $branchCode = $bData[0];
    $bData[1] += 1;
    $invoiceNumber = $bData[1];
    $number = "{$year}{$letter}{$branchCode}";
    $number .= str_pad("$invoiceNumber", 7, '0', STR_PAD_LEFT);
    $noVat = $bond['pay'] / 1.15;
    $vat = $bond['pay'] - $noVat;

    $params = [
        $bond['bonds_id'],
        $bond['branch_id'],
        $bond['tretment_id'],
        $bond['bonds_type_type_id'],
        $number,
        $bond['date_time'],
        $noVat,
        $vat,
        $bond['pay'],
        $bond['how_pay_id'],
    ];

    $insertQuery = <<bind_param('ssiissdddi', ...$params);
    // $stmt->execute();
}

// $desired = 655476.19;
// $subset = subsetSum($bonds, $desired);
// echo "done";
//
// $subsetSum = array_sum($subset);

// echo "
subset sum: $subsetSum"; echo "
";