<?php

error_reporting(E_ALL);
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);

require_once __DIR__ . '/functions.php';


/* ============================================================
   DOCUMENT
   ============================================================ */

if (!isset($_GET['id'])) {
    die('Document ID missing');
}

$id = intval($_GET['id']);

$doc = getDocument($id);

if (!$doc) {
    die('Document not found');
}

$items = json_decode($doc['items'] ?? '[]', true);

if (!is_array($items)) {
    $items = [];
}


/* ============================================================
   COMPANY INFORMATION
   ============================================================ */

$companyName = 'ABIROS POWER VENTURES LTD';

$companyAddress =
    'P.O BOX 34998-00100, NAIROBI, KENYA';

$companyPhone =
    '070845689, 0705123059, 0706490308';

$companyPIN =
    'P052309662N';


/* ============================================================
   LOGO
   ============================================================ */

$logoPath = __DIR__ . '/logo.png';

if (!file_exists($logoPath)) {

    die(
        'Logo not found. Please upload logo.png into the same directory as pdf.php.'
    );
}

if (!function_exists('imagecreatefrompng')) {

    die(
        'PHP GD extension is required to process logo.png. Please enable GD in cPanel.'
    );
}

$logoImage = @imagecreatefrompng($logoPath);

if (!$logoImage) {

    die(
        'logo.png was found but could not be loaded. Please make sure it is a valid PNG image.'
    );
}

$logoWidth =
    imagesx($logoImage);

$logoHeight =
    imagesy($logoImage);


/* ============================================================
   PAYMENT DETAILS
   ============================================================ */

$bankDetails = [

    'Paybill' =>
        'Bn: 400200',

    'Account' =>
        'Acc: 01108959079800',

    'M-PESA Till' =>
        '9542241'
];


/* ============================================================
   DOCUMENT TYPE
   ============================================================ */

$docType =
    strtolower(
        $doc['doc_type'] ?? 'proforma'
    );

$titles = [

    'quotation' =>
        'QUOTATION',

    'proforma' =>
        'PROFORMA INVOICE',

    'invoice' =>
        'INVOICE',

    'receipt' =>
        'RECEIPT'
];

$documentTitle =
    $titles[$docType] ??
    'PROFORMA INVOICE';


/* ============================================================
   STATUS
   ============================================================ */

$status = '';

if ($docType === 'quotation') {

    $status = 'QUOTATION';

} elseif ($docType === 'proforma') {

    $status = 'PROFORMA';

} elseif ($docType === 'invoice') {

    $status = 'UNPAID';

} elseif ($docType === 'receipt') {

    $status = 'PAID';
}


/* ============================================================
   CUSTOMER
   ============================================================ */

$customerName =
    trim(
        $doc['customer_name'] ?? ''
    );

$customerAddress =
    trim(
        $doc['customer_address'] ?? ''
    );

$customerPhone =
    trim(
        $doc['customer_phone'] ?? ''
    );

$customerEmail =
    trim(
        $doc['customer_email'] ?? ''
    );


/* ============================================================
   DOCUMENT DETAILS
   ============================================================ */

$documentNumber =
    $doc['doc_number'] ?? '';

$documentDate = '';

if (!empty($doc['doc_date'])) {

    $timestamp =
        strtotime(
            $doc['doc_date']
        );

    if ($timestamp !== false) {

        $documentDate =
            date(
                'd M Y',
                $timestamp
            );
    }
}

$dueDate = '';

if (
    $docType === 'invoice' &&
    !empty($doc['doc_date'])
) {

    $timestamp =
        strtotime(
            $doc['doc_date']
        );

    if ($timestamp !== false) {

        $dueDate =
            date(
                'd M Y',
                strtotime(
                    '+30 days',
                    $timestamp
                )
            );
    }
}


/* ============================================================
   VAT
   ============================================================ */

$vatEnabled = false;

if (isset($doc['vat_enabled'])) {

    if (
        $doc['vat_enabled'] == 1 ||
        $doc['vat_enabled'] === true ||
        $doc['vat_enabled'] === '1'
    ) {

        $vatEnabled = true;
    }
}

if (
    !$vatEnabled &&
    isset($doc['vat_amount']) &&
    is_numeric($doc['vat_amount']) &&
    (float)$doc['vat_amount'] > 0
) {

    $vatEnabled = true;
}

$vatRate = 16;

if (
    isset($doc['vat_rate']) &&
    is_numeric($doc['vat_rate']) &&
    (float)$doc['vat_rate'] > 0
) {

    $vatRate =
        (float)$doc['vat_rate'];
}


/* ============================================================
   DISCOUNT
   ============================================================ */

$discount = 0;

if (
    isset($doc['discount']) &&
    is_numeric($doc['discount'])
) {

    $discount =
        (float)$doc['discount'];
}

if (
    isset($doc['discount_amount']) &&
    is_numeric($doc['discount_amount'])
) {

    $discount =
        (float)$doc['discount_amount'];
}

