import 'package:html/dom.dart';
import 'package:html/parser.dart';

String htmlToSimpleText(String htmlContentFragment) {
  try {
    final dom = parseFragment(htmlContentFragment);
    final segments = dom.nodes
        .map((n) => n is Element ? n.elementToEditText() : n.nodeToEditText())
        .toList();
    return segments.join('');
  } catch (e) {
    return htmlContentFragment;
  }
}

extension NodeTextConverter on Node {
  String nodeToEditText() {
    if (nodes.isEmpty) {
      final stringWithQuotes = toString();
      final start = stringWithQuotes.startsWith('"') ? 1 : 0;
      final end = stringWithQuotes.endsWith('"')
          ? stringWithQuotes.length - 1
          : stringWithQuotes.length;
      return stringWithQuotes.substring(start, end);
    }

    final convertedNodes = nodes
        .map((n) => n is Element ? n.elementToEditText() : n.nodeToEditText())
        .toList();
    return convertedNodes.join('');
  }
}

extension ElementTextConverter on Element {
  String elementToEditText({int depth = 0}) {
    late final String innerText;
    late final String startText;
    late final String endText;
    switch (localName) {
      case 'a':
        startText = '';
        innerText = htmlLinkToString();
        endText = '';
        break;
      case 'br':
        startText = '';
        innerText = '';
        endText = '\n';
        break;
      case 'p':
        startText = '';
        innerText = buildInnerText(depth);
        endText = '\n';
        break;
      case 'em':
        startText = '*';
        innerText = buildInnerText(depth);
        endText = '*';
        break;
      case 'strong':
        startText = '**';
        innerText = buildInnerText(depth);
        endText = '**';
        break;
      case 'li':
        startText = '\n${buildTabs(depth)}- ';
        innerText = buildInnerText(depth);
        endText = '';
        break;
      case 'ul':
        startText = '';
        innerText = buildInnerText(depth + 1);
        endText = '';
        break;
      default:
        startText = '<$localName>';
        innerText = buildInnerText(depth);
        endText = '</$localName>';
    }

    return '$startText$innerText$endText';
  }

  String htmlLinkToString() {
    final attrs = attributes['class'] ?? '';
    if (attrs.contains('hashtag')) {
      return text;
    }

    if (attrs.contains('mention')) {
      final uri = Uri.parse(attributes['href'] ?? '');
      final host = uri.host;
      final username = text;
      return '$username@$host';
    }

    return attributes['href'] ?? 'No link found';
  }

  String buildInnerText(int depth) {
    if (nodes.isEmpty) {
      return '';
    }

    final convertedNodes = nodes
        .map((n) => n is Element
            ? n.elementToEditText(depth: depth)
            : n.nodeToEditText())
        .toList();
    return convertedNodes.join('');
  }

  String buildTabs(int depth) => depth == 0
      ? ''
      : List.generate(
          depth,
          (index) => '  ',
        ).join('');
}
