<?php
declare(strict_types=1);
require __DIR__.'/app/bootstrap.php';require_permission('tax.einvoice.submit');require __DIR__.'/app/layout.php';
$pdo=db();$companyId=company_id();
function uuid_v4():string{$d=random_bytes(16);$d[6]=chr((ord($d[6])&0x0f)|0x40);$d[8]=chr((ord($d[8])&0x3f)|0x80);return vsprintf('%s%s-%s-%s-%s-%s%s%s',str_split(bin2hex($d),4));}
function xml_e(string $v):string{return htmlspecialchars($v,ENT_XML1|ENT_QUOTES,'UTF-8');}
function tlv_b64(array $values):string{$out='';foreach($values as $tag=>$value){$value=(string)$value;$out.=chr((int)$tag).chr(strlen($value)).$value;}return base64_encode($out);}
if(isset($_GET['download'])){$id=(int)$_GET['download'];$q=$pdo->prepare('SELECT * FROM electronic_invoices WHERE id=? AND company_id=?');$q->execute([$id,$companyId]);$e=$q->fetch();$base=realpath(__DIR__.'/uploads/einvoices');$path=$e?realpath(__DIR__.'/'.$e['xml_path']):false;if(!$e||!$base||!$path||!str_starts_with($path,$base.DIRECTORY_SEPARATOR)){http_response_code(404);exit('الملف غير موجود.');}header('Content-Type: application/xml; charset=UTF-8');header('Content-Disposition: attachment; filename="invoice-'.$e['uuid'].'.xml"');readfile($path);exit;}
if($_SERVER['REQUEST_METHOD']==='POST'){verify_csrf();try{$action=(string)($_POST['action']??'');
 if($action==='prepare'){$invoiceId=(int)($_POST['invoice_id']??0);$q=$pdo->prepare("SELECT si.*,bp.legal_name_ar customer_name,bp.vat_registration_no customer_vat,c.legal_name_ar seller_name,c.vat_registration_no seller_vat,c.address_line,c.city FROM sales_invoices si JOIN customers cu ON cu.id=si.customer_id JOIN business_partners bp ON bp.id=cu.partner_id JOIN companies c ON c.id=si.company_id WHERE si.id=? AND si.company_id=? AND si.status IN ('issued','partially_collected','collected','overdue')");$q->execute([$invoiceId,$companyId]);$inv=$q->fetch();if(!$inv)throw new RuntimeException('الفاتورة غير متاحة للتجهيز الإلكتروني.');if(!$inv['seller_vat'])throw new RuntimeException('أدخل الرقم الضريبي للشركة أولًا.');if((int)scalar('SELECT COUNT(*) FROM electronic_invoices WHERE sales_invoice_id=?',[$invoiceId]))throw new RuntimeException('سبق تجهيز هذه الفاتورة إلكترونيًا.');$uuid=uuid_v4();$timestamp=$inv['invoice_date'].'T'.date('H:i:s').'Z';$qr=tlv_b64([1=>$inv['seller_name'],2=>$inv['seller_vat'],3=>$timestamp,4=>number_format((float)$inv['gross_amount'],2,'.',''),5=>number_format((float)$inv['tax_amount'],2,'.','')]);$lines=$pdo->prepare('SELECT * FROM sales_invoice_items WHERE sales_invoice_id=? ORDER BY id');$lines->execute([$invoiceId]);$lineXml='';foreach($lines->fetchAll() as $i=>$l){$lineXml.='<cac:InvoiceLine><cbc:ID>'.($i+1).'</cbc:ID><cbc:InvoicedQuantity unitCode="PCE">'.xml_e((string)$l['quantity']).'</cbc:InvoicedQuantity><cbc:LineExtensionAmount currencyID="SAR">'.number_format((float)$l['line_total']-(float)$l['tax_amount'],2,'.','').'</cbc:LineExtensionAmount><cac:Item><cbc:Name>'.xml_e((string)$l['description']).'</cbc:Name></cac:Item><cac:Price><cbc:PriceAmount currencyID="SAR">'.number_format((float)$l['unit_price'],4,'.','').'</cbc:PriceAmount></cac:Price></cac:InvoiceLine>';}$xml='<?xml version="1.0" encoding="UTF-8"?><Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2" xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2" xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2"><cbc:ProfileID>reporting:1.0</cbc:ProfileID><cbc:ID>'.xml_e((string)$inv['invoice_no']).'</cbc:ID><cbc:UUID>'.$uuid.'</cbc:UUID><cbc:IssueDate>'.xml_e((string)$inv['invoice_date']).'</cbc:IssueDate><cbc:InvoiceTypeCode name="0100000">388</cbc:InvoiceTypeCode><cbc:DocumentCurrencyCode>SAR</cbc:DocumentCurrencyCode><cac:AccountingSupplierParty><cac:Party><cac:PartyName><cbc:Name>'.xml_e((string)$inv['seller_name']).'</cbc:Name></cac:PartyName><cac:PartyTaxScheme><cbc:CompanyID>'.xml_e((string)$inv['seller_vat']).'</cbc:CompanyID></cac:PartyTaxScheme></cac:Party></cac:AccountingSupplierParty><cac:AccountingCustomerParty><cac:Party><cac:PartyName><cbc:Name>'.xml_e((string)$inv['customer_name']).'</cbc:Name></cac:PartyName></cac:Party></cac:AccountingCustomerParty><cac:TaxTotal><cbc:TaxAmount currencyID="SAR">'.number_format((float)$inv['tax_amount'],2,'.','').'</cbc:TaxAmount></cac:TaxTotal><cac:LegalMonetaryTotal><cbc:LineExtensionAmount currencyID="SAR">'.number_format((float)$inv['subtotal'],2,'.','').'</cbc:LineExtensionAmount><cbc:TaxInclusiveAmount currencyID="SAR">'.number_format((float)$inv['gross_amount'],2,'.','').'</cbc:TaxInclusiveAmount><cbc:PayableAmount currencyID="SAR">'.number_format((float)$inv['net_due_amount'],2,'.','').'</cbc:PayableAmount></cac:LegalMonetaryTotal>'.$lineXml.'</Invoice>';$dir=__DIR__.'/uploads/einvoices';if(!is_dir($dir)&&!mkdir($dir,0750,true))throw new RuntimeException('تعذر إنشاء مجلد الفواتير الإلكترونية.');$stored=$uuid.'.xml';if(file_put_contents($dir.'/'.$stored,$xml,LOCK_EX)===false)throw new RuntimeException('تعذر حفظ ملف XML.');$hash=base64_encode(hash('sha256',$xml,true));$pdo->prepare("INSERT INTO electronic_invoices(company_id,sales_invoice_id,uuid,invoice_hash,qr_code_base64,xml_path,clearance_status,created_at,updated_at) VALUES (?,?,?,?,?,?,'not_started',NOW(),NOW())")->execute([$companyId,$invoiceId,$uuid,$hash,$qr,'uploads/einvoices/'.$stored]);$id=(int)$pdo->lastInsertId();audit('einvoice.prepare','electronic_invoice',(string)$id,['uuid'=>$uuid]);flash('success','تم تجهيز XML وQR. يلزم توقيعه بشهادة جهاز الهيئة قبل الإرسال.');
 }elseif($action==='record_submission'){$id=(int)($_POST['id']??0);$status=(string)($_POST['status']??'');if(!in_array($status,['cleared','reported','warning','rejected','failed'],true))throw new RuntimeException('نتيجة الإرسال غير صالحة.');$q=$pdo->prepare('SELECT * FROM electronic_invoices WHERE id=? AND company_id=?');$q->execute([$id,$companyId]);$e=$q->fetch();if(!$e)throw new RuntimeException('الفاتورة الإلكترونية غير موجودة.');$success=in_array($status,['cleared','reported','warning'],true)?1:0;$submissionType=$status==='reported'?'reporting':'clearance';$pdo->beginTransaction();$pdo->prepare('INSERT INTO electronic_invoice_submissions(electronic_invoice_id,submission_type,request_id,response_status_code,response_payload,errors_json,submitted_at,completed_at,is_success,retry_no) VALUES (?,?,?,?,?,?,NOW(),NOW(),?,?)')->execute([$id,$submissionType,trim((string)($_POST['request_id']??''))?:null,(int)($_POST['response_status_code']??0)?:null,json_encode(['status'=>$status],JSON_UNESCAPED_UNICODE),$success?null:json_encode([trim((string)($_POST['message']??''))],JSON_UNESCAPED_UNICODE),$success,(int)scalar('SELECT COUNT(*) FROM electronic_invoice_submissions WHERE electronic_invoice_id=?',[$id])]);$pdo->prepare('UPDATE electronic_invoices SET clearance_status=?,cleared_or_reported_at=IF(? IN (\'cleared\',\'reported\'),NOW(),cleared_or_reported_at),last_error_message=? WHERE id=?')->execute([$status,$status,$success?null:trim((string)($_POST['message']??'')),$id]);$zatca=in_array($status,['cleared','reported','warning','rejected'],true)?$status:'pending';$pdo->prepare('UPDATE sales_invoices SET zatca_status=? WHERE id=?')->execute([$zatca,$e['sales_invoice_id']]);$pdo->commit();audit('einvoice.submission_result','electronic_invoice',(string)$id,['status'=>$status]);flash($success?'success':'error','تم تسجيل نتيجة الربط: '.$status);
 }}catch(Throwable $e){if($pdo->inTransaction())$pdo->rollBack();flash('error',$e instanceof PDOException?'سبق تجهيز الفاتورة أو البيانات غير مكتملة.':$e->getMessage());}redirect('einvoicing.php');}