if ($discount < 0) {

    $discount = 0;
}


/* ============================================================
   PDF HELPER FUNCTIONS
   ============================================================ */

function pdf_escape($text)
{
    $text = (string)$text;

    $text = preg_replace(
        '/[\x00-\x08\x0B\x0C\x0E-\x1F]/',
        '',
        $text
    );

    $replace = [

        '–' => '-',
        '—' => '-',
        '’' => "'",
        '‘' => "'",
        '“' => '"',
        '”' => '"',
        '•' => '-',
        '…' => '...',
        '€' => 'EUR',
        '£' => 'GBP',
        '₦' => 'NGN',
        '→' => '->'
    ];

    $text =
        strtr(
            $text,
            $replace
        );

    $converted =
        @iconv(
            'UTF-8',
            'Windows-1252//TRANSLIT//IGNORE',
            $text
        );

    if ($converted !== false) {

        $text = $converted;
    }

    return str_replace(

        ['\\', '(', ')'],

        ['\\\\', '\\(', '\\)'],

        $text
    );
}


function pdf_text(
    $x,
    $y,
    $text,
    $size = 10,
    $font = '/F1',
    $color = '0 0 0'
) {

    return

        "BT\n" .

        $color .
        " rg\n" .

        $font .
        " " .
        $size .
        " Tf\n" .

        "1 0 0 1 " .
        $x .
        " " .
        $y .
        " Tm\n" .

        "(" .
        pdf_escape($text) .
        ") Tj\n" .

        "ET\n";
}


function pdf_line(
    $x1,
    $y1,
    $x2,
    $y2,
    $color = '0 0 0',
    $width = 1
) {

    return

        $color .
        " RG\n" .

        $width .
        " w\n" .

        $x1 .
        " " .
        $y1 .
        " m\n" .

        $x2 .
        " " .
        $y2 .
        " l\n" .

        "S\n";
}


function pdf_fill_rect(
    $x,
    $y,
    $w,
    $h,
    $color
) {

    return

        $color .
        " rg\n" .

        $x .
        " " .
        $y .
        " " .
        $w .
        " " .
        $h .
        " re\n" .

        "f\n";
}


function pdf_border_rect(
    $x,
    $y,
    $w,
    $h,
    $color = '0 0 0',
    $width = 1
) {

    return

        $color .
        " RG\n" .

        $width .
        " w\n" .

        $x .
        " " .
        $y .
        " " .
        $w .
        " " .
        $h .
        " re\n" .

        "S\n";
}


function money($amount)
{
    return number_format(
        (float)$amount,
        2
    );
}


function wrapText(
    $text,
    $maxCharacters
) {

    $text =
        trim(
            (string)$text
        );

    if ($text === '') {

        return [''];
    }

    $words =
        preg_split(
            '/\s+/',
            $text
        );

    $lines = [];

    $current = '';

    foreach ($words as $word) {

        if ($current === '') {

            $current = $word;

        } elseif (
            strlen(
                $current .
                ' ' .
                $word
            ) <= $maxCharacters
        ) {

            $current .=
                ' ' .
                $word;

        } else {

            $lines[] =
                $current;

            $current =
                $word;
        }
    }

    if ($current !== '') {

        $lines[] =
            $current;
    }

    return $lines;
}


/* ============================================================
   NUMBER TO WORDS
   ============================================================ */

function numberToWords($number)
{
    $number =
        round(
            (float)$number,
            2
        );

    $whole =
        floor($number);

    $decimal =
        round(
            ($number - $whole) * 100
        );

    $ones = [

        '',
        'One',
        'Two',
        'Three',
        'Four',
        'Five',
        'Six',
        'Seven',
        'Eight',
        'Nine',
        'Ten',
        'Eleven',
        'Twelve',
        'Thirteen',
        'Fourteen',
        'Fifteen',
        'Sixteen',
        'Seventeen',
        'Eighteen',
        'Nineteen'
    ];

    $tens = [

        '',
        '',
        'Twenty',
        'Thirty',
        'Forty',
        'Fifty',
        'Sixty',
        'Seventy',
        'Eighty',
        'Ninety'
    ];

    if ($whole == 0) {

        $words = 'Zero';

    } else {

        $words = '';

        if ($whole >= 1000000000) {

            $words .=

                numberToWords(
                    floor(
                        $whole /
                        1000000000
                    )
                ) .

                ' Billion ';

            $whole %=
                1000000000;
        }

        if ($whole >= 1000000) {

            $words .=

                numberToWords(
                    floor(
                        $whole /
                        1000000
                    )
                ) .

                ' Million ';

            $whole %=
                1000000;
        }

        if ($whole >= 1000) {

            $words .=

                numberToWords(
                    floor(
                        $whole /
                        1000
                    )
                ) .

                ' Thousand ';

            $whole %=
                1000;
        }

        if ($whole >= 100) {

            $words .=

                $ones[
                    floor(
                        $whole /
                        100
                    )
                ] .

                ' Hundred ';

            $whole %=
                100;
        }

        if ($whole >= 20) {

            $words .=

                $tens[
                    floor(
                        $whole /
                        10
                    )
                ] .

                ' ';

            $whole %=
                10;
        }

        if ($whole > 0) {

            $words .=
                $ones[$whole] .
                ' ';
        }

        $words =
            trim($words);
    }

    if ($decimal > 0) {

        return

            $words .
            ' Kenya Shillings and ' .
            str_pad(
                $decimal,
                2,
                '0',
                STR_PAD_LEFT
            ) .
            ' Cents Only';
    }

    return

        $words .
        ' Kenya Shillings Only';
}


