part of '../document_viewer.dart';

class _SvgViewer extends StatelessWidget {
  final Uint8List bytes;
  final PyramidTheme pt;
  const _SvgViewer({required this.bytes, required this.pt});

  @override
  Widget build(BuildContext context) {
    return Center(
      child: InteractiveViewer(
        minScale: 0.5,
        maxScale: 10,
        child: Padding(
          padding: const EdgeInsets.all(24),
          child: SvgPicture.memory(bytes),
        ),
      ),
    );
  }
}
class _MarkdownViewer extends StatelessWidget {
  final Uint8List bytes;
  final PyramidTheme pt;
  const _MarkdownViewer({required this.bytes, required this.pt});

  @override
  Widget build(BuildContext context) {
    final String text;
    try {
      text = utf8.decode(bytes, allowMalformed: true);
    } catch (e) {
      return _ErrorView(message: e.toString(), pt: pt);
    }

    return Markdown(
      data: text,
      selectable: true,
      padding: const EdgeInsets.all(24),
      styleSheet: MarkdownStyleSheet(
        p: TextStyle(color: pt.fg, fontSize: 14, height: 1.65),
        h1: TextStyle(color: pt.fg, fontSize: 22, fontWeight: FontWeight.w700),
        h2: TextStyle(color: pt.fg, fontSize: 18, fontWeight: FontWeight.w600),
        h3: TextStyle(color: pt.fg, fontSize: 16, fontWeight: FontWeight.w600),
        h4: TextStyle(color: pt.fg, fontSize: 14, fontWeight: FontWeight.w600),
        code: TextStyle(color: pt.accent, fontFamily: 'monospace', fontSize: 13, backgroundColor: pt.bg2),
        codeblockDecoration: BoxDecoration(
          color: pt.bg2,
          borderRadius: BorderRadius.circular(pt.rSm),
          border: Border.all(color: pt.border),
        ),
        blockquoteDecoration: BoxDecoration(
          border: Border(left: BorderSide(color: pt.accent, width: 3)),
          color: pt.accentSoft,
        ),
        blockquotePadding: const EdgeInsets.fromLTRB(12, 8, 12, 8),
        a: TextStyle(color: pt.accent, decoration: TextDecoration.underline, decorationColor: pt.accent),
        strong: TextStyle(color: pt.fg, fontWeight: FontWeight.w600),
        em: TextStyle(color: pt.fg, fontStyle: FontStyle.italic),
        listBullet: TextStyle(color: pt.fgMuted),
        horizontalRuleDecoration: BoxDecoration(border: Border(top: BorderSide(color: pt.border))),
      ),
      onTapLink: (text, href, title) {
        if (href != null) launchUrl(Uri.parse(href), mode: LaunchMode.externalApplication);
      },
    );
  }
}
class _TextViewer extends StatelessWidget {
  final Uint8List bytes;
  final PyramidTheme pt;
  final bool mono;
  static const _maxBytes = 512 * 1024;
  const _TextViewer({required this.bytes, required this.pt, required this.mono});

  @override
  Widget build(BuildContext context) {
    final bool truncated = bytes.length > _maxBytes;
    final slice = truncated ? bytes.sublist(0, _maxBytes) : bytes;
    final String text;
    try {
      text = utf8.decode(slice, allowMalformed: true);
    } catch (e) {
      return _ErrorView(message: e.toString(), pt: pt);
    }

    return Column(
      children: [
        if (truncated)
          Container(
            width: double.infinity,
            padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 6),
            color: pt.bg2,
            child: Text('Zeige erste ${_maxBytes ~/ 1024} KB', style: TextStyle(color: pt.fgDim, fontSize: 11)),
          ),
        Expanded(
          child: SingleChildScrollView(
            padding: const EdgeInsets.all(20),
            child: SelectableText(
              text,
              style: mono
                  ? TextStyle(color: pt.fg, fontFamily: 'monospace', fontSize: 13, height: 1.5)
                  : TextStyle(color: pt.fg, fontSize: 14, height: 1.65),
            ),
          ),
        ),
      ],
    );
  }
}
class _OfficeTextViewer extends StatefulWidget {
  final Uint8List bytes;
  final String filename;
  final PyramidTheme pt;
  const _OfficeTextViewer({required this.bytes, required this.filename, required this.pt});

  @override
  State<_OfficeTextViewer> createState() => _OfficeTextViewerState();
}
class _OfficeTextViewerState extends State<_OfficeTextViewer> {
  String? _text;
  String? _error;

  @override
  void initState() {
    super.initState();
    _extract();
  }

  void _extract() {
    try {
      final archive = ZipDecoder().decodeBytes(widget.bytes);
      final ext = widget.filename.contains('.') ? widget.filename.split('.').last.toLowerCase() : '';

      final xmlFiles = <ArchiveFile>[];
      for (final f in archive.files) {
        if (!f.isFile) continue;
        final n = f.name.toLowerCase();
        if (ext == 'docx' && n == 'word/document.xml') { xmlFiles.add(f); break; }
        if (ext == 'xlsx' && n.startsWith('xl/worksheets/') && n.endsWith('.xml')) xmlFiles.add(f);
        if (ext == 'pptx' && n.startsWith('ppt/slides/slide') && n.endsWith('.xml')) xmlFiles.add(f);
        // ODF formats (Writer/Impress/Calc) all use content.xml
        if ((ext == 'odt' || ext == 'odp' || ext == 'ods') && n == 'content.xml') { xmlFiles.add(f); break; }
      }

      final buf = StringBuffer();
      for (final f in xmlFiles) {
        final xml = utf8.decode(f.content as List<int>, allowMalformed: true);
        // Strip XML tags, collapse whitespace
        final stripped = xml
            .replaceAll(RegExp(r'<[^>]+>'), ' ')
            .replaceAll(RegExp(r'&amp;'), '&')
            .replaceAll(RegExp(r'&lt;'), '<')
            .replaceAll(RegExp(r'&gt;'), '>')
            .replaceAll(RegExp(r'&nbsp;'), ' ')
            .replaceAll(RegExp(r'\s+'), ' ')
            .trim();
        buf.writeln(stripped);
        buf.writeln();
      }

      _text = buf.toString().trim().isEmpty
          ? '(Kein lesbarer Text gefunden)'
          : buf.toString().trim();
    } catch (e) {
      _error = e.toString().split('\n').first;
    }
  }

  @override
  Widget build(BuildContext context) {
    final pt = widget.pt;
    if (_error != null) return _ErrorView(message: _error!, pt: pt);

    return Column(
      children: [
        Container(
          width: double.infinity,
          padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
          color: pt.bg2,
          child: Row(
            children: [
              Icon(Icons.info_outline_rounded, size: 14, color: pt.fgDim),
              const SizedBox(width: 8),
              Text('Textvorschau (Formatierung nicht verfügbar)', style: TextStyle(color: pt.fgDim, fontSize: 12)),
            ],
          ),
        ),
        Expanded(
          child: SingleChildScrollView(
            padding: const EdgeInsets.all(20),
            child: SelectableText(
              _text ?? '',
              style: TextStyle(color: pt.fg, fontSize: 14, height: 1.65),
            ),
          ),
        ),
      ],
    );
  }
}
