import 'dart:convert';
import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';

/// 로깅 인터셉터
class LoggingInterceptor extends Interceptor {
  @override
  void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
    // 요청 시간 기록
    options.extra['requestTime'] = DateTime.now();
    
    debugPrint('╔════════════════════════════════════════════════════════════');
    debugPrint('║ REQUEST [${DateTime.now().toIso8601String()}]');
    debugPrint('╟────────────────────────────────────────────────────────────');
    debugPrint('║ ${options.method} ${options.uri}');
    debugPrint('╟────────────────────────────────────────────────────────────');
    debugPrint('║ Headers:');
    options.headers.forEach((key, value) {
      // 민감한 정보 마스킹
      if (key.toLowerCase() == 'authorization') {
        debugPrint('║   $key: ${_maskToken(value.toString())}');
      } else {
        debugPrint('║   $key: $value');
      }
    });
    
    if (options.queryParameters.isNotEmpty) {
      debugPrint('╟────────────────────────────────────────────────────────────');
      debugPrint('║ Query Parameters:');
      options.queryParameters.forEach((key, value) {
        debugPrint('║   $key: $value');
      });
    }
    
    if (options.data != null) {
      debugPrint('╟────────────────────────────────────────────────────────────');
      debugPrint('║ Request Body:');
      try {
        final formattedData = _formatJson(options.data);
        formattedData.split('\n').forEach((line) {
          debugPrint('║ $line');
        });
      } catch (e) {
        debugPrint('║ ${options.data}');
      }
    }
    
    debugPrint('║ Timeout Settings:');
    debugPrint('║   Connect: ${options.connectTimeout}');
    debugPrint('║   Receive: ${options.receiveTimeout}');
    debugPrint('║   Send: ${options.sendTimeout}');
    debugPrint('╚════════════════════════════════════════════════════════════');
    
    handler.next(options);
  }
  
  @override
  void onResponse(Response response, ResponseInterceptorHandler handler) {
    final requestTime = response.requestOptions.extra['requestTime'] as DateTime?;
    final responseTime = DateTime.now();
    final duration = requestTime != null 
        ? responseTime.difference(requestTime).inMilliseconds 
        : null;
    
    debugPrint('╔════════════════════════════════════════════════════════════');
    debugPrint('║ RESPONSE');
    debugPrint('╟────────────────────────────────────────────────────────────');
    debugPrint('║ ${response.requestOptions.method} ${response.requestOptions.uri}');
    debugPrint('║ Status: ${response.statusCode} ${response.statusMessage}');
    if (duration != null) {
      debugPrint('║ Duration: ${duration}ms');
    }
    debugPrint('╟────────────────────────────────────────────────────────────');
    debugPrint('║ Headers:');
    response.headers.forEach((key, values) {
      debugPrint('║   $key: ${values.join(', ')}');
    });
    
    if (response.data != null) {
      debugPrint('╟────────────────────────────────────────────────────────────');
      debugPrint('║ Response Body:');
      try {
        final formattedData = _formatJson(response.data);
        final lines = formattedData.split('\n');
        // 너무 긴 응답은 일부만 출력
        if (lines.length > 50) {
          lines.take(25).forEach((line) {
            debugPrint('║ $line');
          });
          debugPrint('║ ... (${lines.length - 50} lines omitted) ...');
          for (final line in lines.skip(lines.length - 25)) {
            debugPrint('║ $line');
          }
        } else {
          for (final line in lines) {
            debugPrint('║ $line');
          }
        }
      } catch (e) {
        debugPrint('║ ${response.data}');
      }
    }
    
    debugPrint('╚════════════════════════════════════════════════════════════');
    
    handler.next(response);
  }
  
  @override
  void onError(DioException err, ErrorInterceptorHandler handler) {
    debugPrint('╔════════════════════════════════════════════════════════════');
    debugPrint('║ ERROR');
    debugPrint('╟────────────────────────────────────────────────────────────');
    debugPrint('║ ${err.requestOptions.method} ${err.requestOptions.uri}');
    debugPrint('║ Error Type: ${err.type}');
    debugPrint('║ Error Message: ${err.message}');
    
    if (err.response != null) {
      debugPrint('╟────────────────────────────────────────────────────────────');
      debugPrint('║ Status: ${err.response!.statusCode} ${err.response!.statusMessage}');
      
      if (err.response!.data != null) {
        debugPrint('╟────────────────────────────────────────────────────────────');
        debugPrint('║ Error Response:');
        try {
          final formattedData = _formatJson(err.response!.data);
          formattedData.split('\n').forEach((line) {
            debugPrint('║ $line');
          });
        } catch (e) {
          debugPrint('║ ${err.response!.data}');
        }
      }
    }
    
    if (err.error != null) {
      debugPrint('╟────────────────────────────────────────────────────────────');
      debugPrint('║ Original Error: ${err.error}');
    }
    
    debugPrint('╚════════════════════════════════════════════════════════════');
    
    handler.next(err);
  }
  
  /// JSON 포맷팅
  String _formatJson(dynamic data) {
    try {
      if (data is String) {
        final parsed = json.decode(data);
        return const JsonEncoder.withIndent('  ').convert(parsed);
      } else {
        return const JsonEncoder.withIndent('  ').convert(data);
      }
    } catch (e) {
      return data.toString();
    }
  }
  
  /// 토큰 마스킹
  String _maskToken(String token) {
    if (token.length <= 20) {
      return '***MASKED***';
    }
    
    // Bearer 프리픽스 처리
    if (token.startsWith('Bearer ')) {
      final actualToken = token.substring(7);
      if (actualToken.length > 20) {
        return 'Bearer ${actualToken.substring(0, 10)}...${actualToken.substring(actualToken.length - 10)}';
      }
      return 'Bearer ***MASKED***';
    }
    
    return '${token.substring(0, 10)}...${token.substring(token.length - 10)}';
  }
}

/// 요청 시간 측정을 위한 확장
extension RequestOptionsExtension on RequestOptions {
  void setRequestTime() {
    extra['requestTime'] = DateTime.now();
  }
}