/* ============================================================
   PNG TO PDF RGB
   ============================================================ */

function pngToPdfImage($image)
{
    $width =
        imagesx($image);

    $height =
        imagesy($image);

    $raw = '';

    for (
        $y = 0;
        $y < $height;
        $y++
    ) {

        /*
         * PNG predictor byte.
         */

        $raw .= "\x00";

        for (
            $x = 0;
            $x < $width;
            $x++
        ) {

            $rgba =
                imagecolorat(
                    $image,
                    $x,
                    $y
                );

            $r =
                ($rgba >> 16) &
                0xFF;

            $g =
                ($rgba >> 8) &
                0xFF;

            $b =
                $rgba &
                0xFF;

            /*
             * Transparency.
             */

            $alpha =
                ($rgba &
                0x7F000000) >>
                24;

            if ($alpha > 0) {

                $opacity =
                    1 -
                    (
                        $alpha /
                        127
                    );

                $r =
                    (int)(
                        255 -
                        (
                            255 -
                            $r
                        ) *
                        $opacity
                    );

                $g =
                    (int)(
                        255 -
                        (
                            255 -
                            $g
                        ) *
                        $opacity
                    );

                $b =
                    (int)(
                        255 -
                        (
                            255 -
                            $b
                        ) *
                        $opacity
                    );
            }

            $raw .=
                chr($r) .
                chr($g) .
                chr($b);
        }
    }

    return gzcompress(
        $raw,
        9
    );
}


/* ============================================================
   CALCULATE TOTALS
   ============================================================ */

$subtotal = 0;

foreach (
    $items
    as $item
) {

    $qty =
        floatval(
            $item['quantity'] ?? 0
        );

    $price =
        floatval(
            $item['unit_price'] ?? 0
        );

    $subtotal +=
        $qty *
        $price;
}


$discount =
    min(
        $discount,
        $subtotal
    );


$taxableAmount =
    max(
        0,
        $subtotal -
        $discount
    );


$vatAmount = 0;

if ($vatEnabled) {

    $vatAmount =
        $taxableAmount *
        (
            $vatRate /
            100
        );
}


if (
    $vatEnabled &&
    isset($doc['vat_amount']) &&
    is_numeric($doc['vat_amount'])
) {

    $savedVat =
        (float)$doc['vat_amount'];

    if ($savedVat >= 0) {

        $vatAmount =
            $savedVat;
    }
}


$grandTotal =
    $taxableAmount +
    $vatAmount;


/* ============================================================
   PAGE SETTINGS
   ============================================================ */

$pageWidth = 595;

$pageHeight = 842;

$margin = 42;

$contentPages = [];

$currentContent = '';


/* ============================================================
   HEADER
   ============================================================ */

