import 'dart:convert';

import 'package:dio/dio.dart';

import '../../contracts/app_update.dart';
import '../emby_api/emby_headers.dart';

const String kSmPlayerReleaseOwner = 'YOUR_GITHUB_OWNER';
const String kSmPlayerReleaseRepo = 'YOUR_GITHUB_REPO';


const String kSmPlayerManifestTag = '_manifests';

class GithubReleasesClient {
  static Uri _platformManifestUri(String platformKey) => Uri.parse(
    'https://github.com/$kSmPlayerReleaseOwner/$kSmPlayerReleaseRepo'
    '/releases/download/$kSmPlayerManifestTag/latest-$platformKey.json',
  );

  final Dio _dio;

  GithubReleasesClient({Dio? dio})
    : _dio =
          dio ??
          Dio(
            BaseOptions(
              connectTimeout: const Duration(seconds: 8),
              receiveTimeout: const Duration(seconds: 15),
              responseType: ResponseType.json,
              headers: {
                'Accept': 'application/json',
                'User-Agent': EmbyRequestHeaders.userAgent,
              },
            ),
          );

  Future<AppUpdateInfo> fetchLatestRelease({
    required String platformKey,
  }) async {
    final response = await _dio.get<dynamic>(
      _platformManifestUri(platformKey).toString(),
    );
    final data = response.data;

    final Map<String, dynamic> json;
    if (data is Map<String, dynamic>) {
      json = data;
    } else if (data is String) {
      final decoded = jsonDecode(data);
      if (decoded is! Map<String, dynamic>) {
        throw const FormatException('GitHub release JSON root is not a map');
      }
      json = decoded;
    } else {
      throw FormatException(
        'GitHub release JSON has unexpected type: ${data.runtimeType}',
      );
    }

    final platformAssets = <String, AppUpdateAsset>{};
    final rawPlatforms = json['platforms'];
    if (rawPlatforms is Map) {
      rawPlatforms.forEach((key, value) {
        if (value is Map<String, dynamic>) {
          final asset = AppUpdateAsset.fromJson(value);
          if (asset.name.isNotEmpty) {
            platformAssets[key.toString()] = asset;
          }
        }
      });
    }

    final assets = platformAssets.values.toList(growable: true);

    final rawAssets = json['assets'];
    if (rawAssets is List) {
      assets.addAll(
        rawAssets
            .whereType<Map<String, dynamic>>()
            .map(AppUpdateAsset.fromJson)
            .where((asset) => asset.name.isNotEmpty),
      );
    }

    final htmlUrl = _firstNonEmpty([
      json['html_url'],
      json['htmlUrl'],
      json['downloadUrl'],
      _latestReleasePageUrl,
    ]);
    return AppUpdateInfo(
      version: _firstNonEmpty([json['version'], json['tag_name']]),
      releaseNotes: _firstNonEmpty([json['notes'], json['body']]),
      htmlUrl: Uri.tryParse(htmlUrl) ?? Uri(),
      assets: assets,
      platformAssets: platformAssets,
    );
  }

  static String get _latestReleasePageUrl =>
      'https://github.com/$kSmPlayerReleaseOwner/$kSmPlayerReleaseRepo/releases/latest';

  static String _firstNonEmpty(Iterable<Object?> values) {
    return values
        .map((value) => value?.toString().trim() ?? '')
        .firstWhere((value) => value.isNotEmpty, orElse: () => '');
  }
}