$available=$pdo->prepare("SELECT si.id,si.invoice_no,si.invoice_date,si.gross_amount,bp.legal_name_ar customer_name FROM sales_invoices si JOIN customers c ON c.id=si.customer_id JOIN business_partners bp ON bp.id=c.partner_id WHERE si.company_id=? AND si.status IN ('issued','partially_collected','collected','overdue') AND NOT EXISTS(SELECT 1 FROM electronic_invoices ei WHERE ei.sales_invoice_id=si.id) ORDER BY si.id DESC");$available->execute([$companyId]);$available=$available->fetchAll();$electronic=$pdo->prepare("SELECT ei.*,si.invoice_no,si.invoice_date,si.gross_amount,bp.legal_name_ar customer_name,(SELECT COUNT(*) FROM electronic_invoice_submissions es WHERE es.electronic_invoice_id=ei.id) attempts FROM electronic_invoices ei JOIN sales_invoices si ON si.id=ei.sales_invoice_id JOIN customers c ON c.id=si.customer_id JOIN business_partners bp ON bp.id=c.partner_id WHERE ei.company_id=? ORDER BY ei.id DESC");$electronic->execute([$companyId]);$electronic=$electronic->fetchAll();
render_header('einvoicing','الفاتورة الإلكترونية','تجهيز XML وQR ومتابعة نتيجة الربط مع هيئة الزكاة والضريبة.');?>
<div class="alert error">الإرسال المباشر يتطلب شهادة جهاز (CSID) ومفتاحًا خاصًا صادرين للشركة. النظام لا ينشئ أو يخزن بيانات اعتماد افتراضية.</div><details class="panel quick-add" open><summary>＋ تجهيز فاتورة إلكترونية</summary><form method="post"><?= csrf_field() ?><input type="hidden" name="action" value="prepare"><label>الفاتورة الصادرة<select name="invoice_id"><?php foreach($available as $i):?><option value="<?= (int)$i['id'] ?>"><?= e($i['invoice_no'].' — '.$i['customer_name'].' — '.number_format((float)$i['gross_amount'],2)) ?></option><?php endforeach;?></select></label><button class="primary-btn">إنشاء UUID وXML وQR</button></form></details>
<section class="panel data-card"><header><h2>سجل الفواتير الإلكترونية</h2></header><div class="responsive-table"><table><thead><tr><th>الفاتورة</th><th>العميل</th><th>UUID</th><th>الإجمالي</th><th>المحاولات</th><th>الحالة</th><th>XML</th><th>تسجيل النتيجة</th></tr></thead><tbody><?php foreach($electronic as $e):?><tr><td><?= e($e['invoice_no']) ?></td><td><?= e($e['customer_name']) ?></td><td><code><?= e($e['uuid']) ?></code></td><td><?= number_format((float)$e['gross_amount'],2) ?></td><td><?= (int)$e['attempts'] ?></td><td><span class="chip"><?= e($e['clearance_status']) ?></span></td><td><a href="?download=<?= (int)$e['id'] ?>">تنزيل</a></td><td><?php if(!in_array($e['clearance_status'],['cleared','reported'],true)):?><form method="post"><?= csrf_field() ?><input type="hidden" name="action" value="record_submission"><input type="hidden" name="id" value="<?= (int)$e['id'] ?>"><select name="status"><option value="cleared">Cleared</option><option value="reported">Reported</option><option value="warning">Warning</option><option value="rejected">Rejected</option><option value="failed">Failed</option></select><input name="request_id" placeholder="Request ID"><input type="number" name="response_status_code" placeholder="HTTP"><input name="message" placeholder="الرسالة"><button>حفظ</button></form><?php endif;?></td></tr><?php endforeach;?></tbody></table></div></section>
<?php render_footer();
