import 'dart:developer';

import 'package:hub/features/module/index.dart';
import 'package:hub/features/storage/index.dart';
import 'package:hub/shared/extensions/string_extensions.dart';
import 'package:sqflite/sqflite.dart';

abstract class LicenseLocalDataSource {
  Future<void> init();

  Future<void> setDisplayByKey(final List<String> key, final String display);

  Future<bool> isNewVersion();

  Future<String?> get(String key);

  Future<bool> set<T>(String key, T value);

  Future<void> del(String key);

  Future<bool> setupLicense(bool isNewVersion);

  Future<List<String>> getLicense();

  Future<void> clear();
}

class LicenseLocalDataSourceImpl implements LicenseLocalDataSource {
  Database? _database;

  static final LicenseLocalDataSourceImpl _instance =
      LicenseLocalDataSourceImpl._internal();

  factory LicenseLocalDataSourceImpl(Database database) {
    _instance._database ??= database;
    return _instance;
  }

  LicenseLocalDataSourceImpl._internal();

  @override
  Future<void> init() async {
    await DatabaseService.instance.init();
  }

  @override
  Future<bool> setupLicense(bool isNewVersion) async {
    log('Setting up license...');
    try {
      final License license = await License.getLicense(isNewVersion);

      final List<String> inactiveModuleKey = license.modules
          .where((module) => module.display == ModuleStatus.inactive.key)
          .map((module) => module.key)
          .toList();

      final List<String> activeModuleKey = license.modules
          .where((module) => module.display == ModuleStatus.active.key)
          .map((module) => module.key)
          .toList();

      final List<String> disabledModuleKey = license.modules
          .where((module) => module.display == ModuleStatus.disabled.key)
          .map((module) => module.key)
          .toList();

      await setDisplayByKey(inactiveModuleKey, 'INVISIVEL');
      await setDisplayByKey(activeModuleKey, 'VISIVEL');
      await setDisplayByKey(disabledModuleKey, 'DESABILITADO');

      return true;
    } catch (e, s) {
      log('Erro ao configurar licenças: $e', stackTrace: s);
      return false;
    }
  }

  @override
  Future<void> setDisplayByKey(
      final List<String> keys, final String display) async {
    if (keys.isEmpty) return;
    final validKeys = keys.where((key) => key.isNotEmpty).toList();
    for (var key in validKeys) {
      await set(key, {
        'display': display,
        'expirationDate': '',
        'startDate': '',
        'quantity': '',
      });
    }
  }

  @override
  Future<bool> isNewVersion() async {
    final String? reponse =
        await StorageHelper().get(LocalsStorageKey.isNewVersion.key);
    final bool isNewVersion = reponse.toBoolean();
    return isNewVersion;
  }

  @override
  Future<String?> get(String key) async {
    var response = await _instance._database
        ?.query(tableLicense, where: 'key = ?', whereArgs: [key]);
    if (response!.isEmpty) {
      return null;
    }

    return response.toString();
  }

  @override
  Future<bool> set<T>(String key, T value) async {
    value as Map<String, dynamic>;
    if (value.isEmpty) return false;
    if (key == 'null') return false;

    await _instance._database?.rawInsert(
      'INSERT OR REPLACE INTO $tableLicense (key, display, expirationDate, startDate, quantity) VALUES (?, ?, ?, ?, ?)',
      [
        key,
        value['display'],
        value['expirationDate'],
        value['startDate'],
        value['quantity']
      ],
    );
    return true;
  }

  @override
  Future<void> del(String key) async {
    await _instance._database
        ?.delete(tableLicense, where: 'key = ?', whereArgs: [key]);
  }

  @override
  Future<void> clear() async {
    await _instance._database?.delete(tableLicense);
  }

  @override
  Future<List<String>> getLicense() async {
    var response =
        await _instance._database?.query(tableLicense, columns: ['key']);
    if (response!.isEmpty) {
      return [];
    }
    return response.map((e) => e.toString()).toList();
  }
}
