part of '../document_viewer.dart';

enum _DocType { pdf, svg, text, code, markdown, office, archive, psdThumb, zipPreview, proprietary, unknown }
_DocType _detectType(String filename) {
  final ext = filename.contains('.') ? filename.split('.').last.toLowerCase() : '';
  return switch (ext) {
    // AI/EPS files embed a full PDF when saved with PDF compatibility
    'pdf' || 'ai' || 'eps'                         => _DocType.pdf,
    'svg'                                          => _DocType.svg,
    'md' || 'markdown' || 'rst'                    => _DocType.markdown,
    'zip' || 'tar' || 'gz' || 'tgz' || 'tar.gz'   => _DocType.archive,
    'txt' || 'log' || 'csv' || 'tsv' ||
    'rtf' || 'tex' || 'srt' || 'vtt' || 'nfo'     => _DocType.text,
    // ODF formats are ZIP+XML, same extraction approach as OOXML
    'docx' || 'xlsx' || 'pptx' ||
    'odt' || 'odp' || 'ods'                       => _DocType.office,
    'dart' || 'py' || 'js' || 'mjs' || 'cjs' || 'ts' || 'jsx' || 'tsx' ||
    'json' || 'jsonl' || 'ndjson' || 'yaml' || 'yml' || 'xml' || 'plist' ||
    'html' || 'htm' || 'css' || 'scss' || 'sass' || 'less' ||
    'vue' || 'svelte' || 'astro' ||
    'sh' || 'bash' || 'zsh' || 'fish' || 'ps' || 'ps1' || 'bat' || 'cmd' ||
    'kt' || 'kts' || 'gradle' || 'java' || 'swift' || 'go' || 'rs' ||
    'cpp' || 'cc' || 'cxx' || 'c' || 'h' || 'hpp' || 'hxx' || 'm' || 'mm' ||
    'cs' || 'rb' || 'php' || 'r' || 'lua' || 'pl' || 'pm' || 'scala' ||
    'clj' || 'ex' || 'exs' || 'erl' || 'hs' || 'jl' || 'nim' || 'zig' ||
    'toml' || 'ini' || 'conf' || 'cfg' || 'env' || 'editorconfig' ||
    'properties' || 'diff' || 'patch' || 'gitignore' || 'dockerfile' ||
    'sql' || 'graphql' || 'gql' || 'proto'         => _DocType.code,
    // PSD/PSB embed a JPEG thumbnail in Image Resource 1036
    'psd' || 'psb'                                 => _DocType.psdThumb,
    // Sketch and XD are ZIP archives containing a preview PNG
    'sketch' || 'xd'                               => _DocType.zipPreview,
    // Truly proprietary — no extractable preview
    'afphoto' || 'afdesign' || 'afpub' ||
    'indd' || 'inx' || 'fig' ||
    'doc' || 'ppt' || 'xls'                        => _DocType.proprietary,
    _                                              => _DocType.unknown,
  };
}
class DocumentViewer extends StatelessWidget {
  final String filename;
  final Uint8List bytes;
  final String senderName;
  final int initialPage;

  const DocumentViewer({
    super.key,
    required this.filename,
    required this.bytes,
    required this.senderName,
    this.initialPage = 1,
  });

  static bool supportsPreview(String filename) =>
      _detectType(filename) != _DocType.unknown;

  /// True for formats rendered inline in chat (pdf/svg types, including ai/eps).
  static bool isInlinePreviewable(String filename) {
    final t = _detectType(filename);
    return t == _DocType.pdf || t == _DocType.svg;
  }

  /// True for formats that show a card inline in chat (needs download-on-tap).
  static bool showsInlineCard(String filename) {
    final t = _detectType(filename);
    return t == _DocType.proprietary || t == _DocType.psdThumb || t == _DocType.zipPreview;
  }

  /// Kept for compatibility — same as showsInlineCard.
  static bool isProprietaryFormat(String filename) => showsInlineCard(filename);

