import 'dart:async';
import 'dart:convert';

import 'package:color/color.dart';
import 'package:dart_framework/utils/string_util.dart';
import 'package:dart_framework/utils/system_util.dart';
import 'package:http/http.dart' as http;
import 'package:oto/oto/utils/mattermost/mattermost_data.dart';

enum MattermostBuildType { android, ios, windows, mac, web }

class MattermostSender {
  final String token;
  final String url;

  MattermostSender(this.token, this.url);

  Future sendData(DataMattermost message,
      {String? defaultChannelId,
      Function(String)? completeListener,
      Function(Object)? errorListener}) async {
    return sendMap(message.toPostJson(defaultChannelId: defaultChannelId),
        completeListener: completeListener, errorListener: errorListener);
  }

  Future sendMap(Map<String, dynamic> payload,
      {Function(String)? completeListener,
      Function(Object)? errorListener}) async {
    return send(jsonEncode(payload),
        completeListener: completeListener, errorListener: errorListener);
  }

  Future send(String jsonString,
      {Function(String)? completeListener,
      Function(Object)? errorListener}) async {
    final decoded = jsonDecode(jsonString);
    if (decoded is! Map) {
      throw Exception('Mattermost payload must be a JSON object.');
    }

    final payload = normalizeMattermostPost(Map<String, dynamic>.from(decoded));
    final header = {
      'Content-Type': 'application/json',
      'Authorization': 'Bearer $token',
    };
    final encoded = jsonEncode(payload);
    print(encoded);
    final response =
        await http.post(Uri.parse(url), headers: header, body: encoded);

    print(response.statusCode);

    if (response.statusCode >= 200 && response.statusCode < 300) {
      print(response.body);
      if (completeListener != null) {
        completeListener(response.body);
      }
    } else {
      print(response.body);
      if (errorListener != null) {
        errorListener(response);
      }
      throw Exception(
          'Mattermost post failed (${response.statusCode}): ${response.body}');
    }

    return simpleFuture;
  }

  Future sendBuild(String appName, MattermostBuildType buildType, Color color,
      String version, String downloadURL,
      {required String channelId}) async {
    final buildURL = 'https://toki-labs.com/cdn/build/';
    final thumbUrl = buildType == MattermostBuildType.android
        ? '${buildURL}android.png'
        : '${buildURL}appstore.png';
    final projectIcon = '$buildURL$appName/icon.png';
    final buildTypeStr = buildTypeToString(buildType);
    final osColor =
        buildType == MattermostBuildType.ios ? '#ED145B' : '#81CA3F';

    final message = DataMattermost()
      ..channel_id = channelId
      ..message = '${toPascal(appName)} $buildTypeStr build is ready.'
      ..props = {
        'attachments': [
          MattermostAttachment()
            ..color = color.toHexColor().toCssString()
            ..fields = [
              MattermostField.withParam(
                  toPascal(appName), 'App: ${toPascal(appName)}')
            ],
          MattermostAttachment()
            ..color = osColor
            ..author_name = buildTypeStr
            ..author_icon = thumbUrl
            ..thumb_url = projectIcon
            ..title = 'Download'
            ..title_link = downloadURL
            ..text =
                'Successfully built $buildTypeStr binary file.\nBuild version: **$version**'
            ..fields = [MattermostField.withParam('Download URL', downloadURL)],
        ].map((item) => item.toJson()).toList(),
      };

    return sendData(message);
  }

  String buildTypeToString(MattermostBuildType type) {
    final typeStr = type.name;
    return typeStr == 'ios' ? 'iOS' : toPascal(typeStr);
  }
}
