import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:photo_view/photo_view.dart';

import 'pm_node.dart';
import 'pm_render_scope.dart';

class PmImageView extends StatelessWidget {
  final PmImage node;

  const PmImageView({required this.node, super.key});

  @override
  Widget build(BuildContext context) {
    final provider = _imageProvider();
    return LayoutBuilder(
      builder: (context, constraints) {
        final available = constraints.maxWidth.isFinite
            ? constraints.maxWidth
            : MediaQuery.sizeOf(context).width;
        final targetWidth = _resolveWidth(node.width, available);

        Widget image = ConstrainedBox(
          constraints: BoxConstraints(maxWidth: targetWidth ?? available),
          child: _imageWidget(context, provider),
        );

        final href = node.href;
        if (href != null && href.isNotEmpty) {
          image = InkWell(
            onTap: () => PmRenderScope.maybeOf(context)?.onLinkTap?.call(href),
            child: image,
          );
        } else if (provider != null) {
          image = InkWell(
            onTap: () => _openFullscreen(context, provider),
            child: image,
          );
        }

        return Align(alignment: _alignment(node.align), child: image);
      },
    );
  }

  ImageProvider? _imageProvider() {
    if (node.bytes != null) return MemoryImage(node.bytes!);
    if (node.src.startsWith('http')) {
      return CachedNetworkImageProvider(node.src);
    }
    return null;
  }

  Widget _imageWidget(BuildContext context, ImageProvider? provider) {
    if (node.bytes != null) {
      return Image.memory(
        node.bytes!,
        errorBuilder: (context, error, stack) => _brokenImage(context),
      );
    }
    if (node.src.startsWith('http')) {
      return CachedNetworkImage(
        imageUrl: node.src,
        errorWidget: (context, url, error) => _brokenImage(context),
      );
    }
    return _brokenImage(context);
  }

  Widget _brokenImage(BuildContext context) {
    final theme = Theme.of(context);
    return DecoratedBox(
      decoration: BoxDecoration(
        color: theme.colorScheme.surfaceContainerHighest,
        borderRadius: BorderRadius.circular(8),
      ),
      child: Padding(
        padding: const EdgeInsets.all(24),
        child: Icon(
          Icons.broken_image_outlined,
          color: theme.colorScheme.onSurfaceVariant,
        ),
      ),
    );
  }

  void _openFullscreen(BuildContext context, ImageProvider provider) {
    showDialog<void>(
      context: context,
      barrierColor: Colors.black,
      builder: (context) => Scaffold(
        backgroundColor: Colors.black,
        appBar: AppBar(
          backgroundColor: Colors.black,
          foregroundColor: Colors.white,
        ),
        body: PhotoView(
          minScale: PhotoViewComputedScale.contained,
          maxScale: PhotoViewComputedScale.covered * 3,
          imageProvider: provider,
          backgroundDecoration: const BoxDecoration(color: Colors.black),
        ),
      ),
    );
  }

  Alignment _alignment(String? align) {
    switch (align) {
      case 'center':
        return Alignment.center;
      case 'right':
        return Alignment.centerRight;
      default:
        return Alignment.centerLeft;
    }
  }

  double? _resolveWidth(String? width, double available) {
    if (width == null) return null;
    final match = RegExp(r'^(\d+(?:\.\d+)?)(px|%|em|rem)$').firstMatch(width);
    if (match == null) return null;
    final value = double.parse(match.group(1)!);
    final double resolved;
    switch (match.group(2)) {
      case '%':
        resolved = available * value / 100;
      case 'em':
      case 'rem':
        resolved = value * 16;
      default:
        resolved = value;
    }
    return resolved.clamp(1, available);
  }
}