  static Future<void> show(
    BuildContext context, {
    required String filename,
    required Uint8List bytes,
    required String senderName,
    int initialPage = 1,
  }) {
    return showGeneralDialog(
      context: context,
      barrierDismissible: true,
      barrierLabel: 'Schließen',
      barrierColor: Colors.black.withAlpha(178),
      transitionDuration: const Duration(milliseconds: 180),
      transitionBuilder: (ctx, anim, a, child) =>
          FadeTransition(opacity: anim, child: child),
      pageBuilder: (ctx, a, b) => DocumentViewer(
        filename: filename,
        bytes: bytes,
        senderName: senderName,
        initialPage: initialPage,
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    final pt = PyramidTheme.of(context);
    final type = _detectType(filename);
    final size = MediaQuery.sizeOf(context);
    final maxW = (size.width - 48).clamp(300.0, 1100.0);
    final maxH = (size.height - 48).clamp(300.0, 900.0);

    return Material(
      type: MaterialType.transparency,
      child: Center(
        child: Container(
          width: maxW,
          height: maxH,
          decoration: BoxDecoration(
            color: pt.bg0,
            borderRadius: BorderRadius.circular(pt.rLg),
            border: Border.all(color: pt.border),
            boxShadow: [BoxShadow(color: Colors.black.withAlpha(80), blurRadius: 32, offset: const Offset(0, 8))],
          ),
          clipBehavior: Clip.hardEdge,
          child: Column(
            children: [
              _DocHeader(filename: filename, senderName: senderName, pt: pt),
              Expanded(
                child: _DocContent(
                  filename: filename,
                  bytes: bytes,
                  type: type,
                  pt: pt,
                  initialPage: initialPage,
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}
class _DocHeader extends StatelessWidget {
  final String filename;
  final String senderName;
  final PyramidTheme pt;
  const _DocHeader({required this.filename, required this.senderName, required this.pt});

  @override
  Widget build(BuildContext context) {
    final ext = filename.contains('.') ? filename.split('.').last.toUpperCase() : '';
    return Container(
      padding: const EdgeInsets.fromLTRB(16, 12, 8, 12),
      decoration: BoxDecoration(
        color: pt.bg1,
        border: Border(bottom: BorderSide(color: pt.border)),
      ),
      child: Row(
        children: [
          _ExtBadge(ext: ext, pt: pt),
          const SizedBox(width: 12),
          Expanded(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              mainAxisSize: MainAxisSize.min,
              children: [
                Text(filename, style: TextStyle(color: pt.fg, fontSize: 14, fontWeight: FontWeight.w600), overflow: TextOverflow.ellipsis),
                Text(senderName, style: TextStyle(color: pt.fgDim, fontSize: 12)),
              ],
            ),
          ),
          IconButton(
            onPressed: () => Navigator.of(context).pop(),
            icon: Icon(Icons.close_rounded, color: pt.fgMuted, size: 20),
            tooltip: 'Schließen',
          ),
        ],
      ),
    );
  }
}
class _ExtBadge extends StatelessWidget {
  final String ext;
  final PyramidTheme pt;
  const _ExtBadge({required this.ext, required this.pt});

  @override
  Widget build(BuildContext context) {
    final label = ext.length > 4 ? ext.substring(0, 4) : ext;
    return Container(
      width: 44, height: 44,
      decoration: BoxDecoration(color: pt.accentSoft, borderRadius: BorderRadius.circular(pt.rSm)),
      child: Center(
        child: Text(label, style: TextStyle(color: pt.accent, fontSize: label.length > 3 ? 10 : 12, fontWeight: FontWeight.w700)),
      ),
    );
  }
}
class _DocContent extends StatelessWidget {
  final String filename;
  final Uint8List bytes;
  final _DocType type;
  final PyramidTheme pt;
  final int initialPage;
  const _DocContent({required this.filename, required this.bytes, required this.type, required this.pt, required this.initialPage});

  @override
  Widget build(BuildContext context) {
    return switch (type) {
      _DocType.pdf      => _PdfFullViewer(bytes: bytes, filename: filename, pt: pt, initialPage: initialPage),
      _DocType.svg      => _SvgViewer(bytes: bytes, pt: pt),
      _DocType.markdown => _MarkdownViewer(bytes: bytes, pt: pt),
      _DocType.text     => _TextViewer(bytes: bytes, pt: pt, mono: false),
      _DocType.code     => _TextViewer(bytes: bytes, pt: pt, mono: true),
      _DocType.office   => _OfficeTextViewer(bytes: bytes, filename: filename, pt: pt),
      _DocType.archive      => _ArchiveViewer(bytes: bytes, filename: filename, pt: pt),
      _DocType.psdThumb     => _PsdThumbViewer(bytes: bytes, filename: filename, pt: pt),
      _DocType.zipPreview   => _ZipPreviewViewer(bytes: bytes, filename: filename, pt: pt),
      _DocType.proprietary  => _ProprietaryViewer(filename: filename, bytes: bytes, pt: pt),
      _DocType.unknown      => _UnsupportedViewer(pt: pt),
    };
  }
}
class _ErrorView extends StatelessWidget {
  final String message;
  final PyramidTheme pt;
  const _ErrorView({required this.message, required this.pt});

  @override
  Widget build(BuildContext context) => Center(
    child: Padding(
      padding: const EdgeInsets.all(32),
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          Icon(Icons.error_outline_rounded, size: 32, color: pt.danger),
          const SizedBox(height: 8),
          Text('Fehler beim Laden', style: TextStyle(color: pt.danger, fontSize: 14, fontWeight: FontWeight.w600)),
          const SizedBox(height: 6),
          Text(message, style: TextStyle(color: pt.fgMuted, fontSize: 12), textAlign: TextAlign.center),
        ],
      ),
    ),
  );
}
class _UnsupportedViewer extends StatelessWidget {
  final PyramidTheme pt;
  const _UnsupportedViewer({required this.pt});

  @override
  Widget build(BuildContext context) => Center(
    child: Column(
      mainAxisSize: MainAxisSize.min,
      children: [
        Icon(Icons.preview_outlined, size: 48, color: pt.fgDim),
        const SizedBox(height: 12),
        Text('Vorschau nicht verfügbar', style: TextStyle(color: pt.fgDim, fontSize: 15)),
        const SizedBox(height: 4),
        Text('Proprietäres Format — bitte herunterladen.', style: TextStyle(color: pt.fgMuted, fontSize: 12)),
      ],
    ),
  );
}
class _FileFallback extends StatelessWidget {
  final String filename;
  final PyramidTheme pt;
  final VoidCallback? onDownload;
  const _FileFallback({required this.filename, required this.pt, this.onDownload});

  @override
  Widget build(BuildContext context) {
    return Container(
      margin: const EdgeInsets.only(top: 4, bottom: 4),
      padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
      constraints: const BoxConstraints(maxWidth: 300),
      decoration: BoxDecoration(
        color: pt.bg3,
        borderRadius: BorderRadius.circular(pt.rBase),
        border: Border.all(color: pt.border),
      ),
      child: Row(
        mainAxisSize: MainAxisSize.min,
        children: [
          Container(
            width: 36, height: 36,
            decoration: BoxDecoration(color: pt.accentSoft, borderRadius: BorderRadius.circular(pt.rSm)),
            child: Icon(Icons.picture_as_pdf_outlined, size: 20, color: pt.accent),
          ),
          const SizedBox(width: 10),
          Expanded(
            child: Text(filename, style: TextStyle(color: pt.fg, fontSize: 13, fontWeight: FontWeight.w500), maxLines: 2, overflow: TextOverflow.ellipsis),
          ),
          if (onDownload != null)
            IconButton(
              onPressed: onDownload,
              icon: Icon(Icons.download_rounded, size: 20, color: pt.fgMuted),
              constraints: const BoxConstraints(minWidth: 32, minHeight: 32),
              padding: EdgeInsets.zero,
            ),
        ],
      ),
    );
  }
}