function drawHeader(
    &$content,
    $pageWidth,
    $pageHeight,
    $margin,
    $companyName,
    $companyAddress,
    $companyPhone,
    $companyPIN,
    $documentTitle,
    $documentNumber,
    $status,
    $logoWidth,
    $logoHeight
) {

    /*
     * Larger logo.
     */

    $maxLogoWidth =
        105;

    $maxLogoHeight =
        72;

    $scaleX =
        $maxLogoWidth /
        $logoWidth;

    $scaleY =
        $maxLogoHeight /
        $logoHeight;

    $scale =
        min(
            $scaleX,
            $scaleY
        );

    $drawWidth =
        $logoWidth *
        $scale;

    $drawHeight =
        $logoHeight *
        $scale;


    /*
     * Logo – centered horizontally.
     */

    $logoX =
        ($pageWidth - $drawWidth) / 2;

    $logoY =
        $pageHeight -
        30 -
        $drawHeight;

    $content .=

        "q\n" .

        $drawWidth .
        " 0 0 " .
        $drawHeight .
        " " .
        $logoX .
        " " .
        $logoY .
        " cm\n" .

        "/Im1 Do\n" .

        "Q\n";


    /*
     * Company name – centered.
     * Approximate center: we set x to 185 (about half of page width minus text width).
     * The text is 15pt bold, ~9pt per character, 25 chars => ~225pt, so 595/2 - 225/2 ≈ 185.
     */

    $companyX =
        185;

    $content .= pdf_text(
        $companyX,
        $pageHeight - 30,
        $companyName,
        15,
        '/F2',
        '0.06 0.08 0.14'
    );


    /*
     * Address details – left‑aligned (where the logo used to be).
     */

    $addressX =
        $margin;

    $content .= pdf_text(
        $addressX,
        $pageHeight - 46,
        $companyAddress,
        7.2,
        '/F1',
        '0.38 0.40 0.45'
    );

    $content .= pdf_text(
        $addressX,
        $pageHeight - 58,
        'TEL: ' .
        $companyPhone,
        7.2,
        '/F1',
        '0.38 0.40 0.45'
    );

    $content .= pdf_text(
        $addressX,
        $pageHeight - 70,
        'PIN: ' .
        $companyPIN,
        7.2,
        '/F1',
        '0.38 0.40 0.45'
    );


    /*
     * Document title – removed to avoid overlap.
     * (The line is commented out.)
     */
    // $content .= pdf_text(
    //     390,
    //     $pageHeight - 36,
    //     $documentTitle,
    //     15,
    //     '/F2',
    //     '0.06 0.08 0.14'
    // );


    /*
     * Document number – right side.
     */

    $content .= pdf_text(
        390,
        $pageHeight - 51,
        'No: ' .
        $documentNumber,
        7.5,
        '/F1',
        '0.38 0.40 0.45'
    );


    /*
     * Status badge – right side, below document number.
     */

    if ($status !== '') {

        $content .=
            pdf_fill_rect(
                390,
                $pageHeight - 78,
                90,
                16,
                '0.90 0.93 0.98'
            );

        $content .=
            pdf_text(
                401,
                $pageHeight - 72,
                $status,
                7,
                '/F2',
                '0.05 0.20 0.55'
            );
    }


    /*
     * Header separator.
     */

    $content .=
        pdf_line(
            $margin,
            $pageHeight - 94,
            $pageWidth - $margin,
            $pageHeight - 94,
            '0.78 0.80 0.84',
            0.7
        );
}


/* ============================================================
   TABLE HEADER
   ============================================================ */

function drawTableHeader(
    &$content,
    $tableX,
    $tableWidth,
    $tableTop,
    $colItem,
    $colDescription,
    $colQty,
    $colPrice,
    $colTotal
) {

    $headerHeight = 25;

    $content .=
        pdf_fill_rect(
            $tableX,
            $tableTop -
            $headerHeight,
            $tableWidth,
            $headerHeight,
            '0.07 0.10 0.17'
        );


    $content .=
        pdf_text(
            $colItem + 7,
            $tableTop - 17,
            '#',
            8,
            '/F2',
            '1 1 1'
        );


    $content .=
        pdf_text(
            $colDescription + 7,
            $tableTop - 17,
            'DESCRIPTION',
            8,
            '/F2',
            '1 1 1'
        );


    $content .=
        pdf_text(
            $colQty + 5,
            $tableTop - 17,
            'QTY',
            8,
            '/F2',
            '1 1 1'
        );


    $content .=
        pdf_text(
            $colPrice + 2,
            $tableTop - 17,
            'UNIT PRICE',
            7,
            '/F2',
            '1 1 1'
        );


    $content .=
        pdf_text(
            $colTotal + 2,
            $tableTop - 17,
            'TOTAL',
            8,
            '/F2',
            '1 1 1'
        );


    return
        $tableTop -
        $headerHeight;
}


/* ============================================================
   FIRST PAGE HEADER
   ============================================================ */

drawHeader(
    $currentContent,
    $pageWidth,
    $pageHeight,
    $margin,
    $companyName,
    $companyAddress,
    $companyPhone,
    $companyPIN,
    $documentTitle,
    $documentNumber,
    $status,
    $logoWidth,
    $logoHeight
);


/* ============================================================
   CUSTOMER INFORMATION
   ============================================================ */

$infoTop =
    $pageHeight -
    122;


/*
 * BILL TO BOX
 */

$currentContent .=
    pdf_fill_rect(
        $margin,
        $infoTop - 72,
        275,
        72,
        '0.97 0.98 0.99'
    );


$currentContent .=
    pdf_border_rect(
        $margin,
        $infoTop - 72,
        275,
        72,
        '0.84 0.85 0.88',
        0.5
    );


$currentContent .=
    pdf_text(
        $margin + 12,
        $infoTop - 17,
        'BILL TO',
        8,
        '/F2',
        '0.06 0.08 0.14'
    );


$currentContent .=
    pdf_text(
        $margin + 12,
        $infoTop - 33,
        $customerName,
        10,
        '/F2',
        '0.12 0.14 0.18'
    );


$customerY =
    $infoTop - 47;


$customerLines =
    wrapText(
        $customerAddress,
        45
    );


foreach (
    $customerLines
    as $line
) {

    if ($line === '') {
        continue;
    }

    $currentContent .=
        pdf_text(
            $margin + 12,
            $customerY,
            $line,
            7.3,
            '/F1',
            '0.38 0.40 0.45'
        );

    $customerY -= 10;
}


