<?php
declare(strict_types=1);

require __DIR__ . '/app/bootstrap.php';
require_auth();
require_current_schema();
require_permission('documents.create');
require __DIR__ . '/app/layout.php';

$documentId = (int)($_GET['id'] ?? $_POST['document_id'] ?? 0);
$requestedType = (($_GET['type'] ?? $_POST['document_type'] ?? 'invoice') === 'quotation') ? 'quotation' : 'invoice';
$document = null;
$existingItems = [];

if ($documentId > 0) {
    $stmt = db()->prepare('SELECT * FROM documents WHERE id=? AND type IN ("invoice","quotation")');
    $stmt->execute([$documentId]);
    $document = $stmt->fetch() ?: null;
    if (!$document) {
        flash('error', 'The document could not be found.');
        redirect('index.php?page=invoices');
    }
    $requestedType = (string)$document['type'];
    $itemStmt = db()->prepare('SELECT * FROM document_items WHERE document_id=? ORDER BY sort_order,id');
    $itemStmt->execute([$documentId]);
    $existingItems = $itemStmt->fetchAll();
}

$documentType = $requestedType;
$isQuotation = $documentType === 'quotation';
$isEdit = $document !== null;
$customers = db()->query('SELECT id,name,company_name,email,phone,whatsapp,address,city,area,preferred_payment FROM customers WHERE active=1 ORDER BY COALESCE(NULLIF(company_name,""),name),name')->fetchAll();
$products = db()->query('SELECT id,sku,name,description,category,unit_price,cost_price,tax_rate,stock_quantity,reorder_level,track_stock FROM products WHERE active=1 ORDER BY FIELD(category,"CO2 Cylinders","Sparkling Water Machines","Bottles","Flavours & Syrups","Services","Other"),name')->fetchAll();
$productsById = [];
$groupedProducts = [];
foreach ($products as $product) {
    $productsById[(int)$product['id']] = $product;
    $groupedProducts[$product['category'] ?: 'Other'][] = $product;
}

$errors = [];
$posted = $_SERVER['REQUEST_METHOD'] === 'POST';

