import 'dart:typed_data'; import 'package:flutter/services.dart' show rootBundle; import 'package:intl/intl.dart'; import 'package:pdf/pdf.dart'; import 'package:pdf/widgets.dart' as pw; import 'package:printing/printing.dart'; class DepartmentReferralPdfService { /// Genera el documento PDF de Referimiento a Departamento en formato Media Carta Vertical /// (5.5 x 8.5 pulgadas / 396 x 612 pt). static Future buildDepartmentReferralPdf({ required String doctorName, required String specialty, required String subspecialty, required String generalContact, required String referralText, DateTime? date, pw.Font? fontRegular, pw.Font? fontBold, pw.Font? fontTitle, String? logoSvg, }) async { final pdf = pw.Document(title: 'Referir a Departamento'); final formattedDate = DateFormat('dd/MM/yyyy').format(date ?? DateTime.now()); // Formato Carta Vertical (8.5 x 11.0 pulgadas / 612 x 792 pt): // Todo el contenido abarca estrictamente la mitad superior de la hoja (5.5 pulgadas / 396 pt), // dejando la mitad inferior libre para corte o papel pre-cortado. const pageFormat = PdfPageFormat( 8.5 * PdfPageFormat.inch, 11.0 * PdfPageFormat.inch, marginLeft: 54, marginRight: 54, marginTop: 20, marginBottom: 20, ); // Tipografías estándar con fallback a fuentes base PDF si no hay conexión a internet pw.Font regular = fontRegular ?? pw.Font.helvetica(); pw.Font bold = fontBold ?? pw.Font.helveticaBold(); pw.Font titleFont = fontTitle ?? pw.Font.timesBoldItalic(); if (fontRegular == null || fontBold == null || fontTitle == null) { try { regular = await PdfGoogleFonts.robotoRegular(); bold = await PdfGoogleFonts.robotoBold(); titleFont = await PdfGoogleFonts.playfairDisplayItalic(); } catch (_) { regular = pw.Font.helvetica(); bold = pw.Font.helveticaBold(); titleFont = pw.Font.timesBoldItalic(); } } String? svgContent = logoSvg; if (svgContent == null) { try { svgContent = await rootBundle.loadString('assets/images/hidalyx_logo_blue.svg'); } catch (_) { svgContent = null; } } pdf.addPage( pw.Page( pageFormat: pageFormat, build: (pw.Context context) { return pw.Column( crossAxisAlignment: pw.CrossAxisAlignment.stretch, children: [ // Mitad superior de la hoja (máximo 5.5 pulgadas / 396 pt) pw.Container( height: 5.5 * PdfPageFormat.inch - 36, child: pw.Column( crossAxisAlignment: pw.CrossAxisAlignment.stretch, children: [ // 1. Cabecera con Nombre del Doctor y Badge Sutil de Hidalyx Med pw.Stack( children: [ pw.Align( alignment: pw.Alignment.center, child: pw.Column( children: [ pw.Text( doctorName.isNotEmpty ? doctorName : 'Dr. Luis A. Castro Sosa', style: pw.TextStyle( font: titleFont, fontSize: 22, fontWeight: pw.FontWeight.bold, color: PdfColor.fromHex('1E293B'), ), ), pw.SizedBox(height: 3), if (specialty.isNotEmpty) pw.Text( specialty.toUpperCase(), style: pw.TextStyle( font: bold, fontSize: 10.5, letterSpacing: 0.5, color: PdfColor.fromHex('0F172A'), ), ), if (subspecialty.isNotEmpty) ...[ pw.SizedBox(height: 2), pw.Text( subspecialty.toUpperCase(), textAlign: pw.TextAlign.center, style: pw.TextStyle( font: regular, fontSize: 8.5, color: PdfColor.fromHex('475569'), ), ), ], pw.SizedBox(height: 3), pw.Text( 'Fecha: $formattedDate', style: pw.TextStyle( font: regular, fontSize: 9.5, color: PdfColor.fromHex('334155'), ), ), ], ), ), // Badge sutil de Hidalyx Med en la esquina superior derecha pw.Positioned( top: 0, right: 0, child: pw.Row( mainAxisSize: pw.MainAxisSize.min, crossAxisAlignment: pw.CrossAxisAlignment.center, children: [ if (svgContent != null && svgContent.isNotEmpty) ...[ pw.Opacity( opacity: 0.6, child: pw.SvgImage( svg: svgContent, width: 7.5, height: 7.5, ), ), pw.SizedBox(width: 3), ], pw.Text( 'hidalyx.com', style: pw.TextStyle( font: regular, fontSize: 6.0, color: PdfColor.fromHex('94A3B8'), ), ), ], ), ), ], ), pw.SizedBox(height: 6), // Línea divisoria decorativa del membrete pw.Container( height: 1, color: PdfColor.fromHex('CBD5E1'), ), pw.SizedBox(height: 8), // 2. Contenido del Referimiento (Idéntico a AlfaMedical) pw.Expanded( child: pw.Container( padding: const pw.EdgeInsets.symmetric(vertical: 4), child: pw.Text( referralText.trim().isNotEmpty ? referralText.trim() : 'Sin detalles de referimiento.', style: pw.TextStyle( font: regular, fontSize: 10.5, lineSpacing: 3.5, color: PdfColor.fromHex('1E293B'), ), ), ), ), pw.SizedBox(height: 6), // 3. Pie de página con Contacto del Consultorio if (generalContact.isNotEmpty) ...[ pw.Container( padding: const pw.EdgeInsets.only(top: 4), child: pw.Text( generalContact.toUpperCase(), textAlign: pw.TextAlign.center, style: pw.TextStyle( font: regular, fontSize: 6.8, color: PdfColor.fromHex('64748B'), lineSpacing: 1.5, ), ), ), ], pw.SizedBox(height: 3), // Confirmación institucional pw.Center( child: pw.Text( 'Documento médico emitido electrónicamente', style: pw.TextStyle( font: regular, fontSize: 6.0, color: PdfColor.fromHex('94A3B8'), ), ), ), ], ), ), ], ); }, ), ); return pdf.save(); } /// Envía a imprimir directamente o abre el diálogo nativo de impresión/PDF. static Future printDepartmentReferral({ required String doctorName, required String specialty, required String subspecialty, required String generalContact, required String referralText, DateTime? date, }) async { final pdfBytes = await buildDepartmentReferralPdf( doctorName: doctorName, specialty: specialty, subspecialty: subspecialty, generalContact: generalContact, referralText: referralText, date: date, ); await Printing.layoutPdf( onLayout: (PdfPageFormat format) async => pdfBytes, name: 'Referimiento_Departamento', ); } }