if ($customerPhone !== '') {

    $currentContent .=
        pdf_text(
            $margin + 12,
            $customerY,
            'Phone: ' .
            $customerPhone,
            7.3,
            '/F1',
            '0.38 0.40 0.45'
        );

    $customerY -= 10;
}


if ($customerEmail !== '') {

    $currentContent .=
        pdf_text(
            $margin + 12,
            $customerY,
            'Email: ' .
            $customerEmail,
            7.3,
            '/F1',
            '0.38 0.40 0.45'
        );
}


/*
 * DOCUMENT DETAILS BOX
 */

$detailsX =
    335;


$currentContent .=
    pdf_fill_rect(
        $detailsX,
        $infoTop - 72,
        218,
        72,
        '0.97 0.98 0.99'
    );


$currentContent .=
    pdf_border_rect(
        $detailsX,
        $infoTop - 72,
        218,
        72,
        '0.84 0.85 0.88',
        0.5
    );


$currentContent .=
    pdf_text(
        $detailsX + 12,
        $infoTop - 17,
        'DOCUMENT DETAILS',
        8,
        '/F2',
        '0.06 0.08 0.14'
    );


$currentContent .=
    pdf_text(
        $detailsX + 12,
        $infoTop - 34,
        'Document No.',
        7.3,
        '/F1',
        '0.40 0.42 0.47'
    );


$currentContent .=
    pdf_text(
        $detailsX + 100,
        $infoTop - 34,
        $documentNumber,
        7.3,
        '/F2',
        '0.12 0.14 0.18'
    );


$currentContent .=
    pdf_text(
        $detailsX + 12,
        $infoTop - 49,
        'Date',
        7.3,
        '/F1',
        '0.40 0.42 0.47'
    );


$currentContent .=
    pdf_text(
        $detailsX + 100,
        $infoTop - 49,
        $documentDate,
        7.3,
        '/F2',
        '0.12 0.14 0.18'
    );


if ($dueDate !== '') {

    $currentContent .=
        pdf_text(
            $detailsX + 12,
            $infoTop - 64,
            'Due Date',
            7.3,
            '/F1',
            '0.40 0.42 0.47'
        );


    $currentContent .=
        pdf_text(
            $detailsX + 100,
            $infoTop - 64,
            $dueDate,
            7.3,
            '/F2',
            '0.12 0.14 0.18'
        );
}


/* ============================================================
   TABLE
   ============================================================ */

$tableX =
    $margin;


$tableWidth =
    $pageWidth -
    ($margin * 2);


$colItem =
    $tableX;


$colDescription =
    $tableX + 45;


$colQty =
    $tableX + 335;


$colPrice =
    $tableX + 400;


$colTotal =
    $tableX + 480;


$tableTop =
    $infoTop -
    94;


$rowY =
    drawTableHeader(
        $currentContent,
        $tableX,
        $tableWidth,
        $tableTop,
        $colItem,
        $colDescription,
        $colQty,
        $colPrice,
        $colTotal
    );


/* ============================================================
   TABLE ITEMS
   ============================================================ */

$rowHeight = 32;

$itemNo = 1;


foreach (
    $items
    as $item
) {

    if ($rowY < 150) {

        $contentPages[] =
            $currentContent;

        $currentContent = '';


        drawHeader(
            $currentContent,
            $pageWidth,
            $pageHeight,
            $margin,
            $companyName,
            $companyAddress,
            $companyPhone,
            $companyPIN,
            $documentTitle,
            $documentNumber,
            $status,
            $logoWidth,
            $logoHeight
        );


        $newTableTop =
            $pageHeight -
            115;


        $rowY =
            drawTableHeader(
                $currentContent,
                $tableX,
                $tableWidth,
                $newTableTop,
                $colItem,
                $colDescription,
                $colQty,
                $colPrice,
                $colTotal
            );
    }


    $qty =
        floatval(
            $item['quantity'] ?? 0
        );


    $price =
        floatval(
            $item['unit_price'] ?? 0
        );


    $amount =
        $qty *
        $price;


    $description =
        preg_replace(
            '/\s+/',
            ' ',
            trim(
                $item['description'] ?? ''
            )
        );


    $descriptionLines =
        wrapText(
            $description,
            42
        );


    if (
        count($descriptionLines) > 2
    ) {

        $descriptionLines =
            array_slice(
                $descriptionLines,
                0,
                2
            );

        $last =
            count(
                $descriptionLines
            ) - 1;

        $descriptionLines[$last] =
            substr(
                $descriptionLines[$last],
                0,
                38
            ) .
            '...';
    }


    if (
        $itemNo % 2 === 0
    ) {

        $currentContent .=
            pdf_fill_rect(
                $tableX,
                $rowY -
                $rowHeight,
                $tableWidth,
                $rowHeight,
                '0.975 0.977 0.982'
            );
    }


    $currentContent .=
        pdf_line(
            $tableX,
            $rowY -
            $rowHeight,
            $tableX +
            $tableWidth,
            $rowY -
            $rowHeight,
            '0.86 0.87 0.90',
            0.4
        );


    $currentContent .=
        pdf_text(
            $colItem + 8,
            $rowY - 19,
            $itemNo,
            8,
            '/F1',
            '0.20 0.22 0.27'
        );


    $descriptionY =
        $rowY - 14;


    foreach (
        $descriptionLines
        as $line
    ) {

        $currentContent .=
            pdf_text(
                $colDescription + 7,
                $descriptionY,
                $line,
                7.8,
                '/F1',
                '0.12 0.14 0.18'
            );

        $descriptionY -= 10;
    }


    $currentContent .=
        pdf_text(
            $colQty + 4,
            $rowY - 19,
            number_format(
                $qty,
                2
            ),
            7.8,
            '/F1',
            '0.20 0.22 0.27'
        );


    $currentContent .=
        pdf_text(
            $colPrice + 2,
            $rowY - 19,
            money($price),
            7.8,
            '/F1',
            '0.20 0.22 0.27'
        );


    $currentContent .=
        pdf_text(
            $colTotal + 2,
            $rowY - 19,
            money($amount),
            7.8,
            '/F2',
            '0.08 0.10 0.15'
        );


    $rowY -=
        $rowHeight;

    $itemNo++;
}


