import 'dart:async';
import 'dart:io';

import 'package:app_links/app_links.dart';
import 'package:comwell_key_app/base/base_cubit.dart';
import 'package:comwell_key_app/presentation/app/app_events.dart';
import 'package:comwell_key_app/utils/secure_storage.dart';
import 'package:comwell_key_app/utils/uri_utils.dart';
import 'package:comwell_key_app/domain/models/app_error.dart';
import 'package:device_info_plus/device_info_plus.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:package_info_plus/package_info_plus.dart';

part '../../../.generated/presentation/app/bloc/app_cubit.freezed.dart';

class AppCubit extends BaseCubit<AppState> {
  final ComwellPreferences _comwellPreferences;

  AppCubit(this._comwellPreferences) : super(const AppState()) {
    _init();
  }

  late final StreamSubscription<Uri> _appLinksSubscription;

  void _init() {
    _appLinksSubscription = AppLinks().uriLinkStream.listen((uri) async {
      if (uri.isDeeplink) {
        navigate(uri);
      }
    });
    cacheUserAgent();
  }

  void navigate(Uri uri) {
    safeEmit(state.copyWith(event: Navigate(uri)));
  }

  Future<void> cacheUserAgent() async {
    try {
      final packageInfo = await PackageInfo.fromPlatform();
      final String osVersion;
      if (Platform.isAndroid) {
        final deviceInfo = await DeviceInfoPlugin().androidInfo;
        osVersion = deviceInfo.version.sdkInt.toString();
      } else {
        final deviceInfo = await DeviceInfoPlugin().iosInfo;
        osVersion = deviceInfo.systemVersion;
      }

      final platform = Platform.isAndroid ? 'android' : 'ios';
      final versionCode = packageInfo.buildNumber;
      final versionName = packageInfo.version;
      await _comwellPreferences.setUserAgent(
        "ComwellKeyApp/$versionName ($platform; OS $osVersion; Build $versionCode)",
      );
    } catch (e, st) {
      logError(e, st);
    }
  }

  @override
  Future<void> close() async {
    await _appLinksSubscription.cancel();
    return super.close();
  }
}

@freezed
abstract class AppState with _$AppState {
  const factory AppState({
    @Default(false) bool isLoading,
    @Default(AppError.none) AppError error,
    @Default(null) AppEvent? event,
  }) = _AppState;
}