import 'package:path/path.dart'; import 'package:sqflite/sqflite.dart'; import '../modelos/emisora.dart'; /// Servicio de persistencia de emisoras favoritas con SQLite. /// /// - Inicialización lazy: la BD se abre en el primer acceso. /// - Migration-ready: versión 2 añade campos de la Radio Browser API. class ServicioFavoritos { static const _dbName = 'pluriwave.db'; static const _dbVersion = 2; Database? _db; Future get _database async { _db ??= await _initDb(); return _db!; } Future _initDb() async { final dbPath = await getDatabasesPath(); final path = join(dbPath, _dbName); return openDatabase( path, version: _dbVersion, onCreate: _onCreate, onUpgrade: _onUpgrade, ); } Future _onCreate(Database db, int version) async { await db.execute(''' CREATE TABLE favoritos ( id INTEGER PRIMARY KEY AUTOINCREMENT, uuid TEXT NOT NULL UNIQUE, nombre TEXT NOT NULL, url TEXT NOT NULL, favicon TEXT, pais TEXT, codigo_pais TEXT, idioma TEXT, tags TEXT, codec TEXT, bitrate INTEGER, votes INTEGER NOT NULL DEFAULT 0, clickcount INTEGER NOT NULL DEFAULT 0, orden INTEGER NOT NULL DEFAULT 0 ) '''); } Future _onUpgrade(Database db, int oldVersion, int newVersion) async { if (oldVersion < 2) { // v1→v2: añadir columnas de la Radio Browser API await db.execute('ALTER TABLE favoritos ADD COLUMN codigo_pais TEXT'); await db.execute('ALTER TABLE favoritos ADD COLUMN codec TEXT'); await db.execute('ALTER TABLE favoritos ADD COLUMN bitrate INTEGER'); await db.execute('ALTER TABLE favoritos ADD COLUMN votes INTEGER NOT NULL DEFAULT 0'); await db.execute('ALTER TABLE favoritos ADD COLUMN clickcount INTEGER NOT NULL DEFAULT 0'); } } /// Devuelve todas las emisoras favoritas ordenadas por [orden]. Future> obtenerTodos() async { final db = await _database; final rows = await db.query('favoritos', orderBy: 'orden ASC'); return rows.map(Emisora.fromMap).toList(); } /// Añade una emisora a favoritos. Si ya existe (mismo uuid), la actualiza. Future agregar(Emisora emisora) async { final db = await _database; // Calcular el siguiente orden final maxOrden = Sqflite.firstIntValue( await db.rawQuery('SELECT MAX(orden) FROM favoritos'), ) ?? -1; final nuevaEmisora = emisora.copyWith(orden: maxOrden + 1); await db.insert( 'favoritos', nuevaEmisora.toMap(), conflictAlgorithm: ConflictAlgorithm.replace, ); } /// Elimina una emisora de favoritos por [uuid]. Future eliminar(String uuid) async { final db = await _database; await db.delete('favoritos', where: 'uuid = ?', whereArgs: [uuid]); } /// Devuelve true si la emisora con [uuid] está en favoritos. Future esFavorito(String uuid) async { final db = await _database; final count = Sqflite.firstIntValue( await db.rawQuery( 'SELECT COUNT(*) FROM favoritos WHERE uuid = ?', [uuid], ), ); return (count ?? 0) > 0; } /// Alterna el estado de favorito de una emisora. Future toggleFavorito(Emisora emisora) async { if (await esFavorito(emisora.uuid)) { await eliminar(emisora.uuid); return false; } else { await agregar(emisora); return true; } } /// Actualiza el orden de un favorito. Future reordenar(String uuid, int nuevoOrden) async { final db = await _database; await db.update( 'favoritos', {'orden': nuevoOrden}, where: 'uuid = ?', whereArgs: [uuid], ); } }