/* ============================================================
   TOTALS
   ============================================================ */

if ($rowY < 300) {

    $contentPages[] =
        $currentContent;

    $currentContent = '';


    drawHeader(
        $currentContent,
        $pageWidth,
        $pageHeight,
        $margin,
        $companyName,
        $companyAddress,
        $companyPhone,
        $companyPIN,
        $documentTitle,
        $documentNumber,
        $status,
        $logoWidth,
        $logoHeight
    );


    $totalsTop =
        $pageHeight -
        120;

} else {

    $totalsTop =
        $rowY - 20;
}


/* ============================================================
   AMOUNT IN WORDS
   ============================================================ */

$currentContent .=
    pdf_text(
        $margin,
        $totalsTop,
        'AMOUNT IN WORDS',
        7,
        '/F2',
        '0.40 0.42 0.47'
    );


$amountWords =
    numberToWords(
        $grandTotal
    );


$amountWordLines =
    wrapText(
        $amountWords,
        65
    );


$wordsY =
    $totalsTop -
    15;


foreach (
    $amountWordLines
    as $line
) {

    $currentContent .=
        pdf_text(
            $margin,
            $wordsY,
            $line,
            8,
            '/F1',
            '0.12 0.14 0.18'
        );

    $wordsY -= 11;
}


/* ============================================================
   TOTAL BOX
   ============================================================ */

$boxX =
    355;

$boxWidth =
    200;

$boxTop =
    $totalsTop;

$boxHeight =
    140;


$currentContent .=
    pdf_border_rect(
        $boxX,
        $boxTop -
        $boxHeight,
        $boxWidth,
        $boxHeight,
        '0.82 0.83 0.87',
        0.6
    );


$totalY =
    $boxTop -
    20;


/*
 * SUBTOTAL
 */

$currentContent .=
    pdf_text(
        $boxX + 12,
        $totalY,
        'Subtotal',
        8,
        '/F1',
        '0.35 0.37 0.42'
    );


$currentContent .=
    pdf_text(
        $boxX + 120,
        $totalY,
        'KES ' .
        money($subtotal),
        8,
        '/F1',
        '0.15 0.17 0.21'
    );


$totalY -= 18;


/*
 * DISCOUNT
 */

if ($discount > 0) {

    $currentContent .=
        pdf_text(
            $boxX + 12,
            $totalY,
            'Discount',
            8,
            '/F1',
            '0.35 0.37 0.42'
        );


    $currentContent .=
        pdf_text(
            $boxX + 120,
            $totalY,
            '- KES ' .
            money($discount),
            8,
            '/F1',
            '0.65 0.15 0.15'
        );


    $totalY -= 18;
}


/*
 * TAXABLE AMOUNT
 */

if ($discount > 0) {

    $currentContent .=
        pdf_text(
            $boxX + 12,
            $totalY,
            'Taxable Amount',
            8,
            '/F1',
            '0.35 0.37 0.42'
        );


    $currentContent .=
        pdf_text(
            $boxX + 120,
            $totalY,
            'KES ' .
            money($taxableAmount),
            8,
            '/F1',
            '0.15 0.17 0.21'
        );


    $totalY -= 18;
}


/*
 * VAT
 */

if ($vatEnabled) {

    $currentContent .=
        pdf_text(
            $boxX + 12,
            $totalY,
            'VAT (' .
            money($vatRate) .
            '%)',
            8,
            '/F1',
            '0.35 0.37 0.42'
        );


    $currentContent .=
        pdf_text(
            $boxX + 120,
            $totalY,
            'KES ' .
            money($vatAmount),
            8,
            '/F1',
            '0.15 0.17 0.21'
        );


    $totalY -= 18;
}


