import 'package:flutter/material.dart'; import 'package:flutter_form_builder/flutter_form_builder.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; import '../../../../core/theme/app_colors.dart'; import '../../../../core/widgets/medical_modal.dart'; import '../../../insurance_auth/presentation/views/insurance_auth_modal_view.dart'; import '../../../prescription/presentation/views/prescription_modal_view.dart'; import '../../../referrals/presentation/views/department_referral_modal_view.dart'; import '../../../referrals/presentation/views/doctor_referral_modal_view.dart'; import '../../data/models/patient_model.dart'; import '../store/patient_store.dart'; import '../widgets/clinical_documents_dropdown.dart'; import '../widgets/patient_clinical_tabs.dart'; import '../widgets/patient_demographics_form.dart'; import '../widgets/secretary_appointment_section.dart'; class PatientModalView extends StatefulWidget { final PatientModel? initialPatient; final int? patientId; final ValueChanged? onSaved; final bool isSecretary; const PatientModalView({ super.key, this.initialPatient, this.patientId, this.onSaved, this.isSecretary = false, }); @override State createState() => _PatientModalViewState(); } class _PatientModalViewState extends State { late final PatientStore _store; final _formKey = GlobalKey(); @override void initState() { super.initState(); _store = PatientStore(); if (widget.initialPatient != null) { _store.populateFromModel(widget.initialPatient!); } else if (widget.patientId != null) { _store.loadPatient(widget.patientId!); } else { _store.initForCreate(); } } Future _handleSave() async { if (_formKey.currentState?.saveAndValidate() ?? false) { final values = _formKey.currentState!.value; if (values['nombre'] != null) _store.nombre = values['nombre'].toString(); if (values['apellido'] != null) _store.apellido = values['apellido'].toString(); if (values['cedula'] != null) _store.cedula = values['cedula'].toString(); if (values['telefono'] != null) _store.telefono = values['telefono'].toString(); if (values['direccion'] != null) _store.direccion = values['direccion'].toString(); if (values['ocupacion'] != null) _store.ocupacion = values['ocupacion'].toString(); if (values['edad'] != null) _store.edad = values['edad'].toString(); if (values['sexo'] != null) _store.sexo = values['sexo'].toString(); if (values['seguro'] != null) _store.seguro = values['seguro'].toString(); if (values['est_civil'] != null) _store.estCivil = values['est_civil'].toString(); final success = await _store.savePatient(); if (success && mounted) { if (widget.onSaved != null) { widget.onSaved!(_store.toModel()); } ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(_store.successMessage ?? 'Operación completada exitosamente'), backgroundColor: const Color(0xFF00A65A), behavior: SnackBarBehavior.floating, ), ); Navigator.of(context).pop(_store.toModel()); } } else { _store.errorMessage = 'Por favor complete los campos obligatorios resaltados en rojo.'; } } @override Widget build(BuildContext context) { return Observer( builder: (_) { final title = widget.isSecretary ? (_store.isEditing ? 'Ficha de Recepción' : 'Nuevo Registro de Paciente') : (_store.isEditing ? 'Editar Paciente' : 'Registro De Paciente'); final subtitle = widget.isSecretary ? 'Recepción, datos personales y programación de citas' : (_store.isEditing ? 'Actualizando ficha clínica del paciente ID: ${_store.id ?? ''}' : 'Ingrese los datos generales y antecedentes del paciente'); final mediaQuery = MediaQuery.sizeOf(context); final modalHeight = (mediaQuery.height * 0.92).clamp(740.0, 900.0); final modalWidth = (mediaQuery.width * 0.92).clamp(980.0, 1160.0); return MedicalModalDialog( maxWidth: modalWidth, maxHeight: modalHeight, title: title, titleIcon: Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( color: AppColors.primaryContainer, borderRadius: BorderRadius.circular(10), ), child: Icon( _store.isEditing ? Icons.edit_note_rounded : Icons.person_add_alt_1_rounded, color: AppColors.primary, size: 20, ), ), subtitle: Text( subtitle, maxLines: 1, overflow: TextOverflow.ellipsis, style: const TextStyle(fontSize: 12, color: AppColors.textMuted), ), actions: [ if (_store.estadoEspera == 'en_consulta') ...[ Container( height: 34, padding: const EdgeInsets.symmetric(horizontal: 10), decoration: BoxDecoration( color: const Color(0xFFE0F2FE), borderRadius: BorderRadius.circular(8), border: Border.all(color: const Color(0xFF7DD3FC)), ), alignment: Alignment.center, child: const Row( mainAxisSize: MainAxisSize.min, children: [ Icon(Icons.medical_services_rounded, size: 13, color: Color(0xFF0369A1)), SizedBox(width: 5), Text( 'En Consulta', style: TextStyle(fontSize: 11.5, fontWeight: FontWeight.w700, color: Color(0xFF0369A1)), ), ], ), ), const SizedBox(width: 8), ] else if (_store.estadoEspera == 'en_espera') ...[ Container( height: 34, padding: const EdgeInsets.symmetric(horizontal: 10), decoration: BoxDecoration( color: const Color(0xFFDCFCE7), borderRadius: BorderRadius.circular(8), border: Border.all(color: const Color(0xFF86EFAC)), ), alignment: Alignment.center, child: const Row( mainAxisSize: MainAxisSize.min, children: [ Icon(Icons.hourglass_top_rounded, size: 13, color: Color(0xFF15803D)), SizedBox(width: 5), Text( 'En Espera', style: TextStyle(fontSize: 11.5, fontWeight: FontWeight.w700, color: Color(0xFF15803D)), ), ], ), ), const SizedBox(width: 8), ] else if (_store.estadoEspera == 'atendido') ...[ Container( height: 34, padding: const EdgeInsets.symmetric(horizontal: 10), decoration: BoxDecoration( color: const Color(0xFFF1F5F9), borderRadius: BorderRadius.circular(8), border: Border.all(color: const Color(0xFFCBD5E1)), ), alignment: Alignment.center, child: const Row( mainAxisSize: MainAxisSize.min, children: [ Icon(Icons.check_circle_rounded, size: 13, color: Color(0xFF64748B)), SizedBox(width: 5), Text( 'Atendido', style: TextStyle(fontSize: 11.5, fontWeight: FontWeight.w600, color: Color(0xFF64748B)), ), ], ), ), const SizedBox(width: 8), ], if (!widget.isSecretary) ClinicalDocumentsDropdown( onSelect: (docType) { if (docType == ClinicalDocumentType.recetaMedica) { final patientName = '${_store.nombre} ${_store.apellido}'.trim(); showMedicalModal( context: context, builder: (modalCtx) => PrescriptionModalView( patientName: patientName.isNotEmpty ? patientName : 'Sin Nombre', ), ); } else if (docType == ClinicalDocumentType.autorizacionSeguro) { final patientName = '${_store.nombre} ${_store.apellido}'.trim(); final diagnosis = _store.diagnDesc.trim().isNotEmpty ? _store.diagnDesc.trim() : (_store.diagnDef.trim().isNotEmpty ? _store.diagnDef.trim() : null); showMedicalModal( context: context, builder: (modalCtx) => InsuranceAuthModalView( patientName: patientName.isNotEmpty ? patientName : 'Sin Nombre', initialDiagnosis: diagnosis, ), ); } else if (docType == ClinicalDocumentType.referirDoctor) { final patientName = '${_store.nombre} ${_store.apellido}'.trim(); showMedicalModal( context: context, builder: (modalCtx) => DoctorReferralModalView( patientName: patientName.isNotEmpty ? patientName : 'Sin Nombre', ), ); } else if (docType == ClinicalDocumentType.referirDepartamento) { final patientName = '${_store.nombre} ${_store.apellido}'.trim(); showMedicalModal( context: context, builder: (modalCtx) => DepartmentReferralModalView( patientName: patientName.isNotEmpty ? patientName : 'Sin Nombre', ), ); } }, ), ], bottomBar: Container( padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 12), decoration: const BoxDecoration( color: Color(0xFFF8FAFC), border: Border(top: BorderSide(color: Color(0xFFE2E8F0))), ), child: Row( children: [ Container( padding: const EdgeInsets.all(4), decoration: BoxDecoration( color: _store.errorMessage != null ? AppColors.error.withValues(alpha: 0.12) : (_store.successMessage != null ? const Color(0xFF00A65A).withValues(alpha: 0.12) : AppColors.primary.withValues(alpha: 0.1)), shape: BoxShape.circle, ), child: Icon( _store.errorMessage != null ? Icons.error_outline_rounded : (_store.successMessage != null ? Icons.check_circle_outline_rounded : Icons.info_outline_rounded), size: 15, color: _store.errorMessage != null ? AppColors.error : (_store.successMessage != null ? const Color(0xFF00A65A) : AppColors.primary), ), ), const SizedBox(width: 8), Expanded( child: Text( _store.errorMessage ?? (_store.successMessage ?? (_store.isSaving ? 'Guardando datos en el servidor...' : (_store.estadoEspera == 'en_consulta' ? 'Consulta médica activa · Al guardar pasará automáticamente a Atendido' : (_store.isEditing ? 'Realizando cambios en paciente' : 'Listo para registrar')))), style: TextStyle( fontSize: 12, fontWeight: FontWeight.w600, color: _store.errorMessage != null ? AppColors.error : (_store.successMessage != null ? const Color(0xFF00A65A) : AppColors.textSecondary), ), ), ), Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(6), border: Border.all(color: const Color(0xFFE2E8F0)), ), child: const Row( mainAxisSize: MainAxisSize.min, children: [ Icon(Icons.keyboard_outlined, size: 12, color: AppColors.textMuted), SizedBox(width: 4), Text( 'ESC para salir', style: TextStyle(fontSize: 11, color: AppColors.textMuted, fontWeight: FontWeight.w500), ), ], ), ), ], ), ), child: _store.isLoading ? const Center( child: Column( mainAxisSize: MainAxisSize.min, children: [ CircularProgressIndicator(strokeWidth: 3), SizedBox(height: 16), Text('Cargando ficha del paciente...', style: TextStyle(fontSize: 13)), ], ), ) : FormBuilder( key: _formKey, child: Column( children: [ PatientDemographicsForm( store: _store, formKey: _formKey, onSave: _handleSave, ), if (widget.isSecretary) Expanded( child: SingleChildScrollView( child: SecretaryAppointmentSection(store: _store), ), ) else Expanded( child: PatientClinicalTabs(store: _store), ), ], ), ), ); }, ); } }