import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';
// import '../theme/app_colors.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:path_provider/path_provider.dart';
import 'package:crypto/crypto.dart';
import 'package:flutter/foundation.dart' show kIsWeb;
import '../utils/reduce_motion.dart';

// 파비콘 캐시 관리 클래스
class FaviconCache {
  // 메모리 캐시 (앱 전체에서 공유)
  static final Map<String, String> _memoryCache = {};

  // 로딩 상태 추적 (동시에 동일한 URL에 대한 중복 요청 방지)
  static final Set<String> _loadingKeys = {};

  // 메모리 캐시에서 파비콘 URL 가져오기
  static String? getFromMemory(String serviceKey) {
    return _memoryCache[serviceKey];
  }

  // 메모리 캐시에 파비콘 URL 저장
  static void saveToMemory(String serviceKey, String logoUrl) {
    _memoryCache[serviceKey] = logoUrl;
    // 로딩 완료 표시
    _loadingKeys.remove(serviceKey);
  }

  // 로딩 시작 표시 (중복 요청 방지용)
  static bool markAsLoading(String serviceKey) {
    if (_loadingKeys.contains(serviceKey)) {
      // 이미 로딩 중이면 false 반환
      return false;
    }
    _loadingKeys.add(serviceKey);
    return true;
  }

  // 로딩 취소 표시
  static void cancelLoading(String serviceKey) {
    _loadingKeys.remove(serviceKey);
  }

  // SharedPreferences에서 파비콘 URL 로드
  static Future<String?> getFromPrefs(String serviceKey) async {
    try {
      final prefs = await SharedPreferences.getInstance();
      return prefs.getString('favicon_$serviceKey');
    } catch (e) {
      // 파비콘 캐시 로드 오류
      return null;
    }
  }

  // SharedPreferences에 파비콘 URL 저장
  static Future<void> saveToPrefs(String serviceKey, String logoUrl) async {
    try {
      final prefs = await SharedPreferences.getInstance();
      await prefs.setString('favicon_$serviceKey', logoUrl);
    } catch (e) {
      // 파비콘 캐시 저장 오류
    }
  }

  // 파비콘 캐시 삭제
  static Future<void> remove(String serviceKey) async {
    _memoryCache.remove(serviceKey);
    _loadingKeys.remove(serviceKey);
    try {
      final prefs = await SharedPreferences.getInstance();
      await prefs.remove('favicon_$serviceKey');
    } catch (e) {
      // 파비콘 캐시 삭제 오류
    }
  }

  // 앱에서 로컬 파비콘 파일 경로 가져오기
  static Future<String?> getLocalFaviconPath(String serviceKey) async {
    try {
      final prefs = await SharedPreferences.getInstance();
      return prefs.getString('local_favicon_$serviceKey');
    } catch (e) {
      // 로컬 파비콘 경로 로드 오류
      return null;
    }
  }

  // 앱에서 로컬 파비콘 파일 경로 저장
  static Future<void> saveLocalFaviconPath(
      String serviceKey, String filePath) async {
    try {
      final prefs = await SharedPreferences.getInstance();
      await prefs.setString('local_favicon_$serviceKey', filePath);
    } catch (e) {
      // 로컬 파비콘 경로 저장 오류
    }
  }
}

// 구글 파비콘 API 서비스
class GoogleFaviconService {
  // 구글 파비콘 API URL 생성
  static String getFaviconUrl(String domain, int size) {
    final directUrl =
        'https://t1.gstatic.com/faviconV2?client=SOCIAL&type=FAVICON&fallback_opts=TYPE,SIZE,URL&url=https://$domain&size=$size';
    return directUrl;
  }

  // DuckDuckGo 파비콘 API URL 생성 (CORS 친화적)
  static String getDuckDuckGoFaviconUrl(String domain) {
    return 'https://icons.duckduckgo.com/ip3/$domain.ico';
  }

