import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:material_symbols_icons/symbols.dart';

import '../media/media_item.dart';
import '../utils/formatters.dart';
import '../utils/rating_utils.dart';
import 'app_icon.dart';

enum MediaRatingBadgeVariant { chip, inline }

class MediaRatingBadge extends StatelessWidget {
  const MediaRatingBadge.chip({
    super.key,
    required this.value,
    required this.fallbackIcon,
    this.imageUri,
    this.fallbackText,
    this.textStyle,
    this.foregroundColor,
    this.backgroundColor,
    this.iconSize,
    this.padding,
    this.spacing,
  }) : variant = MediaRatingBadgeVariant.chip;

  const MediaRatingBadge.inline({
    super.key,
    required this.value,
    required this.fallbackIcon,
    this.imageUri,
    this.fallbackText,
    this.textStyle,
    this.foregroundColor,
    this.iconSize,
    this.spacing,
  }) : variant = MediaRatingBadgeVariant.inline,
       backgroundColor = null,
       padding = EdgeInsets.zero;

  final String? imageUri;
  final double value;
  final IconData fallbackIcon;
  final String? fallbackText;
  final MediaRatingBadgeVariant variant;
  final TextStyle? textStyle;
  final Color? foregroundColor;
  final Color? backgroundColor;
  final double? iconSize;
  final EdgeInsetsGeometry? padding;
  final double? spacing;

  static MediaRatingBadge? inlineForMedia({
    required MediaItem item,
    MediaItem? fallbackItem,
    TextStyle? textStyle,
    Color? foregroundColor,
    double? iconSize,
    double? spacing,
  }) {
    final data = _ratingDataFor(item) ?? (fallbackItem == null ? null : _ratingDataFor(fallbackItem));
    if (data == null) return null;

    return MediaRatingBadge.inline(
      imageUri: data.imageUri,
      value: data.value,
      fallbackIcon: data.fallbackIcon,
      fallbackText: data.fallbackText,
      foregroundColor: foregroundColor,
      iconSize: iconSize,
      spacing: spacing,
      textStyle: textStyle,
    );
  }

  /// The text exposed by the rendered badge, without building its icon row.
  static String? semanticLabelForMedia(MediaItem item, {MediaItem? fallbackItem}) {
    final data = _ratingDataFor(item) ?? (fallbackItem == null ? null : _ratingDataFor(fallbackItem));
    if (data == null) return null;
    return parseRatingImage(data.imageUri, data.value)?.formattedValue ?? data.fallbackText;
  }

  static _MediaRatingBadgeData? _ratingDataFor(MediaItem item) {
    final plex = item is PlexMediaItem ? item : null;
    final rating = item.rating;
    if (rating != null) {
      return _MediaRatingBadgeData(
        imageUri: plex?.ratingImage,
        value: rating,
        fallbackIcon: Symbols.star_rounded,
        fallbackText: formatRating(rating),
      );
    }

    final audienceRating = plex?.audienceRating;
    if (audienceRating != null) {
      return _MediaRatingBadgeData(
        imageUri: plex?.audienceRatingImage,
        value: audienceRating,
        fallbackIcon: Symbols.people_rounded,
        fallbackText: '${(audienceRating * 10).toStringAsFixed(0)}%',
      );
    }

    return null;
  }

  @override
  Widget build(BuildContext context) {
    final colorScheme = Theme.of(context).colorScheme;
    final isInline = variant == MediaRatingBadgeVariant.inline;
    final foreground = foregroundColor ?? (isInline ? colorScheme.onSurface : colorScheme.onSecondaryContainer);
    final style =
        (textStyle ??
                TextStyle(color: foreground, fontSize: 13, fontWeight: isInline ? FontWeight.w700 : FontWeight.w600))
            .copyWith(color: textStyle?.color ?? foreground);
    final size = iconSize ?? style.fontSize ?? 13;
    final info = parseRatingImage(imageUri, value);
    final label = info?.formattedValue ?? fallbackText ?? '${(value * 10).toStringAsFixed(0)}%';
    final content = Row(
      mainAxisSize: MainAxisSize.min,
      children: [
        if (info != null)
          SvgPicture.asset(info.assetPath, width: size, height: size)
        else
          AppIcon(fallbackIcon, fill: 1, color: foreground, size: size),
        SizedBox(width: spacing ?? (isInline ? 4 : 4)),
        Text(label, maxLines: 1, overflow: TextOverflow.clip, style: style),
      ],
    );

    if (isInline) return content;

    return Container(
      padding: padding ?? const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
      decoration: BoxDecoration(
        color: backgroundColor ?? colorScheme.secondaryContainer.withValues(alpha: 0.8),
        borderRadius: const BorderRadius.all(Radius.circular(100)),
      ),
      child: content,
    );
  }
}

class _MediaRatingBadgeData {
  const _MediaRatingBadgeData({
    required this.value,
    required this.fallbackIcon,
    required this.fallbackText,
    this.imageUri,
  });

  final String? imageUri;
  final double value;
  final IconData fallbackIcon;
  final String fallbackText;
}
