import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import '../bloc/app/app_cubit.dart'; import '../bloc/app/app_state.dart'; import '../bloc/etiquetas/etiquetas_cubit.dart'; import '../bloc/etiquetas/etiquetas_state.dart'; import '../../domain/entities/destino.dart'; import '../../domain/entities/biblioteca.dart'; import '../../data/repositories/config_repository.dart'; class ConfigPage extends StatelessWidget { const ConfigPage({super.key}); @override Widget build(BuildContext context) { return Scaffold( body: ListView( padding: const EdgeInsets.all(16), children: [ // Destinos section Card( child: Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ const Icon(Icons.cloud_upload), const SizedBox(width: 8), const Text( 'Destinos', style: TextStyle( fontWeight: FontWeight.bold, fontSize: 18, ), ), const Spacer(), IconButton( icon: const Icon(Icons.add), onPressed: () => _showDestinoDialog(context), ), ], ), const SizedBox(height: 8), BlocBuilder( builder: (context, state) { if (state.destinos.isEmpty) { return const Padding( padding: EdgeInsets.all(16), child: Text('No hay destinos configurados'), ); } return Column( children: state.destinos.map((destino) { final isActive = state.destinoActivo?.id == destino.id; return ListTile( leading: Icon( isActive ? Icons.radio_button_checked : Icons.radio_button_off, color: isActive ? Theme.of(context).colorScheme.primary : null, ), title: Text(destino.nombre), subtitle: Text( destino.url, maxLines: 1, overflow: TextOverflow.ellipsis, ), trailing: IconButton( icon: const Icon(Icons.delete_outline), onPressed: () => context.read().removeDestino(destino.id!), ), onTap: () => context.read().setDestinoActivo(destino), ); }).toList(), ); }, ), ], ), ), ), const SizedBox(height: 16), // Bibliotecas section Card( child: Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ const Icon(Icons.library_books), const SizedBox(width: 8), const Text( 'Bibliotecas', style: TextStyle( fontWeight: FontWeight.bold, fontSize: 18, ), ), const Spacer(), IconButton( icon: const Icon(Icons.add), onPressed: () => _showBibliotecaDialog(context), ), ], ), const SizedBox(height: 8), BlocBuilder( builder: (context, state) { if (state.bibliotecas.isEmpty) { return const Padding( padding: EdgeInsets.all(16), child: Text('No hay bibliotecas configuradas'), ); } return Column( children: state.bibliotecas.map((bib) { final etiquetas = state.etiquetasPorBiblioteca[bib.id] ?? []; return ListTile( leading: const Icon(Icons.folder), title: Text(bib.nombre), subtitle: Text( '${bib.url}${bib.endpoint}\n${etiquetas.length} etiquetas en cache', ), isThreeLine: true, trailing: IconButton( icon: const Icon(Icons.sync), onPressed: () => context.read().syncBiblioteca(bib.id!), ), ); }).toList(), ); }, ), ], ), ), ), const SizedBox(height: 16), // App info Card( child: Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Row( children: [ Icon(Icons.info_outline), SizedBox(width: 8), Text( 'Información', style: TextStyle( fontWeight: FontWeight.bold, fontSize: 18, ), ), ], ), const SizedBox(height: 16), const ListTile( title: Text('Packet'), subtitle: Text('v1.0.0'), leading: Icon(Icons.apps), ), const ListTile( title: Text('Biblioteca HST'), subtitle: Text('tzrtech.org'), leading: Icon(Icons.link), ), ], ), ), ), ], ), ); } void _showDestinoDialog(BuildContext context) { final nombreController = TextEditingController(); final urlController = TextEditingController(); final hashController = TextEditingController(); showDialog( context: context, builder: (ctx) => AlertDialog( title: const Text('Nuevo Destino'), content: SingleChildScrollView( child: Column( mainAxisSize: MainAxisSize.min, children: [ TextField( controller: nombreController, decoration: const InputDecoration(labelText: 'Nombre'), ), const SizedBox(height: 12), TextField( controller: urlController, decoration: const InputDecoration( labelText: 'URL', hintText: 'https://api.example.com', ), ), const SizedBox(height: 12), TextField( controller: hashController, decoration: const InputDecoration( labelText: 'Llave (hash 64 chars)', ), ), ], ), ), actions: [ TextButton( onPressed: () => Navigator.pop(ctx), child: const Text('Cancelar'), ), FilledButton( onPressed: () { if (nombreController.text.isNotEmpty && urlController.text.isNotEmpty && hashController.text.length == 64) { context.read().addDestino(Destino( nombre: nombreController.text, url: urlController.text, hash: hashController.text, )); Navigator.pop(ctx); } }, child: const Text('Guardar'), ), ], ), ); } void _showBibliotecaDialog(BuildContext context) { final nombreController = TextEditingController(); final urlController = TextEditingController(); final endpointController = TextEditingController(text: '/api/tags'); final configRepo = ConfigRepository(); showDialog( context: context, builder: (ctx) => AlertDialog( title: const Text('Nueva Biblioteca'), content: SingleChildScrollView( child: Column( mainAxisSize: MainAxisSize.min, children: [ TextField( controller: nombreController, decoration: const InputDecoration(labelText: 'Nombre'), ), const SizedBox(height: 12), TextField( controller: urlController, decoration: const InputDecoration( labelText: 'URL', hintText: 'https://example.com', ), ), const SizedBox(height: 12), TextField( controller: endpointController, decoration: const InputDecoration(labelText: 'Endpoint'), ), ], ), ), actions: [ TextButton( onPressed: () => Navigator.pop(ctx), child: const Text('Cancelar'), ), FilledButton( onPressed: () async { if (nombreController.text.isNotEmpty && urlController.text.isNotEmpty) { await configRepo.insertBiblioteca(Biblioteca( nombre: nombreController.text, url: urlController.text, endpoint: endpointController.text, )); if (ctx.mounted) { Navigator.pop(ctx); context.read().init(); } } }, child: const Text('Guardar'), ), ], ), ); } }