if ($posted) {
    try {
        verify_csrf();
        $documentId = (int)($_POST['document_id'] ?? 0);
        $documentType = (($_POST['document_type'] ?? 'invoice') === 'quotation') ? 'quotation' : 'invoice';
        $isQuotation = $documentType === 'quotation';
        $nextAction = ($_POST['next_action'] ?? 'draft') === 'issue' ? 'issue' : 'draft';

        $createCustomer = ($_POST['customer_mode'] ?? 'existing') === 'new';
        $customerId = (int)($_POST['customer_id'] ?? 0);
        $newCustomer = [
            'name' => trim((string)($_POST['new_customer_name'] ?? '')),
            'company_name' => trim((string)($_POST['new_customer_company'] ?? '')),
            'phone' => trim((string)($_POST['new_customer_phone'] ?? '')),
            'whatsapp' => trim((string)($_POST['new_customer_whatsapp'] ?? '')),
            'email' => strtolower(trim((string)($_POST['new_customer_email'] ?? ''))),
            'address' => trim((string)($_POST['new_customer_address'] ?? '')),
            'area' => trim((string)($_POST['new_customer_area'] ?? '')),
            'preferred_payment' => trim((string)($_POST['new_customer_payment'] ?? '')),
        ];
        if ($createCustomer) {
            if ($newCustomer['name'] === '' && $newCustomer['company_name'] === '') throw new RuntimeException('Enter the customer or company name.');
            if ($newCustomer['phone'] === '' && $newCustomer['whatsapp'] === '' && $newCustomer['email'] === '') throw new RuntimeException('Enter at least one customer contact: phone, WhatsApp or email.');
            if ($newCustomer['email'] !== '' && !filter_var($newCustomer['email'], FILTER_VALIDATE_EMAIL)) throw new RuntimeException('Enter a valid customer email address.');
        } elseif (!$customerId) {
            throw new RuntimeException('Select a customer or choose “Add a new customer”.');
        }

        $rawItems = is_array($_POST['items'] ?? null) ? $_POST['items'] : [];
        $normalisedItems = [];
        foreach ($rawItems as $rawItem) {
            if (!is_array($rawItem)) continue;
            $productId = (int)($rawItem['product_id'] ?? 0);
            $product = $productId ? ($productsById[$productId] ?? null) : null;
            if ($productId && !$product) throw new RuntimeException('One of the selected products is no longer available.');
            $description = trim((string)($rawItem['description'] ?? ($product['name'] ?? '')));
            $quantity = decimal($rawItem['quantity'] ?? 0);
            if ($description === '' && $quantity <= 0) continue;
            if ($description === '' || $quantity <= 0) throw new RuntimeException('Every line needs a description and quantity greater than zero.');
            $normalisedItems[] = [
                'product_id' => $productId ?: null,
                'description' => $description,
                'quantity' => $quantity,
                'unit_price' => max(0, decimal($rawItem['unit_price'] ?? ($product['unit_price'] ?? 0))),
                'tax_rate' => max(0, decimal($rawItem['tax_rate'] ?? ($product['tax_rate'] ?? 0))),
                'unit_cost' => $product ? max(0, decimal($product['cost_price'])) : 0,
            ];
        }
        if (!$normalisedItems) throw new RuntimeException('Add at least one product or service.');

        $discountType = ($_POST['discount_type'] ?? 'fixed') === 'percent' ? 'percent' : 'fixed';
        $discountValue = max(0, decimal($_POST['discount_value'] ?? 0));
        if ($discountType === 'percent' && $discountValue > 100) throw new RuntimeException('The percentage discount cannot be more than 100%.');
        $fulfilment = ($_POST['fulfilment_method'] ?? 'Pickup') === 'Delivery' ? 'Delivery' : 'Pickup';
        $deliveryFee = $fulfilment === 'Delivery' ? max(0, decimal($_POST['delivery_fee'] ?? 0)) : 0;
        $deliveryAddress = $fulfilment === 'Delivery' ? trim((string)($_POST['delivery_address'] ?? '')) : '';
        if ($nextAction === 'issue' && $fulfilment === 'Delivery' && ($deliveryAddress === '' || $deliveryFee <= 0)) {
            throw new RuntimeException('Before issuing a delivery document, enter the delivery address and the agreed delivery fee. You can save it as a draft while the fee is being confirmed.');
        }

        $issueDate = (string)($_POST['issue_date'] ?? '');
        $dueDate = (string)($_POST['due_date'] ?? '');
        if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $issueDate) || !preg_match('/^\d{4}-\d{2}-\d{2}$/', $dueDate)) throw new RuntimeException('Enter valid issue and due dates.');
        if ($dueDate < $issueDate) throw new RuntimeException(($isQuotation ? 'Valid until' : 'Due date') . ' cannot be before the issue date.');
        $totals = document_totals($normalisedItems, $discountType, $discountValue, $deliveryFee);
        foreach ($totals['items'] as $index => &$calculatedItem) $calculatedItem['unit_cost'] = $normalisedItems[$index]['unit_cost'] ?? 0;
        unset($calculatedItem);

        $orderSource = in_array($_POST['order_source'] ?? '', ['WhatsApp','Website','Walk-in','Phone','Social media','Email','Other'], true) ? (string)$_POST['order_source'] : 'WhatsApp';
        $notes = trim((string)($_POST['notes'] ?? ''));
        $terms = trim((string)($_POST['terms'] ?? (settings()['invoice_terms'] ?? '')));
        $internalNotes = trim((string)($_POST['internal_notes'] ?? ''));
        $customerReference = trim((string)($_POST['customer_reference'] ?? ''));
        $followUpDate = trim((string)($_POST['follow_up_date'] ?? '')) ?: null;
        if ($followUpDate !== null && !preg_match('/^\d{4}-\d{2}-\d{2}$/', $followUpDate)) throw new RuntimeException('Enter a valid follow-up date.');

        db()->beginTransaction();

        $customer = null;
        if ($createCustomer) {
            $duplicate = null;
            if ($newCustomer['email'] !== '') {
                $check = db()->prepare('SELECT * FROM customers WHERE email=? LIMIT 1');
                $check->execute([$newCustomer['email']]);
                $duplicate = $check->fetch() ?: null;
            }
            $contactNumber = $newCustomer['whatsapp'] ?: $newCustomer['phone'];
            $normalisedContact = whatsapp_phone($contactNumber);
            if (!$duplicate && $normalisedContact !== '') {
                $contactRows = db()->query('SELECT * FROM customers WHERE active=1 AND (phone IS NOT NULL OR whatsapp IS NOT NULL)')->fetchAll();
                foreach ($contactRows as $contactRow) {
                    $savedPhone = whatsapp_phone((string)($contactRow['whatsapp'] ?: $contactRow['phone']));
                    if ($savedPhone !== '' && hash_equals($savedPhone, $normalisedContact)) {
                        $duplicate = $contactRow;
                        break;
                    }
                }
            }
            if ($duplicate) {
                $customerId = (int)$duplicate['id'];
                $customer = $duplicate;
            } else {
                $displayName = $newCustomer['name'] ?: $newCustomer['company_name'];
                $insertCustomer = db()->prepare('INSERT INTO customers (name,company_name,email,phone,whatsapp,address,city,customer_type,area,preferred_payment,notes) VALUES (?,?,?,?,?,?,"Harare","Household",?,?,?)');
                $insertCustomer->execute([$displayName, $newCustomer['company_name'], $newCustomer['email'] ?: null, $newCustomer['phone'], $newCustomer['whatsapp'] ?: $newCustomer['phone'], $newCustomer['address'], $newCustomer['area'], $newCustomer['preferred_payment'], 'Created from the document studio']);
                $customerId = (int)db()->lastInsertId();
                $customer = array_merge($newCustomer, ['id' => $customerId]);
            }
        } else {
            $check = db()->prepare('SELECT * FROM customers WHERE id=? AND active=1');
            $check->execute([$customerId]);
            $customer = $check->fetch();
            if (!$customer) throw new RuntimeException('The selected customer could not be found.');
        }

        $status = $nextAction === 'issue' ? 'sent' : 'draft';
        // Draft links are still blocked by share.php; keeping the token ready makes issuing one click.
        $shareToken = bin2hex(random_bytes(32));
        $shareEnabled = 1;
        $sentAt = $nextAction === 'issue' ? date('Y-m-d H:i:s') : null;

        if ($documentId > 0) {
            $lock = db()->prepare('SELECT * FROM documents WHERE id=? FOR UPDATE');
            $lock->execute([$documentId]);
            $lockedDocument = $lock->fetch();
            if (!$lockedDocument || !in_array($lockedDocument['type'], ['invoice','quotation'], true)) throw new RuntimeException('The draft could not be found.');
            if ($lockedDocument['status'] !== 'draft' || $lockedDocument['stock_processed_at']) throw new RuntimeException('Only an unfulfilled draft can be edited.');
            if ((int)($_POST['lock_version'] ?? 0) !== (int)($lockedDocument['lock_version'] ?? 1)) throw new RuntimeException('This draft changed in another session. Reload it before saving.');
            $documentType = (string)$lockedDocument['type'];
            $isQuotation = $documentType === 'quotation';
            $shareToken = $lockedDocument['share_token'] ?: bin2hex(random_bytes(32));
            $update = db()->prepare('UPDATE documents SET customer_id=?,issue_date=?,due_date=?,status=?,subtotal=?,discount_type=?,discount_value=?,discount_total=?,tax_total=?,delivery_fee=?,total=?,notes=?,terms=?,customer_reference=?,order_source=?,fulfilment_method=?,delivery_address=?,share_token=?,share_enabled=?,sent_at=?,follow_up_date=?,internal_notes=?,lock_version=lock_version+1 WHERE id=?');
            $update->execute([$customerId,$issueDate,$dueDate,$status,$totals['subtotal'],$discountType,$discountValue,$totals['discount_total'],$totals['tax_total'],$deliveryFee,$totals['total'],$notes,$terms,$customerReference,$orderSource,$fulfilment,$deliveryAddress,$shareToken,$shareEnabled,$sentAt,$followUpDate,$internalNotes,$documentId]);
            db()->prepare('DELETE FROM document_items WHERE document_id=?')->execute([$documentId]);
            $number = (string)$lockedDocument['number'];
        } else {
            $number = reserve_unique_number($documentType);
            $insert = db()->prepare('INSERT INTO documents (type,number,customer_id,issue_date,due_date,status,currency_code,subtotal,discount_type,discount_value,discount_total,tax_total,delivery_fee,total,notes,terms,customer_reference,order_source,fulfilment_method,delivery_address,share_token,share_enabled,sent_at,follow_up_date,internal_notes,lock_version,created_by) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,1,?)');
            $insert->execute([$documentType,$number,$customerId,$issueDate,$dueDate,$status,(string)(settings()['currency_code'] ?? 'USD'),$totals['subtotal'],$discountType,$discountValue,$totals['discount_total'],$totals['tax_total'],$deliveryFee,$totals['total'],$notes,$terms,$customerReference,$orderSource,$fulfilment,$deliveryAddress,$shareToken,$shareEnabled,$sentAt,$followUpDate,$internalNotes,user()['id']]);
            $documentId = (int)db()->lastInsertId();
        }

        $itemInsert = db()->prepare('INSERT INTO document_items (document_id,product_id,description,quantity,unit_price,unit_cost,tax_rate,line_subtotal,line_tax,line_total,sort_order) VALUES (?,?,?,?,?,?,?,?,?,?,?)');
        foreach ($totals['items'] as $sort => $item) {
            $itemInsert->execute([$documentId,$item['product_id'],$item['description'],$item['quantity'],$item['unit_price'],$item['unit_cost'] ?? 0,$item['tax_rate'],$item['line_subtotal'],$item['line_tax'],$item['line_total'],$sort]);
        }

        if ($nextAction === 'issue' && !$isQuotation && $fulfilment === 'Delivery') {
            $deliveryCheck = db()->prepare('SELECT id FROM deliveries WHERE document_id=? LIMIT 1');
            $deliveryCheck->execute([$documentId]);
            $deliveryId = (int)($deliveryCheck->fetchColumn() ?: 0);
            if ($deliveryId) {
                db()->prepare('UPDATE deliveries SET customer_id=?,delivery_address=?,area=?,delivery_fee=?,status=IF(status="cancelled","pending",status),notes=? WHERE id=?')->execute([$customerId,$deliveryAddress,$customer['area'] ?? '',$deliveryFee,'Issued from document studio '.$number,$deliveryId]);
            } else {
                $reference = 'SZW-DL-'.date('ymd').'-'.strtoupper(bin2hex(random_bytes(2)));
                db()->prepare('INSERT INTO deliveries (reference,customer_id,document_id,delivery_address,area,delivery_fee,status,notes,created_by) VALUES (?,?,?,?,?,? ,"pending",?,?)')->execute([$reference,$customerId,$documentId,$deliveryAddress,$customer['area'] ?? '',$deliveryFee,'Issued from document studio '.$number,user()['id']]);
            }
        }

        db()->prepare('INSERT INTO document_events (document_id,event_type,from_status,to_status,notes,created_by) VALUES (?,?,?,?,?,?)')->execute([$documentId,$isEdit ? 'document_updated' : 'document_created',$isEdit ? 'draft' : null,$status,$nextAction === 'issue' ? 'Saved and issued from document studio' : 'Draft saved from document studio',user()['id']]);
        audit($isEdit ? 'document_updated' : 'document_created', $documentType, $documentId, $number);
        db()->commit();
        flash('success', ($nextAction === 'issue' ? document_label($documentType).' issued and ready to send.' : 'Draft saved successfully.'));
        redirect('index.php?page=document-view&id='.$documentId.($nextAction === 'issue' ? '&share=1' : ''));
    } catch (Throwable $e) {
        if (db()->inTransaction()) db()->rollBack();
        $errors[] = $e instanceof PDOException ? 'The document could not be saved. Review the highlighted information and try again.' : $e->getMessage();
    }
}