  // 웹 환경용 이미지 URL 생성 (다양한 파비콘 서비스 시도)
  static String getWebFaviconUrl(String domain, int size) {
    // 다양한 파비콘 서비스 URL 목록
    final List<String> faviconServices = [
      // DuckDuckGo의 파비콘 서비스 (CORS 친화적)
      'https://icons.duckduckgo.com/ip3/$domain.ico',

      // Google의 S2 파비콘 서비스
      'https://www.google.com/s2/favicons?domain=$domain&sz=$size',
    ];

    // 첫 번째 서비스 사용 (DuckDuckGo 파비콘)
    return faviconServices[0];
  }

  // Base64로 인코딩된 기본 파비콘 (웹 환경 CORS 문제 완전 우회용)
  static String getBase64PlaceholderIcon(String serviceName, Color color) {
    // 간단한 SVG 생성 (서비스 이름의 첫 글자를 원 안에 표시)
    final initial = serviceName.isNotEmpty ? serviceName[0].toUpperCase() : '?';
    final colorHex =
        color.toARGB32().toRadixString(16).padLeft(8, '0').substring(2);

    // 공백 없이 SVG 생성 (공백이 있으면 Base64 디코딩 후 이미지 로드 시 문제 발생)
    final svgContent =
        '<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64">'
        '<rect width="64" height="64" rx="12" fill="#$colorHex"/>'
        '<text x="32" y="40" font-family="Arial, sans-serif" font-size="32" font-weight="bold" text-anchor="middle" fill="white">$initial</text>'
        '</svg>';

    // SVG를 Base64로 인코딩
    final base64 = base64Encode(utf8.encode(svgContent));
    return 'data:image/svg+xml;base64,$base64';
  }
}

class WebsiteIcon extends StatefulWidget {
  final String? url;
  final String serviceName;
  final double size;
  final bool isHovered;

  const WebsiteIcon({
    super.key,
    this.url,
    required this.serviceName,
    required this.size,
    this.isHovered = false,
  });

  @override
  State<WebsiteIcon> createState() => _WebsiteIconState();
}