/*
 * GRAND TOTAL
 */

$currentContent .=
    pdf_line(
        $boxX + 10,
        $totalY + 7,
        $boxX +
        $boxWidth -
        10,
        $totalY + 7,
        '0.65 0.67 0.70',
        0.5
    );


$currentContent .=
    pdf_fill_rect(
        $boxX,
        $totalY - 34,
        $boxWidth,
        34,
        '0.07 0.10 0.17'
    );


$currentContent .=
    pdf_text(
        $boxX + 12,
        $totalY - 21,
        'GRAND TOTAL',
        9,
        '/F2',
        '1 1 1'
    );


$currentContent .=
    pdf_text(
        $boxX + 105,
        $totalY - 21,
        'KES ' .
        money($grandTotal),
        10,
        '/F2',
        '1 1 1'
    );


/* ============================================================
   PAYMENT DETAILS
   ============================================================ */

$paymentY =
    min(
        $wordsY - 25,
        $totalY - 60
    );


$currentContent .=
    pdf_text(
        $margin,
        $paymentY,
        'PAYMENT DETAILS',
        9,
        '/F2',
        '0.06 0.08 0.14'
    );


$paymentY -= 16;


foreach (
    $bankDetails
    as $label =>
    $value
) {

    $currentContent .=
        pdf_text(
            $margin,
            $paymentY,
            $label . ':',
            7.5,
            '/F2',
            '0.35 0.37 0.42'
        );


    $currentContent .=
        pdf_text(
            $margin + 85,
            $paymentY,
            $value,
            7.5,
            '/F1',
            '0.20 0.22 0.26'
        );


    $paymentY -= 12;
}


/* ============================================================
   NOTES
   ============================================================ */

$notesY =
    $paymentY -
    12;


$currentContent .=
    pdf_text(
        $margin,
        $notesY,
        'NOTES & TERMS',
        9,
        '/F2',
        '0.06 0.08 0.14'
    );


$notesY -= 15;


$notes = [

    'Prices are subject to change anytime without prior notice.',

    'Goods and services are subject to availability and agreed terms.'
];


if ($docType === 'proforma') {

    $notes[] =
        'This document is a proforma invoice and is not a tax invoice.';
}


if ($docType === 'quotation') {

    $notes[] =
        'This quotation is subject to the agreed quotation terms.';
}


if ($docType === 'invoice') {

    $notes[] =
        'Payment is due within the agreed payment period.';
}


if ($docType === 'receipt') {

    $notes = [

        'This receipt acknowledges payment received.',

        'Thank you for your business.'
    ];
}


foreach (
    $notes
    as $note
) {

    $currentContent .=
        pdf_text(
            $margin,
            $notesY,
            '- ' .
            $note,
            7.2,
            '/F1',
            '0.38 0.40 0.45'
        );

    $notesY -= 11;
}


/* ============================================================
   SIGNATURES
   ============================================================ */

$signatureY =
    max(
        95,
        $notesY - 30
    );


$currentContent .=
    pdf_line(
        $margin,
        $signatureY,
        $margin + 155,
        $signatureY,
        '0.45 0.47 0.50',
        0.6
    );


$currentContent .=
    pdf_text(
        $margin,
        $signatureY - 14,
        'Authorized By',
        7,
        '/F1',
        '0.40 0.42 0.47'
    );


$currentContent .=
    pdf_line(
        370,
        $signatureY,
        530,
        $signatureY,
        '0.45 0.47 0.50',
        0.6
    );


$currentContent .=
    pdf_text(
        370,
        $signatureY - 14,
        'Customer Signature',
        7,
        '/F1',
        '0.40 0.42 0.47'
    );


/* ============================================================
   SAVE LAST PAGE
   ============================================================ */

$contentPages[] =
    $currentContent;


/* ============================================================
   FOOTERS
   ============================================================ */

$totalPages =
    count($contentPages);


for (
    $i = 0;
    $i < $totalPages;
    $i++
) {

    $footer = '';


    $footer .=
        pdf_line(
            $margin,
            55,
            $pageWidth - $margin,
            55,
            '0.82 0.83 0.86',
            0.5
        );


    $footer .=
        pdf_text(
            $margin,
            40,
            $companyName .
            ' | TEL: ' .
            $companyPhone .
            ' | PIN: ' .
            $companyPIN,
            7,
            '/F1',
            '0.45 0.47 0.52'
        );


    $footer .=
        pdf_text(
            $pageWidth - 105,
            40,
            'Page ' .
            ($i + 1) .
            ' of ' .
            $totalPages,
            7,
            '/F1',
            '0.45 0.47 0.52'
        );


    $contentPages[$i] .=
        $footer;
}


/* ============================================================
   PDF OBJECTS
   ============================================================ */

$objects = [];


/*
 * Catalog
 */

