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<Database> get _database async {
    _db ??= await _initDb();
    return _db!;
  }

  Future<Database> _initDb() async {
    final dbPath = await getDatabasesPath();
    final path = join(dbPath, _dbName);
    return openDatabase(
      path,
      version: _dbVersion,
      onCreate: _onCreate,
      onUpgrade: _onUpgrade,
    );
  }

  Future<void> _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<void> _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<List<Emisora>> 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<void> 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<void> 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<bool> 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<bool> 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<void> reordenar(String uuid, int nuevoOrden) async {
    final db = await _database;
    await db.transaction((txn) async {
      final rows = await txn.query(
        'favoritos',
        columns: ['uuid'],
        orderBy: 'orden ASC, id ASC',
      );
      final uuids = rows.map((r) => r['uuid'] as String).toList();
      final oldIndex = uuids.indexOf(uuid);
      if (oldIndex == -1 || uuids.isEmpty) return;

      final targetIndex = nuevoOrden.clamp(0, uuids.length - 1);
      final moved = uuids.removeAt(oldIndex);
      uuids.insert(targetIndex, moved);

      for (var i = 0; i < uuids.length; i++) {
        await txn.update(
          'favoritos',
          {'orden': i},
          where: 'uuid = ?',
          whereArgs: [uuids[i]],
        );
      }
    });
  }
}