$form = static function (string $name, mixed $default = '') use ($posted, $document): mixed {
    if ($posted) return $_POST[$name] ?? $default;
    if ($document && array_key_exists($name, $document)) return $document[$name];
    return $default;
};
$defaultDueDays = $isQuotation ? 14 : (int)(settings()['default_due_days'] ?? 7);
$defaultDue = date('Y-m-d', strtotime('+'.$defaultDueDays.' days'));
$customerMode = (string)$form('customer_mode', $customers ? 'existing' : 'new');
$selectedCustomerId = (int)$form('customer_id', $_GET['customer_id'] ?? ($document['customer_id'] ?? 0));
$initialItems = $posted ? (is_array($_POST['items'] ?? null) ? $_POST['items'] : []) : $existingItems;
if (!$initialItems) $initialItems = [['product_id'=>'','description'=>'','quantity'=>1,'unit_price'=>'','tax_rate'=>(float)(settings()['default_tax_rate'] ?? 0)]];

render_header(($isEdit ? 'Edit ' : 'New ').($isQuotation ? 'quotation' : 'invoice'), $isQuotation ? 'quotations' : 'invoices');
?>
<div class="document-studio-heading">
    <div>
        <span class="section-kicker">SODA ZW DOCUMENT STUDIO <b class="studio-version">Modern workspace</b></span>
        <h2><?=e($isEdit ? 'Edit '.$document['number'] : 'Create a '.($isQuotation ? 'quotation' : 'invoice'))?></h2>
        <p>Build a professional <?=e($isQuotation ? 'quotation' : 'invoice')?> with guided customer, item, fulfilment and review steps.</p>
        <div class="studio-heading-badges" aria-label="Workspace benefits">
            <span>Private until issued</span><span>Automatic calculations</span><span>Desktop &amp; mobile</span>
        </div>
    </div>
    <div class="document-type-switch" aria-label="Document type">
        <?php if (!$isEdit):?>
            <a class="<?=$isQuotation ? '' : 'active'?>" href="quick-invoice.php"><?=app_nav_icon('invoices')?> Invoice</a>
            <a class="<?=$isQuotation ? 'active' : ''?>" href="quick-invoice.php?type=quotation"><?=app_nav_icon('quotations')?> Quotation</a>
        <?php else:?>
            <span class="studio-status draft">Draft · <?=e(document_label($documentType))?></span>
        <?php endif;?>
    </div>
