import 'dart:convert';

import 'package:dio/dio.dart';
import 'package:networks_sdk/src/presentation/wiring/network_callbacks.dart';

/// 请求/响应日志拦截器
///
/// 每次请求打一条日志，请求和响应合并输出，方便对照：
///
/// ```
/// [Network] ── SendOtpRequest  (auth_repository_impl.dart:45)
/// --> POST https://example.com/app/api/auth/otp/send
/// Headers:
/// {
///   "Platform": "Android",
///   ...
/// }
///
/// Body:
/// {
///   "country_code": "+65",
///   "contact": "83465308",
///   "type": 1
/// }
/// <-- 200 https://example.com/app/api/auth/otp/send
/// {
///   "code": 0,
///   "message": "ok"
/// }
/// ────────────────────────────────────────────────────────────
///
/// [Network ERR] ── SendOtpRequest  (auth_repository_impl.dart:45)
/// --> POST https://example.com/app/api/auth/otp/send
/// ...
/// <-- 404 https://example.com/app/api/auth/otp/send
/// Type: badResponse
///
/// <html>...</html>
/// ────────────────────────────────────────────────────────────
/// ```
///
/// Header 行显示 Request 类名 + 调用文件:行号，直接定位到出问题的调用代码。
/// Footer 行 `────` 视觉上把相邻请求隔开，成对关系一眼看清。
class LoggingInterceptor extends Interceptor {
  final OnLog? onLog;
  final bool enabled;

  LoggingInterceptor({this.onLog, this.enabled = true});

  @override
  void onResponse(Response response, ResponseInterceptorHandler handler) {
    if (enabled && onLog != null) {
      _log(
        opts: response.requestOptions,
        statusCode: response.statusCode,
        data: response.data,
        tag: 'Network',
      );
    }
    handler.next(response);
  }

  @override
  void onError(DioException err, ErrorInterceptorHandler handler) {
    if (enabled && onLog != null) {
      _log(
        opts: err.requestOptions,
        statusCode: err.response?.statusCode,
        data: err.response?.data,
        errorType: err.type.name,
        errorMessage: err.message,
        tag: 'Network ERR',
      );
    }
    handler.next(err);
  }

  // ─── Log ─────────────────────────────────────────────────────────────────

  void _log({
    required RequestOptions opts,
    required int? statusCode,
    required dynamic data,
    String? errorType,
    String? errorMessage,
    required String tag,
  }) {
    try {
      final buf = StringBuffer();
      const footer =
          '────────────────────────────────────────────────────────────';

      // Header：Request 类名 + 调用位置
      final className = opts.extra['_requestClass'] as String? ?? '';
      final callerFrame = opts.extra['_callerFrame'] as String? ?? '';
      if (className.isNotEmpty) {
        buf.write('── $className');
        if (callerFrame.isNotEmpty) {
          buf.writeln('  ($callerFrame)');
        } else {
          buf.writeln();
        }
      }

      // Request：headers + body 合并成一个 JSON 块
      buf.writeln('--> ${opts.method} ${opts.uri}');
      final requestMap = <String, dynamic>{
        'headers': _sanitizeHeaders(opts.headers),
        if (opts.data != null) 'body': opts.data,
      };
      buf.writeln(_formatBody(requestMap));

      // Response
      final status = statusCode != null ? '$statusCode' : 'ERR';
      buf.writeln('<-- $status ${opts.uri}');
      if (errorType != null) {
        buf.writeln('Type: $errorType');
      }
      if (data != null) {
        buf.writeln();
        buf.writeln(_formatBody(data));
      } else if (errorMessage != null && errorType == null) {
        // 无响应 body（超时、断网等），打印错误消息
        buf.writeln(errorMessage);
      }

      // Footer
      buf.write(footer);

      onLog!(buf.toString(), tag: tag);
    } catch (_) {
      onLog!(
        '--> ${opts.method} ${opts.uri} | <-- $statusCode',
        tag: tag,
      );
    }
  }

  // ─── Helpers ──────────────────────────────────────────────────────────────

  /// Authorization token 只保留前 16 位，防止 token 泄露到日志
  Map<String, dynamic> _sanitizeHeaders(Map<String, dynamic> headers) {
    return headers.map((key, value) {
      if (key.toLowerCase() == 'authorization' &&
          value is String &&
          value.length > 16) {
        return MapEntry(key, '${value.substring(0, 16)}...');
      }
      return MapEntry(key, value);
    });
  }

  /// 格式化 body，兼容 String / Map / List
  String _formatBody(dynamic data) {
    try {
      if (data is String) {
        final parsed = jsonDecode(data);
        return const JsonEncoder.withIndent('  ').convert(parsed);
      }
      return const JsonEncoder.withIndent('  ').convert(data);
    } catch (_) {
      return data.toString();
    }
  }
}
