import 'package:flutter/material.dart';

/// 全局文本尺寸语义。
///
/// 业务代码应优先选择语义化的 variant，而不是直接散落 `fontSize`。
/// 这样后续调整整套字号体系时，只需要维护这一处映射。
enum AppTextVariant {
  display,
  headline,
  title,
  subtitle,
  body,
  bodySmall,
  label,
  caption,
}

/// 全局文本颜色语义。
///
/// tone 只表达“文本在界面中的语义角色”，具体颜色从当前 Theme 解析，
/// 避免页面直接依赖硬编码色值。
enum AppTextTone {
  primary,
  secondary,
  tertiary,
  inverse,
  brand,
  success,
  warning,
  danger,
  disabled,
}

/// 应用级文本组件。
///
/// `AppText` 是对 Flutter `Text` 的轻量封装，目标是统一页面里的字号、
/// 字重、颜色和溢出策略，同时保留 `Text` 的常用能力。
///
/// 使用建议：
/// - 普通文案使用默认 `AppText('内容')`。
/// - 标题使用 `variant: AppTextVariant.title`。
/// - 错误、警告、成功等状态文案使用 `tone`，不要在业务里直接写颜色。
/// - 只有遇到一次性视觉细节时才传入 `style`、`fontSize` 或 `fontWeight`。
class AppText extends StatelessWidget {
  const AppText(
    this.data, {
    super.key,
    this.variant = AppTextVariant.body,
    this.tone = AppTextTone.primary,
    this.style,
    this.color,
    this.fontSize,
    this.fontWeight,
    this.height,
    this.letterSpacing,
    this.textAlign,
    this.textDirection,
    this.locale,
    this.softWrap,
    this.overflow,
    this.maxLines,
    this.semanticsLabel,
    this.textWidthBasis,
    this.textHeightBehavior,
    this.textScaler,
    this.selectionColor,
  }) : textSpan = null;

  /// 富文本构造器。
  ///
  /// 用于同一段文案中存在局部强调、不同颜色或不同字重的场景。
  /// 外层的 `variant`、`tone` 和通用排版参数仍会作为默认样式作用到 span。
  const AppText.rich(
    this.textSpan, {
    super.key,
    this.variant = AppTextVariant.body,
    this.tone = AppTextTone.primary,
    this.style,
    this.color,
    this.fontSize,
    this.fontWeight,
    this.height,
    this.letterSpacing,
    this.textAlign,
    this.textDirection,
    this.locale,
    this.softWrap,
    this.overflow,
    this.maxLines,
    this.semanticsLabel,
    this.textWidthBasis,
    this.textHeightBehavior,
    this.textScaler,
    this.selectionColor,
  }) : data = null;

  /// 普通文本内容。与 [textSpan] 二选一。
  final String? data;

  /// 富文本内容。与 [data] 二选一。
  final InlineSpan? textSpan;

  /// 文本尺寸和基础字重语义。
  final AppTextVariant variant;

  /// 文本颜色语义。
  final AppTextTone tone;

  /// 额外样式覆盖。优先级高于 variant 和 tone。
  final TextStyle? style;

  /// 显式颜色覆盖。优先级高于 tone 和 `style.color`。
  final Color? color;

  /// 一次性字号覆盖。常规场景优先使用 [variant]。
  final double? fontSize;

  /// 一次性字重覆盖。常规场景优先使用 [variant]。
  final FontWeight? fontWeight;

  /// 行高覆盖。
  final double? height;

  /// 字间距覆盖。
  final double? letterSpacing;

  final TextAlign? textAlign;
  final TextDirection? textDirection;
  final Locale? locale;
  final bool? softWrap;
  final TextOverflow? overflow;
  final int? maxLines;
  final String? semanticsLabel;
  final TextWidthBasis? textWidthBasis;
  final TextHeightBehavior? textHeightBehavior;
  final TextScaler? textScaler;
  final Color? selectionColor;

  @override
  Widget build(BuildContext context) {
    final effectiveStyle = _resolveStyle(context);

    if (textSpan != null) {
      return Text.rich(
        textSpan!,
        style: effectiveStyle,
        textAlign: textAlign,
        textDirection: textDirection,
        locale: locale,
        softWrap: softWrap,
        overflow: overflow,
        maxLines: maxLines,
        semanticsLabel: semanticsLabel,
        textWidthBasis: textWidthBasis,
        textHeightBehavior: textHeightBehavior,
        textScaler: textScaler,
        selectionColor: selectionColor,
      );
    }

    return Text(
      data ?? '',
      style: effectiveStyle,
      textAlign: textAlign,
      textDirection: textDirection,
      locale: locale,
      softWrap: softWrap,
      overflow: overflow,
      maxLines: maxLines,
      semanticsLabel: semanticsLabel,
      textWidthBasis: textWidthBasis,
      textHeightBehavior: textHeightBehavior,
      textScaler: textScaler,
      selectionColor: selectionColor,
    );
  }

  /// 合成最终样式。
  ///
  /// 优先级从低到高：
  /// 1. Theme 中的 TextTheme。
  /// 2. `variant` 与 `tone` 对应的默认样式。
  /// 3. 外部传入的 `style`。
  /// 4. `color`、`fontSize`、`fontWeight` 等显式字段。
  TextStyle _resolveStyle(BuildContext context) {
    final baseStyle = _variantStyle(Theme.of(context).textTheme);
    final toneStyle = baseStyle.copyWith(color: _toneColor(context));
    final mergedStyle = style == null ? toneStyle : toneStyle.merge(style);

    return mergedStyle.copyWith(
      color: color ?? mergedStyle.color,
      fontSize: fontSize ?? mergedStyle.fontSize,
      fontWeight: fontWeight ?? mergedStyle.fontWeight,
      height: height ?? mergedStyle.height,
      letterSpacing: letterSpacing ?? mergedStyle.letterSpacing,
    );
  }

  TextStyle _variantStyle(TextTheme textTheme) {
    return switch (variant) {
      AppTextVariant.display =>
        textTheme.displaySmall ?? const TextStyle(fontSize: 36),
      AppTextVariant.headline =>
        textTheme.headlineSmall ?? const TextStyle(fontSize: 24),
      AppTextVariant.title =>
        textTheme.titleMedium ?? const TextStyle(fontSize: 16),
      AppTextVariant.subtitle =>
        textTheme.titleSmall ?? const TextStyle(fontSize: 14),
      AppTextVariant.body =>
        textTheme.bodyMedium ?? const TextStyle(fontSize: 14),
      AppTextVariant.bodySmall =>
        textTheme.bodySmall ?? const TextStyle(fontSize: 12),
      AppTextVariant.label =>
        textTheme.labelLarge ?? const TextStyle(fontSize: 14),
      AppTextVariant.caption =>
        textTheme.labelSmall ?? const TextStyle(fontSize: 11),
    };
  }

  Color _toneColor(BuildContext context) {
    final colors = Theme.of(context).colorScheme;
    return switch (tone) {
      AppTextTone.primary => colors.onSurface,
      AppTextTone.secondary => colors.onSurfaceVariant,
      AppTextTone.tertiary => colors.outline,
      AppTextTone.inverse => colors.onInverseSurface,
      AppTextTone.brand => colors.primary,
      AppTextTone.success => colors.tertiary,
      AppTextTone.warning => colors.secondary,
      AppTextTone.danger => colors.error,
      AppTextTone.disabled => colors.onSurface.withValues(alpha: 0.38),
    };
  }
}