class _WebsiteIconState extends State<WebsiteIcon>
    with SingleTickerProviderStateMixin {
  String? _logoUrl; // 웹에서 사용할 로고 URL
  String? _localLogoPath; // 앱에서 사용할 로컬 파일 경로
  bool _isLoading = true;
  late AnimationController _animationController;
  late Animation<double> _scaleAnimation;
  // 각 인스턴스에 대한 고유 식별자 추가
  final String _uniqueId = DateTime.now().millisecondsSinceEpoch.toString();
  // 서비스와 URL 조합으로 캐시 키 생성
  String get _serviceKey => '${widget.serviceName}_${widget.url ?? ''}';
  // 이전에 사용한 서비스 키 (URL이 변경됐는지 확인용)
  String? _previousServiceKey;

  @override
  void initState() {
    super.initState();

    // 애니메이션 컨트롤러 초기화
    _animationController = AnimationController(
      vsync: this,
      duration: ReduceMotion.platform()
          ? const Duration(milliseconds: 0)
          : const Duration(milliseconds: 300),
    );

    _scaleAnimation =
        Tween<double>(begin: 1.0, end: ReduceMotion.platform() ? 1.0 : 1.08)
            .animate(CurvedAnimation(
                parent: _animationController, curve: Curves.easeOutCubic));

    // 초기 _previousServiceKey 설정
    _previousServiceKey = _serviceKey;

    // 최초 로딩
    _loadFaviconWithCache();
  }

  // 캐시를 활용해 파비콘 로드
  Future<void> _loadFaviconWithCache() async {
    setState(() {
      _isLoading = true;
    });

    if (kIsWeb) {
      // 웹 환경: 메모리 캐시 확인 후 Google API 사용
      String? cachedLogo = FaviconCache.getFromMemory(_serviceKey);
      if (cachedLogo != null) {
        setState(() {
          _logoUrl = cachedLogo;
          _isLoading = false;
        });
        return;
      }

      // 이미 로딩 중인지 확인
      if (!FaviconCache.markAsLoading(_serviceKey)) {
        await Future.delayed(const Duration(milliseconds: 500));
        cachedLogo = FaviconCache.getFromMemory(_serviceKey);
        if (cachedLogo != null) {
          setState(() {
            _logoUrl = cachedLogo;
            _isLoading = false;
          });
        } else {
          FaviconCache.cancelLoading(_serviceKey);
          _fetchLogoForWeb();
        }
        return;
      }

      // SharedPreferences 확인
      cachedLogo = await FaviconCache.getFromPrefs(_serviceKey);
      if (cachedLogo != null) {
        FaviconCache.saveToMemory(_serviceKey, cachedLogo);
        if (mounted) {
          setState(() {
            _logoUrl = cachedLogo;
            _isLoading = false;
          });
        }
        return;
      }

      // 웹용 로고 가져오기
      _fetchLogoForWeb();
    } else {
      // 앱 환경: 로컬 파일 확인 후 다운로드

      // 1. 로컬 파일 경로 확인
      String? localPath = await FaviconCache.getLocalFaviconPath(_serviceKey);
      if (localPath != null) {
        final file = File(localPath);
        if (await file.exists()) {
          if (mounted) {
            setState(() {
              _localLogoPath = localPath;
              _isLoading = false;
            });
          }
          return;
        }
      }

      // 2. 이미 로딩 중인지 확인
      if (!FaviconCache.markAsLoading(_serviceKey)) {
        await Future.delayed(const Duration(milliseconds: 500));
        localPath = await FaviconCache.getLocalFaviconPath(_serviceKey);
        if (localPath != null) {
          final file = File(localPath);
          if (await file.exists()) {
            setState(() {
              _localLogoPath = localPath;
              _isLoading = false;
            });
          } else {
            FaviconCache.cancelLoading(_serviceKey);
            _fetchLogoForApp();
          }
        } else {
          FaviconCache.cancelLoading(_serviceKey);
          _fetchLogoForApp();
        }
        return;
      }

      // 3. 앱용 로고 다운로드
      _fetchLogoForApp();
    }
  }

  @override
  void didUpdateWidget(WebsiteIcon oldWidget) {
    super.didUpdateWidget(oldWidget);

    // 서비스명이나 URL이 변경된 경우에만 다시 로드
    final currentServiceKey = _serviceKey;
    if (_previousServiceKey != currentServiceKey) {
      // 서비스 키 변경 감지: $_previousServiceKey -> $currentServiceKey
      _previousServiceKey = currentServiceKey;

      // 변경된 서비스 정보로 파비콘 로드
      _loadFaviconWithCache();
    }

    // 호버 상태 변경 처리
    if (widget.isHovered != oldWidget.isHovered) {
      if (widget.isHovered) {
        _animationController.forward();
      } else {
        _animationController.reverse();
      }
    }
  }

  @override
  void dispose() {
    _animationController.dispose();
    super.dispose();
  }

  // 서비스 이름에서 초기 문자 추출
  String _getInitials() {
    if (widget.serviceName.isEmpty) return '?';

    final words = widget.serviceName.split(' ');
    if (words.length == 1) {
      return words[0][0].toUpperCase();
    } else if (words.length > 1) {
      return (words[0][0] + words[1][0]).toUpperCase();
    } else {
      return widget.serviceName[0].toUpperCase();
    }
  }

  // 서비스 이름을 기반으로 색상 선택
  Color _getColorFromName() {
    final int hash = widget.serviceName.hashCode.abs();
    final List<Color> colors = [
      const Color(0xFF2563EB), // primary
      const Color(0xFF22C55E), // success
      const Color(0xFF6366F1), // info
      const Color(0xFFF59E0B), // warning
      const Color(0xFFF472B6), // accent/danger
    ];

    return colors[hash % colors.length];
  }

  // 도메인 추출 메서드
  String? _extractDomain() {
    if (widget.url == null || widget.url!.isEmpty) return null;

    // URL 형식 처리 개선
    String processedUrl = widget.url!;

    // URL에 http:// 또는 https:// 접두사가 없는 경우 추가
    if (!processedUrl.startsWith('http://') &&
        !processedUrl.startsWith('https://')) {
      processedUrl = 'https://$processedUrl';
    }

    try {
      final uri = Uri.parse(processedUrl);
      if (uri.host.isEmpty) return processedUrl; // 파싱 실패 시 원본 URL 반환
      return uri.host;
    } catch (e) {
      // URL 파싱 실패 시 도메인만 있는 경우를 처리
      if (processedUrl.contains('.')) {
        // 간단한 도메인 형식 검사 (예: netflix.com)
        final domainPattern = RegExp(
          r'^(https?:\/\/)?(www\.)?([a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)+)',
        );
        final match = domainPattern.firstMatch(processedUrl);
        if (match != null && match.group(3) != null) {
          return match.group(3);
        }
      }
      return null;
    }
  }

  // 웹 환경용 파비콘 가져오기
  Future<void> _fetchLogoForWeb() async {
    try {
      final domain = _extractDomain();
      if (domain == null) {
        if (mounted) {
          setState(() {
            _isLoading = false;
          });
        }
        FaviconCache.cancelLoading(_serviceKey);
        return;
      }

      // 로딩 시작 시간 기록
      final loadStartTime = DateTime.now();

      // 1. DuckDuckGo Favicon API 시도 (CORS 친화적)
      final ddgFaviconUrl =
          GoogleFaviconService.getDuckDuckGoFaviconUrl(domain);

      try {
        // 이미지 존재 여부 확인을 위한 HEAD 요청
        final response = await http.head(Uri.parse(ddgFaviconUrl));

        if (response.statusCode == 200) {
          // DuckDuckGo로부터 파비콘을 성공적으로 가져옴
          if (mounted) {
            setState(() {
              _logoUrl = ddgFaviconUrl;
              _isLoading = false;
            });
          }

          // 캐시에 저장
          FaviconCache.saveToMemory(_serviceKey, ddgFaviconUrl);
          FaviconCache.saveToPrefs(_serviceKey, ddgFaviconUrl);
          FaviconCache.cancelLoading(_serviceKey);
          return;
        }
      } catch (e) {
        // DuckDuckGo 파비콘 API 요청 실패
        // 실패 시 백업 방법으로 진행
      }

      // 2. DuckDuckGo API가 실패하면 Base64 인코딩된 SVG 이미지를 로고로 사용 (CORS 회피)
      final color = _getColorFromName();
      final base64Logo = GoogleFaviconService.getBase64PlaceholderIcon(
          widget.serviceName, color);

      // 최소 로딩 시간 보장 (깜박임 방지)
      final processingTime =
          DateTime.now().difference(loadStartTime).inMilliseconds;
      if (processingTime < 300) {
        await Future.delayed(Duration(milliseconds: 300 - processingTime));
      }

      if (mounted) {
        setState(() {
          _logoUrl = base64Logo;
          _isLoading = false;
        });

        // 캐시에 저장
        FaviconCache.saveToMemory(_serviceKey, base64Logo);
        FaviconCache.saveToPrefs(_serviceKey, base64Logo);
      }

      FaviconCache.cancelLoading(_serviceKey);
    } catch (e) {
      // 웹용 파비콘 가져오기 오류
      if (mounted) {
        setState(() {
          _isLoading = false;
        });
      }
      FaviconCache.cancelLoading(_serviceKey);
    }
  }

  // 앱 환경용 파비콘 다운로드 및 로컬 저장
  Future<void> _fetchLogoForApp() async {
    try {
      final domain = _extractDomain();
      if (domain == null) {
        if (mounted) {
          setState(() {
            _isLoading = false;
          });
        }
        FaviconCache.cancelLoading(_serviceKey);
        return;
      }

      // 로딩 시작 시간 기록
      final loadStartTime = DateTime.now();

      // 1. Google API를 통해 파비콘 URL 생성
      final faviconUrl =
          GoogleFaviconService.getFaviconUrl(domain, widget.size.toInt() * 2);

      // 2. http.get()으로 이미지 다운로드
      final response = await http.get(Uri.parse(faviconUrl));

      if (response.statusCode != 200) {
        throw Exception('파비콘 다운로드 실패: ${response.statusCode}');
      }

      // 3. Uint8List로 변환
      final Uint8List imageBytes = response.bodyBytes;

      // 4. 고유한 파일명 생성 (서비스명 + URL의 해시)
      final String hash =
          md5.convert(utf8.encode(_serviceKey)).toString().substring(0, 8);
      final String fileName =
          'favicon_${widget.serviceName.replaceAll(' ', '_')}_$hash.png';

      // 5. 임시 디렉토리 가져오기
      final appDir = await getApplicationDocumentsDirectory();
      final faviconDir = Directory('${appDir.path}/favicons');
      if (!await faviconDir.exists()) {
        await faviconDir.create(recursive: true);
      }

      // 6. PNG 파일로 저장
      final File file = File('${faviconDir.path}/$fileName');
      await file.writeAsBytes(imageBytes);
      final String localFilePath = file.path;

      // 최소 로딩 시간 보장 (깜박임 방지)
      final processingTime =
          DateTime.now().difference(loadStartTime).inMilliseconds;
      if (processingTime < 300) {
        await Future.delayed(Duration(milliseconds: 300 - processingTime));
      }

      if (mounted) {
        setState(() {
          _localLogoPath = localFilePath;
          _isLoading = false;
        });

        // 로컬 파일 경로 캐시에 저장
        FaviconCache.saveLocalFaviconPath(_serviceKey, localFilePath);
      }

      FaviconCache.cancelLoading(_serviceKey);
    } catch (e) {
      // 앱용 파비콘 다운로드 오류
      if (mounted) {
        setState(() {
          _isLoading = false;
        });
      }
      FaviconCache.cancelLoading(_serviceKey);
    }
  }

  @override
  Widget build(BuildContext context) {
    return RepaintBoundary(
        child: AnimatedBuilder(
      animation: _animationController,
      builder: (context, child) {
        final scale =
            ReduceMotion.isEnabled(context) ? 1.0 : _scaleAnimation.value;
        return Transform.scale(
          scale: scale,
          child: child,
        );
      },
      child: AnimatedContainer(
        key: ValueKey(
            'icon_container_${widget.serviceName}_${widget.url ?? ''}_$_uniqueId'),
        duration: const Duration(milliseconds: 200),
        width: widget.size,
        height: widget.size,
        decoration: BoxDecoration(
          borderRadius: BorderRadius.circular(widget.size * 0.2),
          boxShadow: widget.isHovered
              ? [
                  BoxShadow(
                    color:
                        _getColorFromName().withValues(alpha: 0.3), // 약 0.3 알파값
                    blurRadius: 12,
                    spreadRadius: 0,
                    offset: const Offset(0, 4),
                  )
                ]
              : null,
        ),
        child: _buildIconContent(),
      ),
    ));
  }

  Widget _buildIconContent() {
    // 로딩 중 표시
    if (_isLoading) {
      if (ReduceMotion.isEnabled(context)) {
        return Container(
          key: ValueKey('loading_${widget.serviceName}_$_uniqueId'),
          decoration: BoxDecoration(
            color: Theme.of(context).colorScheme.surfaceContainerHighest,
            borderRadius: BorderRadius.circular(widget.size * 0.2),
            border: Border.all(
              color: Theme.of(context).colorScheme.outline,
              width: 0.5,
            ),
          ),
        );
      }
      return Container(
        key: ValueKey('loading_${widget.serviceName}_$_uniqueId'),
        decoration: BoxDecoration(
          color: Theme.of(context).colorScheme.surfaceContainerHighest,
          borderRadius: BorderRadius.circular(widget.size * 0.2),
          border: Border.all(
            color: Theme.of(context).colorScheme.outline,
            width: 0.5,
          ),
        ),
        child: Center(
          child: SizedBox(
            width: widget.size * 0.4,
            height: widget.size * 0.4,
            child: CircularProgressIndicator(
              strokeWidth: 2,
              valueColor: AlwaysStoppedAnimation<Color>(
                  Theme.of(context).colorScheme.primary.withValues(alpha: 0.7)),
            ),
          ),
        ),
      );
    }

    if (kIsWeb) {
      // 웹 환경: 파비콘 API에서 가져온 이미지 또는 Base64 인코딩된 이미지 사용
      if (_logoUrl != null) {
        if (_logoUrl!.startsWith('data:image/svg+xml;base64')) {
          // Base64 인코딩된 SVG 이미지인 경우
          return ClipRRect(
            key: ValueKey('web_svg_logo_${_logoUrl!.hashCode}'),
            borderRadius: BorderRadius.circular(widget.size * 0.2),
            child: SvgPicture.string(
              utf8.decode(base64.decode(_logoUrl!.split(',')[1])),
              width: widget.size,
              height: widget.size,
              fit: BoxFit.cover,
            ),
          );
        } else {
          // DuckDuckGo나 다른 파비콘 서비스에서 가져온 URL인 경우
          return ClipRRect(
            key: ValueKey('web_url_logo_${_logoUrl!.hashCode}'),
            borderRadius: BorderRadius.circular(widget.size * 0.2),
            child: CachedNetworkImage(
              imageUrl: _logoUrl!,
              width: widget.size,
              height: widget.size,
              fit: BoxFit.cover,
              fadeInDuration: ReduceMotion.isEnabled(context)
                  ? const Duration(milliseconds: 0)
                  : const Duration(milliseconds: 300),
              fadeOutDuration: ReduceMotion.isEnabled(context)
                  ? const Duration(milliseconds: 0)
                  : const Duration(milliseconds: 300),
              placeholder: (context, url) {
                if (ReduceMotion.isEnabled(context)) {
                  return Container(
                      color: Theme.of(context)
                          .colorScheme
                          .surfaceContainerHighest);
                }
                return Container(
                  color: Theme.of(context).colorScheme.surfaceContainerHighest,
                  child: Center(
                    child: SizedBox(
                      width: widget.size * 0.4,
                      height: widget.size * 0.4,
                      child: CircularProgressIndicator(
                        strokeWidth: 2,
                        valueColor: AlwaysStoppedAnimation<Color>(
                            Theme.of(context)
                                .colorScheme
                                .primary
                                .withValues(alpha: 0.7)),
                      ),
                    ),
                  ),
                );
              },
              errorWidget: (context, url, error) => _buildFallbackIcon(),
            ),
          );
        }
      }
      return _buildFallbackIcon();
    } else {
      // 앱 환경: 로컬 파일 표시
      if (_localLogoPath == null) {
        return _buildFallbackIcon();
      }

      return ClipRRect(
        key: ValueKey('local_logo_$_localLogoPath'),
        borderRadius: BorderRadius.circular(widget.size * 0.2),
        child: Image.file(
          File(_localLogoPath!),
          width: widget.size,
          height: widget.size,
          fit: BoxFit.cover,
          errorBuilder: (context, error, stackTrace) {
            return _buildFallbackIcon();
          },
        ),
      );
    }
  }

  Widget _buildFallbackIcon() {
    final color = _getColorFromName();

    return Container(
      key: ValueKey('fallback_${widget.serviceName}_$_uniqueId'),
      decoration: BoxDecoration(
        color: color,
        borderRadius: BorderRadius.circular(widget.size * 0.2),
      ),
      child: Center(
        child: Text(
          _getInitials(),
          style: TextStyle(
            color: Colors.white,
            fontWeight: FontWeight.w600,
            fontSize: widget.size * 0.4,
          ),
        ),
      ),
    );
  }
}
