<?php
require('fpdf.php');

if (session_status() === PHP_SESSION_NONE) {
    session_start();
}

require_once __DIR__ . '/../../includes/bootstrap.php';
require_login();

$paymentId = (int)($_GET['payment_id'] ?? 0);
$orderId   = (int)($_GET['order_id'] ?? 0);

if ($orderId <= 0) {
    exit('Missing order id');
}

/* -----------------------------
   Helpers
----------------------------- */
function pdf_txt($text)
{
    $text = (string)$text;
    return iconv('UTF-8', 'ISO-8859-1//TRANSLIT', $text);
}

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

function safe_date_fmt_pdf($date, $format = 'd M Y')
{
    if (!$date) return '';
    $ts = strtotime($date);
    return $ts ? date($format, $ts) : $date;
}


function receipt_column_exists(PDO $pdo, string $tableName, string $columnName): bool
{
    static $cache = [];
    $key = $tableName . '.' . $columnName;

    if (array_key_exists($key, $cache)) {
        return $cache[$key];
    }

    try {
        $stmt = $pdo->prepare("
            SELECT COUNT(*)
            FROM INFORMATION_SCHEMA.COLUMNS
            WHERE TABLE_SCHEMA = DATABASE()
              AND TABLE_NAME = :table_name
              AND COLUMN_NAME = :column_name
        ");
        $stmt->execute([
            ':table_name' => $tableName,
            ':column_name' => $columnName,
        ]);
        $cache[$key] = ((int)$stmt->fetchColumn() > 0);
    } catch (Throwable $e) {
        $cache[$key] = false;
    }

    return $cache[$key];
}

function receipt_folio_label(array $folio): string
{
    $type = strtolower(trim((string)($folio['folio_type'] ?? '')));
    $roomNo = trim((string)($folio['room_no'] ?? ''));
    $roomType = trim((string)($folio['room_type_title'] ?? ''));
    $occupantName = trim((string)($folio['occupant_name'] ?? ''));
    $folioName = trim((string)($folio['folio_name'] ?? ''));

    if ($type === 'master') {
        return 'Master Folio';
    }

    if ($type === 'room') {
        $label = 'Room Folio';
        if ($roomNo !== '') {
            $label .= ' - Room ' . $roomNo;
        }
        if ($roomType !== '') {
            $label .= ' • ' . $roomType;
        }
        return $label;
    }

    if ($type === 'guest') {
        $label = 'Guest Folio';
        if ($occupantName !== '') {
            $label .= ' - ' . $occupantName;
        } elseif ($folioName !== '') {
            $label .= ' - ' . $folioName;
        }
        if ($roomNo !== '') {
            $label .= ' / Room ' . $roomNo;
        }
        if ($roomType !== '') {
            $label .= ' • ' . $roomType;
        }
        return $label;
    }

    return $folioName !== '' ? $folioName : 'Booking Folio';
}

/* -----------------------------
   Load booking first
----------------------------- */
$stmt = $pdo->prepare("
    SELECT
        o.*,
        g.firstname,
        g.lastname,
        p.name AS property_name,
        p.code AS property_code,
        p.currency_code AS property_currency_code,
        CONCAT(COALESCE(a.firstname,''), ' ') AS agent_name
    FROM orders o
    LEFT JOIN guests g ON g.id = o.guest_id
    LEFT JOIN properties p ON p.id = o.property_id
    LEFT JOIN agents a ON a.id = o.agent_id
    WHERE o.id = :id
    LIMIT 1
");
$stmt->execute([':id' => $orderId]);
$order = $stmt->fetch(PDO::FETCH_ASSOC);

if (!$order) {
    exit('Booking not found');
}

$propertyId = (int)($order['property_id'] ?? 0);
$folioOccupantSelect = receipt_column_exists($pdo, 'folios', 'occupant_name') ? 'f.occupant_name' : 'NULL';

/* -----------------------------
   Real room mix from order_rooming
----------------------------- */
$roomMix = '';
$roomMixRows = [];

try {
    $stmt = $pdo->prepare("
        SELECT
            rmg.room_type_id,
            rt.title AS room_type_title,
            COUNT(*) AS qty_rooms
        FROM order_rooming rmg
        INNER JOIN room_types rt ON rt.id = rmg.room_type_id
        WHERE rmg.order_id = :order_id
        GROUP BY rmg.room_type_id, rt.title
        ORDER BY rt.title ASC
    ");
    $stmt->execute([':order_id' => $orderId]);
    $roomMixRows = $stmt->fetchAll(PDO::FETCH_ASSOC);

    $parts = [];
    foreach ($roomMixRows as $mixRow) {
        $parts[] = trim((string)$mixRow['room_type_title']) . ' x ' . (int)$mixRow['qty_rooms'];
    }
    $roomMix = implode(', ', $parts);
} catch (Throwable $e) {
    $roomMixRows = [];
    $roomMix = '';
}

if ($roomMix === '') {
    $roomMix = 'Not set';
}

$guestName = trim(($order['firstname'] ?? '') . ' ' . ($order['lastname'] ?? ''));
if ($guestName === '') {
    $guestName = 'Guest';
}

$agentName = trim((string)($order['agent_name'] ?? ''));
if ($agentName === '') {
    $agentName = 'Direct';
}

$currencyCode = trim((string)($order['property_currency_code'] ?? 'USD'));
if ($currencyCode === '') {
    $currencyCode = 'USD';
}

$currency = $currencyCode;
$symbolMap = [
    'USD' => '$',
    'EUR' => '€',
    'GBP' => '£',
    'ZAR' => 'R',
    'ZWG' => 'ZWG ',
    'ZWL' => 'ZWL ',
    'BWP' => 'P',
];
$symbol = $symbolMap[$currencyCode] ?? ($currencyCode . ' ');

/* -----------------------------
   Resolve receipt folio context
----------------------------- */
$receiptFolio = null;
$paymentRecord = null;
$paymentLines = [];
$totalPaid = 0.00;

if ($paymentId > 0) {
    /*
      Find exact folio from the payment transaction itself
    */
    $stmt = $pdo->prepare("
        SELECT
            p.*,
            ft.id AS folio_transaction_id,
            ft.folio_id,
            ft.tx_date,
            ft.description,
            ft.credit
        FROM payment p
        INNER JOIN folio_transactions ft
            ON ft.source_table = 'payment'
           AND ft.source_id = p.id
           AND ft.tx_type = 'payment'
        WHERE p.id = :payment_id
          AND p.order_id = :order_id
          AND COALESCE(p.is_voided, 0) = 0
        LIMIT 1
    ");
    $stmt->execute([
        ':payment_id' => $paymentId,
        ':order_id'   => $orderId,
    ]);
    $paymentRecord = $stmt->fetch(PDO::FETCH_ASSOC);

    if (!$paymentRecord) {
        exit('Payment not found or already voided.');
    }

    $stmt = $pdo->prepare("
        SELECT
            f.*,
            r.room_no,
            rt.title AS room_type_title
        FROM folios f
        LEFT JOIN rooms r ON r.id = f.room_id
        LEFT JOIN order_rooming orm ON orm.id = f.rooming_id
        LEFT JOIN room_types rt ON rt.id = orm.room_type_id
        WHERE f.id = :folio_id
        LIMIT 1
    ");
    $stmt->execute([':folio_id' => (int)$paymentRecord['folio_id']]);
    $receiptFolio = $stmt->fetch(PDO::FETCH_ASSOC);

    if (!$receiptFolio) {
        exit('Linked folio not found.');
    }

    $paymentLines[] = [
        'tx_date'     => $paymentRecord['tx_date'],
        'description' => $paymentRecord['description'],
        'credit'      => $paymentRecord['credit'],
    ];

    $totalPaid = (float)$paymentRecord['credit'];
} else {
    /*
      Booking-wide receipt summary across all folios
    */
    $stmt = $pdo->prepare("
        SELECT
            COALESCE(SUM(total_charges),0) AS total_charges,
            COALESCE(SUM(total_payments),0) AS total_payments,
            COALESCE(SUM(balance),0) AS total_balance
        FROM folios
        WHERE order_id = :order_id
    ");
    $stmt->execute([':order_id' => $orderId]);
    $folioTotals = $stmt->fetch(PDO::FETCH_ASSOC);

    $stmt = $pdo->prepare("
        SELECT
            f.*,
            r.room_no,
            rt.title AS room_type_title
        FROM folios f
        LEFT JOIN rooms r ON r.id = f.room_id
        LEFT JOIN order_rooming orm ON orm.id = f.rooming_id
        LEFT JOIN room_types rt ON rt.id = orm.room_type_id
        WHERE f.order_id = :order_id
        ORDER BY
            CASE folio_type
                WHEN 'master' THEN 1
                WHEN 'room' THEN 2
                WHEN 'guest' THEN 3
                ELSE 9
            END,
            id ASC
        LIMIT 1
    ");
    $stmt->execute([':order_id' => $orderId]);
    $receiptFolio = $stmt->fetch(PDO::FETCH_ASSOC);

    $stmt = $pdo->prepare("
        SELECT
            ft.*,
            f.folio_name,
            f.folio_type,
            {$folioOccupantSelect} AS occupant_name,
            r.room_no,
            rt.title AS room_type_title
        FROM folio_transactions ft
        INNER JOIN folios f ON f.id = ft.folio_id
        LEFT JOIN rooms r ON r.id = f.room_id
        LEFT JOIN order_rooming orm ON orm.id = f.rooming_id
        LEFT JOIN room_types rt ON rt.id = orm.room_type_id
        WHERE ft.order_id = :order_id
          AND ft.credit > 0
          AND ft.source_table = 'payment'
        ORDER BY ft.tx_date ASC, ft.id ASC
    ");
    $stmt->execute([':order_id' => $orderId]);
    $paymentLines = $stmt->fetchAll(PDO::FETCH_ASSOC);

    foreach ($paymentLines as $line) {
        $totalPaid += (float)$line['credit'];
    }

    if (!$receiptFolio) {
        $receiptFolio = [
            'folio_no'        => '',
            'folio_name'      => 'Booking Folios',
            'folio_type'      => 'master',
            'total_charges'   => (float)($folioTotals['total_charges'] ?? 0),
            'total_payments'  => (float)($folioTotals['total_payments'] ?? 0),
            'balance'         => (float)($folioTotals['total_balance'] ?? 0),
            'room_no'         => null,
            'room_type_title' => '',
        ];
    } else {
        $receiptFolio['total_charges']  = (float)($folioTotals['total_charges'] ?? 0);
        $receiptFolio['total_payments'] = (float)($folioTotals['total_payments'] ?? 0);
        $receiptFolio['balance']        = (float)($folioTotals['total_balance'] ?? 0);
    }
}

/* -----------------------------
   Company profile
----------------------------- */
$company = [
    'CompanyName'   => defined('APP_NAME') ? APP_NAME : 'RoomZ Lodge',
    'Postal'        => '',
    'Street'        => '',
    'City'          => '',
    'Email'         => '',
    'Phone'         => '',
    'Website'       => '',
    'VATNO'         => '',
    'TIN'           => '',
    'Motto'         => 'Reservations • Folios • Payments',
    'ReceiptPrefix' => 'RCT'
];

try {
    $address = false;

    try {
        $stmtCompany = $pdo->prepare("
            SELECT *
            FROM tblmailinglist
            WHERE property_id = :property_id
            ORDER BY ID DESC
            LIMIT 1
        ");
        $stmtCompany->execute([':property_id' => $propertyId]);
        $address = $stmtCompany->fetch(PDO::FETCH_ASSOC);
    } catch (Throwable $e) {
        $address = false;
    }

    if (!$address) {
        try {
            $q = $pdo->query("SELECT * FROM tblmailinglist WHERE ID = 2 LIMIT 1");
            $address = $q ? $q->fetch(PDO::FETCH_ASSOC) : false;
        } catch (Throwable $e) {
            $address = false;
        }
    }

    if ($address) {
        $company['CompanyName'] = $address['CompanyName'] ?: $company['CompanyName'];
        $company['Postal']      = $address['Postal'] ?? '';
        $company['Street']      = $address['Street'] ?? '';
        $company['City']        = $address['City'] ?? '';
        $company['Email']       = $address['Email'] ?? '';
        $company['Phone']       = $address['Phone'] ?? '';
        $company['Website']     = $address['Website'] ?? '';
        $company['VATNO']       = $address['VATNO'] ?? '';
        $company['TIN']         = $address['TIN'] ?? '';
        $company['Motto']       = $address['Motto'] ?: $company['Motto'];
        if (!empty($address['ReceiptPrefix'])) {
            $company['ReceiptPrefix'] = $address['ReceiptPrefix'];
        }
    }
} catch (Throwable $e) {
    // keep defaults
}

$propertyDisplay = trim((string)($order['property_name'] ?? ''));
if ($propertyDisplay !== '' && stripos($company['CompanyName'], $propertyDisplay) === false) {
    $company['Motto'] = $propertyDisplay . ' • ' . $company['Motto'];
}

/* -----------------------------
   PDF
----------------------------- */
class PDF extends FPDF
{
    public $company = [];
    public $docTitle = 'RECEIPT';

    function Header()
    {
        $companyName = pdf_txt($this->company['CompanyName'] ?? 'Company');
        $street      = pdf_txt($this->company['Street'] ?? '');
        $postal      = pdf_txt($this->company['Postal'] ?? '');
        $city        = pdf_txt($this->company['City'] ?? '');
        $email       = pdf_txt($this->company['Email'] ?? '');
        $phone       = pdf_txt($this->company['Phone'] ?? '');
        $website     = pdf_txt($this->company['Website'] ?? '');

        $this->SetFillColor(24, 94, 82);
        $this->Rect(0, 0, 210, 12, 'F');

        $logo = __DIR__ . '/att.png';
        if (file_exists($logo)) {
            $this->Image($logo, 155, 16, 40);
        }

        $this->SetTextColor(28, 28, 28);
        $this->SetFont('Arial', 'B', 15);
        $this->SetXY(10, 18);
        $this->Cell(100, 7, $companyName, 0, 1, 'L');

        $this->SetFont('Arial', '', 9);
        $this->SetX(10);
        $this->Cell(100, 5, $street, 0, 1, 'L');
        $this->SetX(10);
        $this->Cell(100, 5, trim($postal . '  ' . $city), 0, 1, 'L');
        $this->Ln(1);
        $this->SetX(10);
        $this->Cell(100, 5, 'Tel: ' . $phone, 0, 1, 'L');
        $this->SetX(10);
        $this->Cell(100, 5, 'Email: ' . $email, 0, 1, 'L');
        $this->SetX(10);
        $this->Cell(100, 5, 'Web: ' . $website, 0, 1, 'L');

        $this->SetXY(135, 58);
        $this->SetTextColor(24, 94, 82);
        $this->SetFont('Arial', 'B', 16);
        $this->Cell(60, 10, pdf_txt($this->docTitle), 0, 1, 'R', false);

        $this->SetDrawColor(220, 226, 231);
        $this->Line(10, 70, 200, 70);
        $this->Ln(10);
    }

    function Footer()
    {
        $motto = pdf_txt($this->company['Motto'] ?? '');
        $timestamp = date("Y-m-d H:i:s");

        $this->SetY(-14);
        $this->SetDrawColor(220, 226, 231);
        $this->Line(10, $this->GetY(), 200, $this->GetY());

        $this->SetY(-11);
        $this->SetFont('Arial', 'I', 8);
        $this->SetTextColor(95, 95, 95);
        $this->Cell(120, 5, $motto, 0, 0, 'L');
        $this->Cell(40, 5, $timestamp, 0, 0, 'C');
        $this->Cell(30, 5, 'Page ' . $this->PageNo() . '/{nb}', 0, 0, 'R');
    }

    function sectionBar($title)
    {
        $this->SetFillColor(240, 245, 247);
        $this->SetTextColor(35, 45, 55);
        $this->SetFont('Arial', 'B', 10);
        $this->Cell(190, 8, '  ' . pdf_txt($title), 0, 1, 'L', true);
        $this->Ln(2);
    }
}

$pdf = new PDF();
$pdf->company  = $company;
$pdf->docTitle = 'RECEIPT';
$pdf->AliasNbPages();
$pdf->AddPage();
$pdf->SetAutoPageBreak(true, 18);

/* -----------------------------
   Summary
----------------------------- */
$pdf->sectionBar('Client & Receipt Summary');

$propertyLabel = trim((string)($order['property_name'] ?? ''));
if (!empty($order['property_code'])) {
    $propertyLabel .= ($propertyLabel !== '' ? ' (' . $order['property_code'] . ')' : $order['property_code']);
}

$receiptPrefix = trim((string)($company['ReceiptPrefix'] ?? 'RCT'));
if ($receiptPrefix === '') {
    $receiptPrefix = 'RCT';
}
if (!empty($order['property_code'])) {
    $receiptPrefix .= '-' . strtoupper((string)$order['property_code']);
}

$folioLabel = receipt_folio_label($receiptFolio);

$pdf->SetFont('Arial', 'B', 10);
$pdf->SetTextColor(30, 30, 30);
$pdf->Cell(95, 6, pdf_txt($guestName), 0, 0, 'L');
$pdf->Cell(45, 6, 'Receipt #:', 0, 0, 'R');
$pdf->SetFont('Arial', '', 10);
$receiptNumber = $receiptPrefix . '-' . $orderId;
if ($paymentId > 0) {
    $receiptNumber .= '-' . $paymentId;
}
$pdf->Cell(50, 6, pdf_txt($receiptNumber), 0, 1, 'R');

$pdf->SetFont('Arial', 'B', 10);
$pdf->Cell(95, 6, pdf_txt($agentName), 0, 0, 'L');
$pdf->Cell(45, 6, 'Receipt Date:', 0, 0, 'R');
$pdf->SetFont('Arial', '', 10);
$pdf->Cell(50, 6, safe_date_fmt_pdf(date('Y-m-d'), 'd-M-y'), 0, 1, 'R');

$pdf->SetFont('Arial', '', 9);
$pdf->Cell(95, 5, pdf_txt($roomMix), 0, 0, 'L');
$pdf->Cell(45, 5, 'Booking Ref #:', 0, 0, 'R');
$pdf->Cell(50, 5, pdf_txt($order['order_no'] ?: $orderId), 0, 1, 'R');

$pdf->Cell(95, 5, pdf_txt('Stay: ' . $order['check_in'] . ' to ' . $order['check_out']), 0, 0, 'L');
$pdf->Cell(45, 5, 'Current Balance:', 0, 0, 'R');
$pdf->Cell(50, 5, pdf_txt($currency . ' ' . money_fmt_pdf($receiptFolio['balance'] ?? 0)), 0, 1, 'R');

if ($propertyLabel !== '') {
    $pdf->Cell(95, 5, pdf_txt('Property: ' . $propertyLabel), 0, 0, 'L');
    $pdf->Cell(45, 5, 'Currency:', 0, 0, 'R');
    $pdf->Cell(50, 5, pdf_txt($currency), 0, 1, 'R');
}

$pdf->Cell(95, 5, pdf_txt('Posted To: ' . $folioLabel), 0, 0, 'L');
$pdf->Cell(45, 5, 'Folio No:', 0, 0, 'R');
$pdf->Cell(50, 5, pdf_txt((string)($receiptFolio['folio_no'] ?? '')), 0, 1, 'R');

$pdf->Cell(95, 5, pdf_txt('Rooms / Pax: ' . (int)($order['totalrooms'] ?? 1) . ' rooms • ' . (int)($order['adults'] ?? 0) . 'A / ' . (int)($order['kids'] ?? 0) . 'C'), 0, 1, 'L');

$pdf->Ln(4);

$pdf->SetFillColor(232, 242, 240);
$pdf->SetDrawColor(208, 225, 221);
$pdf->SetFont('Arial', 'B', 10);
$pdf->Cell(140, 10, 'Total Payments Received (' . $currency . ')', 1, 0, 'L', true);
$pdf->Cell(50, 10, $currency . ' ' . money_fmt_pdf($totalPaid), 1, 1, 'R', true);

if (!empty($roomMixRows)) {
    $pdf->Ln(5);
    $pdf->sectionBar('Booked Room Mix');

    $pdf->SetFillColor(24, 94, 82);
    $pdf->SetTextColor(255, 255, 255);
    $pdf->SetFont('Arial', 'B', 9);
    $pdf->Cell(130, 8, 'Room Type', 0, 0, 'L', true);
    $pdf->Cell(60, 8, 'Rooms', 0, 1, 'R', true);

    $pdf->SetTextColor(35, 35, 35);
    $pdf->SetFont('Arial', '', 8.5);
    $fill = false;

    foreach ($roomMixRows as $mixRow) {
        $pdf->SetFillColor($fill ? 248 : 255, $fill ? 250 : 255, $fill ? 252 : 255);
        $pdf->Cell(130, 8, pdf_txt((string)$mixRow['room_type_title']), 0, 0, 'L', true);
        $pdf->Cell(60, 8, (int)$mixRow['qty_rooms'], 0, 1, 'R', true);
        $fill = !$fill;
    }
}

/* -----------------------------
   Payment items
----------------------------- */
$pdf->Ln(5);
$pdf->sectionBar('Payment Items');

$pdf->SetFillColor(24, 94, 82);
$pdf->SetTextColor(255, 255, 255);
$pdf->SetFont('Arial', 'B', 9);

$w1 = 32;
$w2 = 128;
$w3 = 30;

$pdf->Cell($w1, 9, 'Date', 0, 0, 'L', true);
$pdf->Cell($w2, 9, 'Description', 0, 0, 'L', true);
$pdf->Cell($w3, 9, 'Amount', 0, 1, 'R', true);

$pdf->SetTextColor(35, 35, 35);
$pdf->SetFont('Arial', '', 8.5);

$fill = false;
foreach ($paymentLines as $line) {
    $dateTxt = pdf_txt(safe_date_fmt_pdf($line['tx_date'], 'd-M-y'));
    $desc = (string)$line['description'];

    if ($paymentId <= 0) {
        $folioLineLabel = receipt_folio_label($line);

        if ($folioLineLabel !== '') {
            $desc .= ' | ' . $folioLineLabel;
        }
    }

    $descTxt = pdf_txt($desc);
    $amt = (float)$line['credit'];

    if ($fill) {
        $pdf->SetFillColor(248, 250, 252);
    } else {
        $pdf->SetFillColor(255, 255, 255);
    }

    $pdf->Cell($w1, 10, $dateTxt, 0, 0, 'L', true);

    $x = $pdf->GetX();
    $y = $pdf->GetY();

    $pdf->MultiCell($w2, 5, $descTxt, 0, 'L', true);
    $currentY = $pdf->GetY();
    $rowHeight = $currentY - $y;
    if ($rowHeight < 10) {
        $rowHeight = 10;
    }

    $pdf->SetXY($x + $w2, $y);
    $pdf->Cell($w3, $rowHeight, money_fmt_pdf($amt), 0, 1, 'R', true);

    $pdf->SetDrawColor(225, 230, 235);
    $pdf->Line(10, $pdf->GetY(), 200, $pdf->GetY());

    $fill = !$fill;
}

/* -----------------------------
   Totals
----------------------------- */
$pdf->Ln(4);
$pdf->SetFont('Arial', 'B', 9);
$pdf->SetFillColor(245, 247, 249);
$pdf->Cell(130, 8, '', 0, 0);
$pdf->Cell(25, 8, 'Total Paid', 1, 0, 'L', true);
$pdf->Cell(10, 8, $symbol, 1, 0, 'C', true);
$pdf->Cell(25, 8, money_fmt_pdf($totalPaid), 1, 1, 'R', true);

$pdf->Ln(6);
$pdf->SetFont('Arial', 'I', 8.5);

$footerNote = 'This receipt confirms the payments received and posted to the folio for the above booking.';
if ($paymentId > 0) {
    $footerNote = 'This receipt confirms the payment received and posted to ' . $folioLabel . ' for the above booking.';
}

$pdf->MultiCell(
    190,
    6,
    pdf_txt($footerNote),
    0,
    'L'
);

$pdf->Output('receipt_' . ($order['order_no'] ?: $orderId) . ($paymentId > 0 ? '_' . $paymentId : '') . '.pdf', 'I');
exit;