$objects[] =
    "<< /Type /Catalog /Pages 2 0 R >>";


/*
 * Pages placeholder
 */

$objects[] =
    '';


/*
 * Helvetica
 */

$objects[] =
    "<< " .
    "/Type /Font " .
    "/Subtype /Type1 " .
    "/BaseFont /Helvetica " .
    ">>";


/*
 * Helvetica Bold
 */

$objects[] =
    "<< " .
    "/Type /Font " .
    "/Subtype /Type1 " .
    "/BaseFont /Helvetica-Bold " .
    ">>";


/* ============================================================
   EMBED LOGO
   ============================================================ */

$compressedLogo =
    pngToPdfImage(
        $logoImage
    );


imagedestroy(
    $logoImage
);


$logoObjectNumber =
    count($objects) + 1;


$objects[] =

    "<< " .

    "/Type /XObject " .

    "/Subtype /Image " .

    "/Width " .
    $logoWidth .
    " " .

    "/Height " .
    $logoHeight .
    " " .

    "/ColorSpace /DeviceRGB " .

    "/BitsPerComponent 8 " .

    "/Filter /FlateDecode " .

    "/DecodeParms << " .

    "/Predictor 12 " .

    "/Colors 3 " .

    "/BitsPerComponent 8 " .

    "/Columns " .
    $logoWidth .

    " >> " .

    "/Length " .
    strlen($compressedLogo) .

    " >>\n" .

    "stream\n" .

    $compressedLogo .

    "\nendstream";


/* ============================================================
   PAGE OBJECTS
   ============================================================ */

$pageObjectNumbers = [];


foreach (
    $contentPages
    as $pageContent
) {

    /*
     * Content object
     */

    $contentObjectNumber =
        count($objects) + 1;


    $objects[] =

        "<< /Length " .
        strlen($pageContent) .
        " >>\n" .

        "stream\n" .

        $pageContent .

        "\nendstream";


    /*
     * Page object
     */

    $pageObjectNumber =
        count($objects) + 1;


    /*
     * Page resources.
     */

    $resources =

        "<< " .

        "/Font << " .

        "/F1 3 0 R " .

        "/F2 4 0 R " .

        ">> " .

        "/XObject << " .

        "/Im1 " .
        $logoObjectNumber .
        " 0 R " .

        ">> " .

        ">>";


    $objects[] =

        "<< " .

        "/Type /Page " .

        "/Parent 2 0 R " .

        "/MediaBox [0 0 595 842] " .

        "/Resources " .
        $resources .
        " " .

        "/Contents " .
        $contentObjectNumber .
        " 0 R " .

        ">>";


    $pageObjectNumbers[] =
        $pageObjectNumber;
}


/* ============================================================
   PAGES OBJECT
   ============================================================ */

$kids = '';

foreach (
    $pageObjectNumbers
    as $pageObjectNumber
) {

    $kids .=
        $pageObjectNumber .
        " 0 R ";
}


$objects[1] =

    "<< " .

    "/Type /Pages " .

    "/Kids [" .
    trim($kids) .
    "] " .

    "/Count " .
    count($pageObjectNumbers) .

    " >>";


/* ============================================================
   BUILD PDF
   ============================================================ */

$pdf =
    "%PDF-1.4\n";


$offsets = [];


foreach (
    $objects
    as $index =>
    $object
) {

    $objectNumber =
        $index + 1;


    $offsets[$objectNumber] =
        strlen($pdf);


    $pdf .=

        $objectNumber .
        " 0 obj\n" .

        $object .

        "\nendobj\n";
}


/* ============================================================
   XREF
   ============================================================ */

$xrefPosition =
    strlen($pdf);


$pdf .=

    "xref\n" .

    "0 " .
    (count($objects) + 1) .
    "\n" .

    "0000000000 65535 f \n";


foreach (
    $offsets
    as $offset
) {

    $pdf .= sprintf(
        "%010d 00000 n \n",
        $offset
    );
}


/* ============================================================
   TRAILER
   ============================================================ */

$pdf .=

    "trailer\n" .

    "<< " .

    "/Size " .
    (count($objects) + 1) .

    " " .

    "/Root 1 0 R " .

    ">>\n" .

    "startxref\n" .

    $xrefPosition .

    "\n" .

    "%%EOF";


/* ============================================================
   OUTPUT PDF
   ============================================================ */

while (
    ob_get_level()
) {

    ob_end_clean();
}


$filename =
    preg_replace(
        '/[^A-Za-z0-9_\-]/',
        '_',
        $documentNumber
        ?: 'document'
    );


$filename .=
    '.pdf';


header(
    'Content-Type: application/pdf'
);


header(
    'Content-Disposition: attachment; filename="' .
    $filename .
    '"'
);


header(
    'Content-Length: ' .
    strlen($pdf)
);


header(
    'Cache-Control: private, max-age=0, must-revalidate'
);


header(
    'Pragma: public'
);


echo $pdf;

exit;

?>