import 'dart:async';
import 'dart:math';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:google_mobile_ads/google_mobile_ads.dart';
import 'package:lunchpick/core/constants/app_colors.dart';
import 'package:lunchpick/core/constants/app_typography.dart';
import 'package:lunchpick/core/utils/ad_helper.dart';

/// 실제 네이티브 광고(Native Ad)를 표시하는 영역.
/// 광고 미지원 플랫폼이나 로드 실패 시 이전 플레이스홀더 스타일을 유지한다.
class NativeAdPlaceholder extends StatefulWidget {
  final EdgeInsetsGeometry? margin;
  final double height;
  final Duration refreshInterval;
  final bool enabled;

  const NativeAdPlaceholder({
    super.key,
    this.margin,
    this.height = 200,
    this.refreshInterval = const Duration(minutes: 2),
    this.enabled = true,
  });

  @override
  State<NativeAdPlaceholder> createState() => _NativeAdPlaceholderState();
}

class _NativeAdPlaceholderState extends State<NativeAdPlaceholder> {
  NativeAd? _nativeAd;
  Timer? _refreshTimer;
  bool _isLoading = false;
  bool _isLoaded = false;

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addPostFrameCallback((_) {
      if (!mounted || !widget.enabled) return;
      _loadAd();
    });
  }

  @override
  void didUpdateWidget(covariant NativeAdPlaceholder oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (!widget.enabled) {
      _disposeAd();
      setState(() {
        _isLoading = false;
        _isLoaded = false;
      });
      return;
    }

    final oldType = _templateTypeForHeight(oldWidget.height);
    final newType = _templateTypeForHeight(widget.height);

    if (oldType != newType) {
      _loadAd();
      return;
    }

    if (!oldWidget.enabled && widget.enabled) {
      _loadAd();
      return;
    }

    if (widget.refreshInterval != oldWidget.refreshInterval && _isLoaded) {
      _scheduleRefresh();
    }
  }

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

  void _disposeAd() {
    _refreshTimer?.cancel();
    _refreshTimer = null;
    _nativeAd?.dispose();
    _nativeAd = null;
  }

  void _loadAd() {
    if (!widget.enabled) return;
    if (!AdHelper.isMobilePlatform) return;
    if (!mounted) return;

    _refreshTimer?.cancel();
    _nativeAd?.dispose();

    setState(() {
      _isLoading = true;
      _isLoaded = false;
    });

    final adUnitId = AdHelper.nativeAdUnitId;
    final templateType = _templateTypeForHeight(widget.height);
    _nativeAd = NativeAd(
      adUnitId: adUnitId,
      request: const AdRequest(),
      nativeTemplateStyle: _buildTemplateStyle(templateType),
      listener: NativeAdListener(
        onAdLoaded: (ad) {
          if (!mounted) {
            ad.dispose();
            return;
          }
          setState(() {
            _isLoaded = true;
            _isLoading = false;
          });
          _scheduleRefresh();
        },
        onAdFailedToLoad: (ad, error) {
          ad.dispose();
          if (!mounted) return;
          setState(() {
            _isLoading = false;
            _isLoaded = false;
          });
          _scheduleRefresh(retry: true);
        },
        onAdClicked: (ad) => _scheduleRefresh(),
        onAdOpened: (ad) => _scheduleRefresh(),
      ),
    )..load();
  }

  void _scheduleRefresh({bool retry = false}) {
    _refreshTimer?.cancel();
    if (!mounted) return;
    if (!widget.enabled) return;
    final delay = retry ? const Duration(seconds: 30) : widget.refreshInterval;
    _refreshTimer = Timer(delay, _loadAd);
  }

  NativeTemplateStyle _buildTemplateStyle(TemplateType templateType) {
    final isDark = Theme.of(context).brightness == Brightness.dark;
    return NativeTemplateStyle(
      templateType: templateType,
      mainBackgroundColor: isDark ? AppColors.darkSurface : Colors.white,
      cornerRadius: 0,
      callToActionTextStyle: NativeTemplateTextStyle(
        textColor: Colors.white,
        backgroundColor: AppColors.lightPrimary,
        style: NativeTemplateFontStyle.bold,
      ),
      primaryTextStyle: NativeTemplateTextStyle(
        textColor: isDark ? Colors.white : Colors.black87,
        style: NativeTemplateFontStyle.bold,
      ),
      secondaryTextStyle: NativeTemplateTextStyle(
        textColor: isDark ? Colors.white70 : Colors.black54,
        style: NativeTemplateFontStyle.normal,
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    final isDark = Theme.of(context).brightness == Brightness.dark;
    final containerHeight = _resolveContainerHeight();

    if (!AdHelper.isMobilePlatform || !widget.enabled) {
      return _buildPlaceholder(
        isDark,
        containerHeight: containerHeight,
        isLoading: false,
      );
    }

    return AnimatedSwitcher(
      duration: const Duration(milliseconds: 250),
      child: _isLoaded && _nativeAd != null
          ? _buildAdView(isDark, containerHeight)
          : _buildPlaceholder(
              isDark,
              containerHeight: containerHeight,
              isLoading: _isLoading,
            ),
    );
  }

  Widget _buildAdView(bool isDark, double containerHeight) {
    return Container(
      key: const ValueKey('nativeAdLoaded'),
      margin: widget.margin ?? EdgeInsets.zero,
      height: containerHeight,
      width: double.infinity,
      decoration: _decoration(isDark),
      child: AdWidget(ad: _nativeAd!),
    );
  }

  Widget _buildPlaceholder(
    bool isDark, {
    required double containerHeight,
    required bool isLoading,
  }) {
    return Container(
      key: const ValueKey('nativeAdPlaceholder'),
      margin: widget.margin ?? EdgeInsets.zero,
      padding: const EdgeInsets.all(16),
      height: containerHeight,
      width: double.infinity,
      decoration: _decoration(isDark),
      child: Center(
        child: Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            const Icon(Icons.ad_units, color: AppColors.lightPrimary, size: 24),
            const SizedBox(width: 8),
            Text(
              isLoading ? '광고 불러오는 중...' : '광고 영역',
              style: AppTypography.heading2(isDark),
            ),
          ],
        ),
      ),
    );
  }

  double _resolveContainerHeight() {
    final templateType = _templateTypeForHeight(widget.height);
    final minHeight = _templateMinHeight(templateType);
    return max(widget.height, minHeight);
  }

  TemplateType _templateTypeForHeight(double height) {
    // Medium 템플릿은 SDK 기본 레이아웃이 커서, 높이가 낮을 경우 Small로 대체해 잘림을 방지한다.
    return height < 320 ? TemplateType.small : TemplateType.medium;
  }

  double _templateMinHeight(TemplateType type) {
    if (type == TemplateType.small) {
      return 120;
    }
    return switch (defaultTargetPlatform) {
      TargetPlatform.iOS => 402.0,
      TargetPlatform.android => 350.0,
      _ => 320.0,
    };
  }

  BoxDecoration _decoration(bool isDark) {
    return BoxDecoration(
      color: isDark ? AppColors.darkSurface : Colors.white,
      border: Border.all(
        color: isDark ? AppColors.darkDivider : AppColors.lightDivider,
        width: 2,
      ),
      boxShadow: [
        BoxShadow(
          color: (isDark ? Colors.black : Colors.grey).withOpacity(0.08),
          blurRadius: 8,
          offset: const Offset(0, 4),
        ),
      ],
    );
  }
}