</div>

<nav class="studio-workflow" aria-label="Document creation steps">
    <span class="studio-progress-track" aria-hidden="true"><i data-studio-progress></i></span>
    <button type="button" class="is-active" aria-current="step" data-studio-jump="studio-customer"><span>1</span><strong>Customer</strong><small>Select or add</small></button>
    <button type="button" data-studio-jump="studio-items"><span>2</span><strong>Items</strong><small>Products &amp; services</small></button>
    <button type="button" data-studio-jump="studio-fulfilment"><span>3</span><strong>Delivery</strong><small>Pickup or delivery</small></button>
    <button type="button" data-studio-jump="studio-details"><span>4</span><strong>Review</strong><small>Dates &amp; terms</small></button>
</nav>

<?php if ($document && $document['status'] !== 'draft'):?>
    <div class="alert error">This document is no longer a draft and cannot be edited. <a href="index.php?page=document-view&amp;id=<?=$documentId?>">Open the document</a>.</div>
<?php endif;?>
<?php if ($errors):?>
    <div class="studio-error-summary" role="alert" tabindex="-1">
        <strong>Please correct the following:</strong>
        <ul><?php foreach ($errors as $error):?><li><?=e($error)?></li><?php endforeach;?></ul>
    </div>
<?php endif;?>

