import 'package:flutter/material.dart';

import '../l10n/app_localizations.dart';

/// 将 provider 返回的错误码解析为本地化字符串。
/// err 为 null 时返回 null；未知错误码（API 服务端消息）直接透传。
String? resolveProviderError(String? err, AppLocalizations l10n) {
  if (err == null) return null;
  switch (err) {
    case 'errEnterVolume':        return l10n.errEnterVolume;
    case 'errEnterPrice':         return l10n.errEnterPrice;
    case 'errEnterTriggerPrice':  return l10n.errEnterTriggerPrice;
    case 'errContractNotReady':   return l10n.errContractNotReady;
    case 'errPriceNotReady':      return l10n.errPriceNotReady;
    case 'errVolumeInsufficient': return l10n.errVolumeInsufficient;
    case 'errEnterClosePrice':    return l10n.errEnterClosePrice;
    case 'errInvalidOrderId':     return l10n.errInvalidOrderId;
    case 'errNoLongPosition':     return l10n.errNoLongPosition;
    case 'errNoShortPosition':    return l10n.errNoShortPosition;
    case 'errNoOrdersToCancel':   return l10n.errNoOrdersToCancel;
    case 'errServiceUnavailable': return l10n.errServiceUnavailable;
    case 'errTimeout':            return l10n.errTimeout;
    case 'errNetworkError':       return l10n.errNetworkError;
    case 'errLoginCredentialWrong':
      return l10n.errLoginCredentialWrong;
    case 'errAccountAlreadyRegistered':
      return l10n.errAccountAlreadyRegistered;
    // withdraw errors
    case 'errSelectNetwork':      return l10n.errSelectNetwork;
    case 'errEnterAddress':       return l10n.errEnterAddress;
    case 'errEnterAmount':        return l10n.errEnterAmount;
    case 'errEnterFundPassword':  return l10n.errEnterFundPassword;
    case 'errEnterVerifyCode':    return l10n.errEnterVerifyCode;
    case 'errBindGoogleFirst':    return l10n.errBindGoogleFirst;
    case 'errEnterGoogleCode':    return l10n.errEnterGoogleCode;
    case 'errAmountFormat':       return l10n.errAmountFormat;
    case 'errExceedBalance':      return l10n.errExceedBalance;
    case 'errEnterStartTime':     return l10n.errEnterStartTime;
    case 'errEnterEndTime':       return l10n.errEnterEndTime;
    // success codes
    case 'setSuccess':            return l10n.setSuccess;
    case 'changeSuccess':         return l10n.changeSuccess;
    default:
      // errMinWithdraw:xxx / errMinTransfer:xxx
      if (err.startsWith('errMinWithdraw:')) {
        return l10n.errMinWithdraw(err.substring('errMinWithdraw:'.length));
      }
      if (err.startsWith('errMinTransfer:')) {
        return l10n.errMinTransfer(err.substring('errMinTransfer:'.length));
      }
      return err; // 服务端消息直接透传
  }
}

/// 从错误字符串中提取用户可读的消息（兜底清洗）
String _cleanToastMessage(String message) {
  // 已经是简洁消息，直接返回
  if (!message.contains('Exception') && !message.contains('\n')) return message;

  // 从多行中找第一个有意义的非技术行
  final lines = message.split('\n');
  for (final line in lines) {
    final t = line.trim();
    if (t.isEmpty) {
      continue;
    }
    if (t.startsWith('DioException') || t.startsWith('Uri:') ||
        t.startsWith('#') || t.startsWith('Error:')) {
      continue;
    }
    return t;
  }

  // 处理 "Error: ApiException(code): 中文消息" 格式
  final m = RegExp(r'ApiException\(\d+\):\s*(.+?)[\r\n]?$', multiLine: true)
      .firstMatch(message);
  if (m != null) return m.group(1)!.trim();

  // 取最后一个 ": " 之后的内容
  final idx = message.lastIndexOf(': ');
  if (idx != -1 && idx < message.length - 2) {
    final tail = message.substring(idx + 2).trim();
    if (!tail.startsWith('//') && !tail.startsWith('http')) return tail;
  }

  return message;
}

/// 从顶部滑入的错误/提示 toast，自动 2.5 秒后消失
void showTopToast(
  BuildContext context, {
  required String message,
  Color? backgroundColor,
  Duration duration = const Duration(milliseconds: 2500),
}) {
  final displayMessage = _cleanToastMessage(message);
  final overlay = Overlay.of(context);
  final cs = Theme.of(context).colorScheme;
  final bgColor = backgroundColor ?? cs.error;

  late final OverlayEntry entry;
  final controller = AnimationController(
    vsync: overlay,
    duration: const Duration(milliseconds: 300),
  );
  final animation = CurvedAnimation(parent: controller, curve: Curves.easeOut);

  entry = OverlayEntry(
    builder: (context) => AnimatedBuilder(
      animation: animation,
      builder: (context, child) => Positioned(
        top: MediaQuery.of(context).padding.top +
            (-60 + 60 * animation.value),
        left: 0,
        right: 0,
        child: Opacity(
          opacity: animation.value,
          child: child,
        ),
      ),
      child: Material(
        color: Colors.transparent,
        child: Container(
          margin: const EdgeInsets.symmetric(horizontal: 12),
          padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
          decoration: BoxDecoration(
            color: bgColor,
            borderRadius: BorderRadius.circular(8),
          ),
          child: Text(
            displayMessage,
            style: const TextStyle(
              color: Colors.white,
              fontSize: 13,
              fontWeight: FontWeight.w500,
            ),
          ),
        ),
      ),
    ),
  );

  overlay.insert(entry);
  controller.forward();

  Future.delayed(duration, () {
    if (!entry.mounted) {
      controller.dispose();
      return;
    }
    controller.reverse().then((_) {
      try {
        if (entry.mounted) entry.remove();
      } catch (_) {}
      controller.dispose();
    });
  });
}