<form method="post" class="document-studio" data-document-studio data-currency="<?=e((string)(settings()['currency_code'] ?? 'USD'))?>" novalidate>
    <?=csrf_field()?>
    <input type="hidden" name="document_id" value="<?=$documentId?>">
    <input type="hidden" name="document_type" value="<?=e($documentType)?>">
    <input type="hidden" name="lock_version" value="<?=e((string)($document['lock_version'] ?? 1))?>">

    <main class="studio-main">
        <section class="panel studio-section" id="studio-customer">
            <header class="studio-section-head">
                <span class="studio-step">1</span>
                <div><span class="section-kicker">CUSTOMER</span><h2>Who are you billing?</h2><p>Select a saved customer or create a new customer without leaving this document.</p></div>
            </header>
            <div class="customer-mode" role="radiogroup" aria-label="Customer source">
                <label><input type="radio" name="customer_mode" value="existing" <?=$customerMode !== 'new' ? 'checked' : ''?>><span><strong>Saved customer</strong><small>Use an existing account</small></span></label>
                <label><input type="radio" name="customer_mode" value="new" <?=$customerMode === 'new' ? 'checked' : ''?>><span><strong>New customer</strong><small>Create without leaving</small></span></label>
            </div>
            <div data-existing-customer>
                <label class="studio-customer-search">Find customer<input type="search" data-customer-search placeholder="Search name, company, phone or area" autocomplete="off"></label>
                <label class="studio-customer-select">Search or select customer
                    <select name="customer_id" data-studio-customer>
                        <option value="">Choose a customer</option>
                        <?php foreach ($customers as $customer):?>
                            <?php $identity = $customer['company_name'] ?: $customer['name']; $contact = $customer['whatsapp'] ?: $customer['phone'] ?: $customer['email'];?>
                            <option value="<?=$customer['id']?>" data-address="<?=e(trim((string)$customer['address']))?>" data-area="<?=e((string)$customer['area'])?>" <?=$selectedCustomerId === (int)$customer['id'] ? 'selected' : ''?>><?=e($identity.($contact ? ' · '.$contact : '').($customer['area'] ? ' · '.$customer['area'] : ''))?></option>
                        <?php endforeach;?>
                    </select>
                </label>
            </div>
            <div class="new-customer-fields form-grid" data-new-customer>
                <label>Contact name<input name="new_customer_name" value="<?=e((string)$form('new_customer_name'))?>"></label>
                <label>Company<input name="new_customer_company" value="<?=e((string)$form('new_customer_company'))?>"></label>
                <label>Phone<input name="new_customer_phone" value="<?=e((string)$form('new_customer_phone'))?>" placeholder="077 123 4567"></label>
                <label>WhatsApp<input name="new_customer_whatsapp" value="<?=e((string)$form('new_customer_whatsapp'))?>" placeholder="077 123 4567"></label>
                <label>Email<input type="email" name="new_customer_email" value="<?=e((string)$form('new_customer_email'))?>" placeholder="customer@example.com"></label>
                <label>Area / suburb<input name="new_customer_area" value="<?=e((string)$form('new_customer_area'))?>"></label>
                <label class="full">Address<input name="new_customer_address" value="<?=e((string)$form('new_customer_address'))?>"></label>
                <label>Preferred payment<select name="new_customer_payment"><option value="">Confirm later</option><?php foreach (['Cash','EcoCash','Bank transfer','POS / Swipe','Paynow','OneMoney','InnBucks',"O'mari"] as $method):?><option value="<?=e($method)?>" <?=$method === $form('new_customer_payment') ? 'selected' : ''?>><?=e($method)?></option><?php endforeach;?></select></label>
            </div>
            <div class="studio-section-actions"><span>Customer details can still be edited before issuing.</span><button type="button" class="button primary" data-studio-next="studio-items">Continue to items</button></div>
        </section>

        <section class="panel studio-section" id="studio-items">
            <header class="studio-section-head">
                <span class="studio-step">2</span>
                <div><span class="section-kicker">PRODUCTS &amp; SERVICES</span><h2>Build the line items</h2><p>Select from the Soda ZW catalogue, then confirm quantities, prices and tax.</p></div>
            </header>
            <div class="studio-product-picker" data-product-picker>
                <label>Choose a product or service
                    <select data-catalog-select>
                        <option value="">Select from the Soda ZW catalogue</option>
                        <?php foreach ($groupedProducts as $category => $categoryProducts):?>
                            <optgroup label="<?=e($category)?>">
                                <?php foreach ($categoryProducts as $product):?>
                                    <?php $stockLow = $product['track_stock'] && (float)$product['stock_quantity'] <= (float)$product['reorder_level']; ?>
                                    <option value="<?=$product['id']?>" data-name="<?=e((string)$product['name'])?>" data-price="<?=e((string)$product['unit_price'])?>" data-tax="<?=e((string)$product['tax_rate'])?>">
                                        <?=e((string)$product['name'])?> — <?=money($product['unit_price'])?><?php if ($product['track_stock']):?> — <?=e((string)$product['stock_quantity'])?> in stock<?=$stockLow?' (low stock)':''?><?php endif;?>
                                    </option>
                                <?php endforeach;?>
                            </optgroup>
                        <?php endforeach;?>
                    </select>
                </label>
                <button type="button" class="button primary" data-add-selected-product disabled>+ Add selected item</button>
                <small>Choose an item, add it to the document, then adjust its quantity, description or price when needed.</small>
            </div>

            <div class="studio-items" data-studio-items>
                <div class="studio-items-head"><span>Product / description</span><span>Quantity</span><span>Unit price</span><span>Tax</span><span>Total</span><span></span></div>
                <?php foreach ($initialItems as $index => $item):?>
                    <div class="studio-item" data-studio-item>
                        <div class="studio-item-product">
                            <select name="items[<?=$index?>][product_id]" data-item-product aria-label="Product">
                                <option value="">Custom product or service</option>
                                <?php foreach ($groupedProducts as $category => $categoryProducts):?><optgroup label="<?=e($category)?>"><?php foreach ($categoryProducts as $product):?><option value="<?=$product['id']?>" data-name="<?=e((string)$product['name'])?>" data-price="<?=e((string)$product['unit_price'])?>" data-tax="<?=e((string)$product['tax_rate'])?>" <?=((int)($item['product_id'] ?? 0) === (int)$product['id']) ? 'selected' : ''?>><?=e((string)$product['name'])?></option><?php endforeach;?></optgroup><?php endforeach;?>
                            </select>
                            <input name="items[<?=$index?>][description]" data-item-description value="<?=e((string)($item['description'] ?? ''))?>" placeholder="Description" aria-label="Line description">
                        </div>
                        <label><span>Qty</span><input type="number" min="0.01" step="0.01" inputmode="decimal" name="items[<?=$index?>][quantity]" data-item-qty value="<?=e((string)($item['quantity'] ?? 1))?>"></label>
                        <label><span>Price</span><input type="number" min="0" step="0.01" inputmode="decimal" name="items[<?=$index?>][unit_price]" data-item-price value="<?=e((string)($item['unit_price'] ?? ''))?>"></label>
                        <label><span>Tax %</span><input type="number" min="0" step="0.01" inputmode="decimal" name="items[<?=$index?>][tax_rate]" data-item-tax value="<?=e((string)($item['tax_rate'] ?? 0))?>"></label>
                        <strong data-item-total>USD 0.00</strong>
                        <button type="button" class="studio-remove" data-remove-studio-item aria-label="Remove line">×</button>
                    </div>
                <?php endforeach;?>
            </div>
            <button type="button" class="button secondary studio-add-custom" data-add-custom-line>+ Add custom line</button>
            <div class="studio-discount-box">
                <div><span class="section-kicker">DISCOUNT</span><strong>Apply a customer discount</strong><small>The invoice total updates automatically.</small></div>
                <label>Type<select name="discount_type" data-discount-type><option value="fixed">Fixed amount (USD)</option><option value="percent" <?=$form('discount_type') === 'percent' ? 'selected' : ''?>>Percentage (%)</option></select></label>
                <label>Value<input type="number" min="0" step="0.01" name="discount_value" value="<?=e((string)$form('discount_value', 0))?>" data-discount-value></label>
            </div>
            <div class="studio-section-actions"><button type="button" class="button secondary" data-studio-next="studio-customer">Back</button><button type="button" class="button primary" data-studio-next="studio-fulfilment">Continue to delivery</button></div>
        </section>

        <section class="panel studio-section" id="studio-fulfilment">
            <header class="studio-section-head">
                <span class="studio-step">3</span>
                <div><span class="section-kicker">FULFILMENT</span><h2>How will the order be fulfilled?</h2><p>Choose pickup or record the confirmed delivery address and charge.</p></div>
            </header>
            <?php $fulfilment = (string)$form('fulfilment_method', 'Pickup');?>
            <div class="quick-choice studio-choice">
                <label><input type="radio" name="fulfilment_method" value="Pickup" <?=$fulfilment !== 'Delivery' ? 'checked' : ''?>><span><strong>Pickup</strong><small>100 Livingstone Avenue</small></span></label>
                <label><input type="radio" name="fulfilment_method" value="Delivery" <?=$fulfilment === 'Delivery' ? 'checked' : ''?>><span><strong>Delivery</strong><small>Charge by location</small></span></label>
            </div>
            <div class="form-grid studio-delivery" data-delivery-fields>
                <label class="full">Delivery address<input name="delivery_address" value="<?=e((string)$form('delivery_address'))?>" data-delivery-address></label>
                <label>Agreed delivery fee<input type="number" min="0" step="0.01" name="delivery_fee" value="<?=e((string)$form('delivery_fee', 0))?>" data-delivery-fee><small>Harare is USD 10. Outside Harare must be confirmed. You may save a draft before confirmation.</small></label>
                <div class="studio-fee-presets" aria-label="Delivery fee shortcuts"><button type="button" class="button secondary small" data-delivery-preset="10">Use Harare fee · USD 10</button><button type="button" class="button secondary small" data-delivery-preset="">Outside Harare · confirm fee</button></div>
            </div>
            <div class="studio-section-actions"><button type="button" class="button secondary" data-studio-next="studio-items">Back</button><button type="button" class="button primary" data-studio-next="studio-details">Continue to review</button></div>
        </section>

        <section class="panel studio-section" id="studio-details">
            <header class="studio-section-head">
                <span class="studio-step">4</span>
                <div><span class="section-kicker">FINAL DETAILS</span><h2>Review dates and customer message</h2><p>Confirm the document dates, source, reference and customer-facing terms.</p></div>
            </header>
            <div class="form-grid">
                <label>Issue date<input type="date" name="issue_date" value="<?=e((string)$form('issue_date', date('Y-m-d')))?>" required></label>
                <label><?=$isQuotation ? 'Valid until' : 'Due date'?><input type="date" name="due_date" value="<?=e((string)$form('due_date', $defaultDue))?>" required></label>
                <label>Order source<select name="order_source"><?php foreach (['WhatsApp','Website','Walk-in','Phone','Social media','Email','Other'] as $source):?><option value="<?=e($source)?>" <?=$source === $form('order_source', 'WhatsApp') ? 'selected' : ''?>><?=e($source)?></option><?php endforeach;?></select></label>
                <label>Customer reference<input name="customer_reference" value="<?=e((string)$form('customer_reference'))?>" placeholder="PO number or reference"></label>
                <label>Follow-up date<input type="date" name="follow_up_date" value="<?=e((string)$form('follow_up_date'))?>"><small>Useful for quotation reminders</small></label>
                <label class="full">Customer note<textarea name="notes" rows="3" placeholder="Message printed on the document"><?=e((string)$form('notes'))?></textarea></label>
            </div>
            <details class="studio-more">
                <summary>More options</summary>
                <div class="form-grid">
                    <label class="full">Terms<textarea name="terms" rows="3"><?=e((string)$form('terms', settings()['invoice_terms'] ?? ''))?></textarea></label>
                    <label class="full">Internal note<textarea name="internal_notes" rows="2" placeholder="Visible only to Soda ZW staff"><?=e((string)$form('internal_notes'))?></textarea></label>
                </div>
            </details>
            <div class="studio-section-actions"><button type="button" class="button secondary" data-studio-next="studio-fulfilment">Back</button><button type="button" class="button primary" data-review-summary>Review document</button></div>
        </section>
    </main>

    <aside class="panel studio-summary" aria-label="Document summary">
        <div class="studio-summary-top">
            <span class="summary-document-icon"><?=app_nav_icon($isQuotation ? 'quotations' : 'invoices')?></span>
            <div><span class="section-kicker">LIVE SUMMARY</span><h2><?=e($isQuotation ? 'Quotation' : 'Invoice')?></h2></div>
        </div>
        <p data-summary-customer><?=e($isEdit ? $document['number'] : 'No customer selected')?></p>
        <div class="studio-summary-lines"><span data-summary-lines>0 items</span><button type="button" data-scroll-items>Edit</button></div>
        <dl aria-live="polite">
            <div><dt>Subtotal</dt><dd><?=e((string)(settings()['currency_code'] ?? 'USD'))?> <span data-studio-subtotal>0.00</span></dd></div>
            <div><dt>Discount</dt><dd>− <?=e((string)(settings()['currency_code'] ?? 'USD'))?> <span data-studio-discount>0.00</span></dd></div>
            <div><dt>Tax</dt><dd><?=e((string)(settings()['currency_code'] ?? 'USD'))?> <span data-studio-tax>0.00</span></dd></div>
            <div><dt>Delivery</dt><dd><?=e((string)(settings()['currency_code'] ?? 'USD'))?> <span data-studio-delivery>0.00</span></dd></div>
            <div class="studio-total"><dt>Total</dt><dd><?=e((string)(settings()['currency_code'] ?? 'USD'))?> <span data-studio-total>0.00</span></dd></div>
        </dl>
        <div class="studio-assurance"><strong>Review before sending</strong><span>Drafts stay private. Issuing activates the customer link.</span></div>
        <div class="studio-delivery-warning" data-delivery-warning hidden><strong>Delivery confirmation needed</strong><span>Add the address and agreed fee before issuing. Saving a draft is still available.</span></div>
        <div class="studio-readiness" aria-live="polite">
            <div class="studio-readiness-head"><div><span class="section-kicker">DOCUMENT READINESS</span><strong><span data-readiness-score>0</span>% complete</strong></div><span class="studio-ready-mark">✓</span></div>
            <div class="studio-readiness-bar" aria-hidden="true"><i data-readiness-progress></i></div>
            <ul><li data-readiness="customer">Customer selected</li><li data-readiness="items">At least one valid item</li><li data-readiness="delivery">Delivery or pickup confirmed</li></ul>
        </div>
        <button class="button primary studio-issue" type="submit" name="next_action" value="issue" <?=($document && $document['status'] !== 'draft') ? 'disabled' : ''?>>Save &amp; issue <?=e($isQuotation ? 'quotation' : 'invoice')?></button>
        <button class="button secondary studio-draft" type="submit" name="next_action" value="draft" <?=($document && $document['status'] !== 'draft') ? 'disabled' : ''?>>Save draft</button>
        <a class="studio-cancel" href="<?=$documentId ? 'index.php?page=document-view&amp;id='.$documentId : 'index.php?page='.($isQuotation ? 'quotations' : 'invoices')?>">Cancel</a>
    </aside>

    <template data-studio-item-template>
        <div class="studio-item" data-studio-item>
            <div class="studio-item-product">
                <select data-item-product aria-label="Product"><option value="">Custom product or service</option><?php foreach ($groupedProducts as $category => $categoryProducts):?><optgroup label="<?=e($category)?>"><?php foreach ($categoryProducts as $product):?><option value="<?=$product['id']?>" data-name="<?=e((string)$product['name'])?>" data-price="<?=e((string)$product['unit_price'])?>" data-tax="<?=e((string)$product['tax_rate'])?>"><?=e((string)$product['name'])?></option><?php endforeach;?></optgroup><?php endforeach;?></select>
                <input data-item-description placeholder="Description" aria-label="Line description">
            </div>
            <label><span>Qty</span><input type="number" min="0.01" step="0.01" value="1" inputmode="decimal" data-item-qty></label>
            <label><span>Price</span><input type="number" min="0" step="0.01" inputmode="decimal" data-item-price></label>
            <label><span>Tax %</span><input type="number" min="0" step="0.01" value="<?=e((string)(settings()['default_tax_rate'] ?? 0))?>" inputmode="decimal" data-item-tax></label>
            <strong data-item-total>USD 0.00</strong>
            <button type="button" class="studio-remove" data-remove-studio-item aria-label="Remove line">×</button>
        </div>
    </template>
</form>
<?php render_footer();?>
