/// 일정 상세 화면
library;

import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:lucide_icons/lucide_icons.dart';
import 'package:url_launcher/url_launcher.dart';
import '../../core/constants.dart';
import '../../models/schedule.dart';
import '../../services/schedules_service.dart';
import 'widgets/schedule_card.dart';
import 'widgets/member_chip.dart';

/// 카테고리 ID 상수
class CategoryId {
  static const int youtube = 2;
  static const int x = 3;
  static const int album = 4;
  static const int fansign = 5;
  static const int concert = 6;
  static const int ticket = 7;
}

/// 일정 상세 Provider
final scheduleDetailProvider =
    FutureProvider.family<ScheduleDetail, int>((ref, id) async {
  return await getSchedule(id);
});

class ScheduleDetailView extends ConsumerStatefulWidget {
  final int scheduleId;

  const ScheduleDetailView({super.key, required this.scheduleId});

  @override
  ConsumerState<ScheduleDetailView> createState() => _ScheduleDetailViewState();
}

class _ScheduleDetailViewState extends ConsumerState<ScheduleDetailView> {
  late int _currentScheduleId;

  @override
  void initState() {
    super.initState();
    _currentScheduleId = widget.scheduleId;
  }

  /// 회차 변경
  void _changeSchedule(int newId) {
    setState(() {
      _currentScheduleId = newId;
    });
  }

  /// URL 열기
  Future<void> _launchUrl(String url) async {
    final uri = Uri.parse(url);
    if (await canLaunchUrl(uri)) {
      await launchUrl(uri, mode: LaunchMode.externalApplication);
    }
  }

  /// 유튜브 비디오 ID 추출
  String? _extractYoutubeVideoId(String? url) {
    if (url == null) return null;
    final shortMatch = RegExp(r'youtu\.be/([a-zA-Z0-9_-]{11})').firstMatch(url);
    if (shortMatch != null) return shortMatch.group(1);
    final watchMatch =
        RegExp(r'youtube\.com/watch\?v=([a-zA-Z0-9_-]{11})').firstMatch(url);
    if (watchMatch != null) return watchMatch.group(1);
    final shortsMatch =
        RegExp(r'youtube\.com/shorts/([a-zA-Z0-9_-]{11})').firstMatch(url);
    if (shortsMatch != null) return shortsMatch.group(1);
    return null;
  }

  /// X URL에서 username 추출
  String? _extractXUsername(String? url) {
    if (url == null) return null;
    final match = RegExp(r'(?:twitter\.com|x\.com)/([^/]+)').firstMatch(url);
    return match?.group(1);
  }

  /// 날짜 포맷팅 (2026. 1. 15. (수))
  String _formatFullDate(String dateStr) {
    final date = DateTime.parse(dateStr);
    final dayNames = ['일', '월', '화', '수', '목', '금', '토'];
    return '${date.year}. ${date.month}. ${date.day}. (${dayNames[date.weekday % 7]})';
  }

  /// 단일 날짜 포맷팅 (1월 15일 (수) 19:00)
  String _formatSingleDate(String dateStr, String? timeStr) {
    final date = DateTime.parse(dateStr);
    final dayNames = ['일', '월', '화', '수', '목', '금', '토'];
    var result = '${date.month}월 ${date.day}일 (${dayNames[date.weekday % 7]})';
    if (timeStr != null && timeStr.length >= 5) {
      result += ' ${timeStr.substring(0, 5)}';
    }
    return result;
  }

  /// X용 날짜/시간 포맷팅 (오후 2:30 · 2026년 1월 15일)
  String _formatXDateTime(String dateStr, String? timeStr) {
    final date = DateTime.parse(dateStr);
    final year = date.year;
    final month = date.month;
    final day = date.day;

    var result = '$year년 $month월 $day일';

    if (timeStr != null && timeStr.length >= 5) {
      final parts = timeStr.split(':');
      final hours = int.parse(parts[0]);
      final minutes = parts[1];
      final period = hours < 12 ? '오전' : '오후';
      final hour12 = hours == 0 ? 12 : (hours > 12 ? hours - 12 : hours);
      result = '$period $hour12:$minutes · $result';
    }

    return result;
  }

  @override
  Widget build(BuildContext context) {
    final scheduleAsync = ref.watch(scheduleDetailProvider(_currentScheduleId));

    return Scaffold(
      backgroundColor: AppColors.background,
      appBar: AppBar(
        backgroundColor: Colors.white,
        elevation: 0,
        scrolledUnderElevation: 0.5,
        leading: IconButton(
          icon: const Icon(LucideIcons.chevronLeft, size: 24),
          onPressed: () => Navigator.of(context).pop(),
        ),
        title: scheduleAsync.whenOrNull(
          data: (schedule) => Text(
            schedule.categoryName ?? '',
            style: TextStyle(
              fontSize: 16,
              fontWeight: FontWeight.w600,
              color: parseColor(schedule.categoryColor),
            ),
          ),
        ),
        centerTitle: true,
      ),
      body: scheduleAsync.when(
        loading: () => const Center(
          child: CircularProgressIndicator(color: AppColors.primary),
        ),
        error: (error, stack) => _buildErrorView(),
        data: (schedule) => _buildContent(schedule),
      ),
    );
  }

  /// 에러 화면
  Widget _buildErrorView() {
    return Center(
      child: Padding(
        padding: const EdgeInsets.all(32),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Container(
              width: 80,
              height: 80,
              decoration: BoxDecoration(
                color: AppColors.primary.withValues(alpha: 0.1),
                borderRadius: BorderRadius.circular(20),
              ),
              child: Icon(
                LucideIcons.calendar,
                size: 40,
                color: AppColors.primary.withValues(alpha: 0.4),
              ),
            ),
            const SizedBox(height: 24),
            const Text(
              '일정을 찾을 수 없습니다',
              style: TextStyle(
                fontSize: 18,
                fontWeight: FontWeight.bold,
                color: AppColors.textPrimary,
              ),
            ),
            const SizedBox(height: 8),
            const Text(
              '요청하신 일정이 존재하지 않거나\n삭제되었을 수 있습니다.',
              textAlign: TextAlign.center,
              style: TextStyle(
                fontSize: 14,
                color: AppColors.textSecondary,
              ),
            ),
            const SizedBox(height: 32),
            OutlinedButton.icon(
              onPressed: () => Navigator.of(context).pop(),
              icon: const Icon(LucideIcons.arrowLeft, size: 18),
              label: const Text('돌아가기'),
              style: OutlinedButton.styleFrom(
                foregroundColor: AppColors.primary,
                side: const BorderSide(color: AppColors.primary),
                padding:
                    const EdgeInsets.symmetric(horizontal: 24, vertical: 12),
              ),
            ),
          ],
        ),
      ),
    );
  }

  /// 메인 컨텐츠
  Widget _buildContent(ScheduleDetail schedule) {
    return SingleChildScrollView(
      padding: const EdgeInsets.all(16),
      child: _buildCategorySection(schedule),
    );
  }

  /// 카테고리별 섹션
  Widget _buildCategorySection(ScheduleDetail schedule) {
    switch (schedule.categoryId) {
      case CategoryId.youtube:
        return _buildYoutubeSection(schedule);
      case CategoryId.x:
        return _buildXSection(schedule);
      case CategoryId.concert:
        return _buildConcertSection(schedule);
      default:
        return _buildDefaultSection(schedule);
    }
  }

  /// 유튜브 섹션
  Widget _buildYoutubeSection(ScheduleDetail schedule) {
    final videoId = _extractYoutubeVideoId(schedule.sourceUrl);
    final isShorts = schedule.sourceUrl?.contains('/shorts/') ?? false;

    if (videoId == null) return _buildDefaultSection(schedule);

    // 썸네일 URL
    final thumbnailUrl = 'https://img.youtube.com/vi/$videoId/maxresdefault.jpg';

    return Column(
      children: [
        // 썸네일 + 재생 버튼 (클릭시 YouTube로 이동)
        GestureDetector(
          onTap: () => _launchUrl(schedule.sourceUrl!),
          child: isShorts
              ? Center(
                  child: SizedBox(
                    width: 200,
                    child: ClipRRect(
                      borderRadius: BorderRadius.circular(12),
                      child: AspectRatio(
                        aspectRatio: 9 / 16,
                        child: Stack(
                          alignment: Alignment.center,
                          children: [
                            CachedNetworkImage(
                              imageUrl: thumbnailUrl,
                              fit: BoxFit.cover,
                              width: double.infinity,
                              height: double.infinity,
                              placeholder: (_, _) => Container(
                                color: Colors.grey[900],
                              ),
                              errorWidget: (_, _, _) => Container(
                                color: Colors.grey[900],
                                child: const Icon(LucideIcons.play, size: 48, color: Colors.white54),
                              ),
                            ),
                            _buildYoutubePlayButton(),
                          ],
                        ),
                      ),
                    ),
                  ),
                )
              : ClipRRect(
                  borderRadius: BorderRadius.circular(12),
                  child: AspectRatio(
                    aspectRatio: 16 / 9,
                    child: Stack(
                      alignment: Alignment.center,
                      children: [
                        CachedNetworkImage(
                          imageUrl: thumbnailUrl,
                          fit: BoxFit.cover,
                          width: double.infinity,
                          height: double.infinity,
                          placeholder: (_, _) => Container(
                            color: Colors.grey[900],
                          ),
                          errorWidget: (_, _, _) => Container(
                            color: Colors.grey[900],
                            child: const Icon(LucideIcons.play, size: 48, color: Colors.white54),
                          ),
                        ),
                        _buildYoutubePlayButton(),
                      ],
                    ),
                  ),
                ),
        ),
        const SizedBox(height: 16),
        // 정보 카드 (버튼 없음)
        _buildInfoCard(schedule, bottomButton: null),
      ],
    );
  }

  /// 유튜브 재생 버튼 (실제 유튜브 아이콘)
  Widget _buildYoutubePlayButton() {
    return Container(
      width: 68,
      height: 48,
      decoration: BoxDecoration(
        color: Colors.red,
        borderRadius: BorderRadius.circular(12),
        boxShadow: [
          BoxShadow(
            color: Colors.black.withValues(alpha: 0.4),
            blurRadius: 12,
            offset: const Offset(0, 4),
          ),
        ],
      ),
      child: Center(
        child: CustomPaint(
          size: const Size(24, 24),
          painter: _YoutubePlayIconPainter(),
        ),
      ),
    );
  }

  /// X 섹션 (웹과 동일)
  Widget _buildXSection(ScheduleDetail schedule) {
    final username = _extractXUsername(schedule.sourceUrl);
    final displayName = schedule.sourceName ?? username ?? 'Unknown';

    return Container(
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.circular(12),
        border: Border.all(color: AppColors.border),
      ),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          // 헤더
          Padding(
            padding: const EdgeInsets.fromLTRB(16, 16, 16, 0),
            child: Row(
              children: [
                // 프로필 이미지
                Container(
                  width: 40,
                  height: 40,
                  decoration: BoxDecoration(
                    gradient: LinearGradient(
                      begin: Alignment.topLeft,
                      end: Alignment.bottomRight,
                      colors: [Colors.grey[700]!, Colors.grey[900]!],
                    ),
                    shape: BoxShape.circle,
                  ),
                  child: Center(
                    child: Text(
                      displayName[0].toUpperCase(),
                      style: const TextStyle(
                        color: Colors.white,
                        fontWeight: FontWeight.bold,
                        fontSize: 16,
                      ),
                    ),
                  ),
                ),
                const SizedBox(width: 12),
                Expanded(
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      Row(
                        children: [
                          Flexible(
                            child: Text(
                              displayName,
                              style: const TextStyle(
                                fontWeight: FontWeight.bold,
                                fontSize: 14,
                              ),
                              overflow: TextOverflow.ellipsis,
                            ),
                          ),
                          const SizedBox(width: 4),
                          // 인증 배지 (웹과 동일한 SVG 형태)
                          _buildVerifiedBadge(),
                        ],
                      ),
                      if (username != null)
                        Text(
                          '@$username',
                          style: TextStyle(
                            fontSize: 13,
                            color: Colors.grey[500],
                          ),
                        ),
                    ],
                  ),
                ),
              ],
            ),
          ),
          // 본문
          Padding(
            padding: const EdgeInsets.all(16),
            child: Text(
              decodeHtmlEntities(schedule.description ?? schedule.title),
              style: const TextStyle(
                fontSize: 15,
                height: 1.5,
                color: AppColors.textPrimary,
              ),
            ),
          ),
          // 이미지
          if (schedule.imageUrl != null) ...[
            Padding(
              padding: const EdgeInsets.fromLTRB(16, 0, 16, 12),
              child: ClipRRect(
                borderRadius: BorderRadius.circular(12),
                child: CachedNetworkImage(
                  imageUrl: schedule.imageUrl!,
                  fit: BoxFit.cover,
                  placeholder: (_, _) => Container(
                    height: 200,
                    color: Colors.grey[200],
                  ),
                  errorWidget: (_, _, _) => const SizedBox.shrink(),
                ),
              ),
            ),
          ],
          // 날짜/시간
          Container(
            padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
            decoration: BoxDecoration(
              border: Border(top: BorderSide(color: Colors.grey[100]!)),
            ),
            child: Text(
              _formatXDateTime(schedule.date, schedule.time),
              style: TextStyle(
                fontSize: 14,
                color: Colors.grey[500],
              ),
            ),
          ),
          // X에서 보기 버튼
          Container(
            padding: const EdgeInsets.all(16),
            decoration: BoxDecoration(
              color: Colors.grey[50],
              border: Border(top: BorderSide(color: Colors.grey[100]!)),
            ),
            child: SizedBox(
              width: double.infinity,
              child: ElevatedButton(
                onPressed: () => _launchUrl(schedule.sourceUrl ?? ''),
                style: ElevatedButton.styleFrom(
                  backgroundColor: Colors.grey[900],
                  foregroundColor: Colors.white,
                  padding: const EdgeInsets.symmetric(vertical: 12),
                  shape: RoundedRectangleBorder(
                    borderRadius: BorderRadius.circular(24),
                  ),
                ),
                child: Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    // X 로고
                    _buildXLogo(14),
                    const SizedBox(width: 8),
                    const Text(
                      'X에서 보기',
                      style: TextStyle(fontWeight: FontWeight.w500),
                    ),
                  ],
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }

  /// 인증 배지 (웹과 동일한 SVG)
  Widget _buildVerifiedBadge() {
    return SizedBox(
      width: 16,
      height: 16,
      child: CustomPaint(
        painter: _VerifiedBadgePainter(),
      ),
    );
  }

  /// X 로고
  Widget _buildXLogo(double size) {
    return SizedBox(
      width: size,
      height: size,
      child: CustomPaint(
        painter: _XLogoPainter(),
      ),
    );
  }

  /// 콘서트 섹션
  Widget _buildConcertSection(ScheduleDetail schedule) {
    final hasLocation =
        schedule.locationLat != null && schedule.locationLng != null;
    final hasPoster = schedule.images.isNotEmpty;
    final hasMultipleDates = schedule.relatedDates.length > 1;

    return Container(
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.circular(12),
        boxShadow: [
          BoxShadow(
            color: Colors.black.withValues(alpha: 0.04),
            blurRadius: 12,
            offset: const Offset(0, 2),
          ),
        ],
      ),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          // 헤더 (포스터 여백 제거)
          Container(
            decoration: BoxDecoration(
              gradient: LinearGradient(
                colors: [AppColors.primary, AppColors.primary.withValues(alpha: 0.8)],
              ),
              borderRadius:
                  const BorderRadius.vertical(top: Radius.circular(12)),
            ),
            child: Row(
              children: [
                if (hasPoster)
                  ClipRRect(
                    borderRadius: const BorderRadius.only(topLeft: Radius.circular(12)),
                    child: CachedNetworkImage(
                      imageUrl: schedule.images[0],
                      width: 56,
                      height: 72,
                      fit: BoxFit.cover,
                      placeholder: (_, _) => Container(
                        width: 56,
                        height: 72,
                        color: Colors.white24,
                      ),
                      errorWidget: (_, _, _) => const SizedBox.shrink(),
                    ),
                  ),
                Expanded(
                  child: Padding(
                    padding: const EdgeInsets.all(16),
                    child: Text(
                      decodeHtmlEntities(schedule.title),
                      style: const TextStyle(
                        color: Colors.white,
                        fontWeight: FontWeight.bold,
                        fontSize: 15,
                      ),
                      maxLines: 2,
                      overflow: TextOverflow.ellipsis,
                    ),
                  ),
                ),
              ],
            ),
          ),
          // 정보 목록
          Padding(
            padding: const EdgeInsets.all(16),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                // 공연 일정
                _buildSectionLabel(LucideIcons.calendar, '공연 일정'),
                const SizedBox(height: 8),
                if (hasMultipleDates)
                  ...schedule.relatedDates.asMap().entries.map((entry) {
                    final index = entry.key;
                    final item = entry.value;
                    final isCurrent = item.id == schedule.id;
                    return Padding(
                      padding: const EdgeInsets.only(bottom: 8),
                      child: InkWell(
                        onTap: isCurrent ? null : () => _changeSchedule(item.id),
                        borderRadius: BorderRadius.circular(8),
                        child: Container(
                          width: double.infinity,
                          padding: const EdgeInsets.symmetric(
                            horizontal: 12,
                            vertical: 10,
                          ),
                          decoration: BoxDecoration(
                            color: isCurrent
                                ? AppColors.primary
                                : Colors.grey[100],
                            borderRadius: BorderRadius.circular(8),
                          ),
                          child: Text(
                            '${index + 1}회차  ${_formatSingleDate(item.date, item.time)}',
                            style: TextStyle(
                              fontSize: 13,
                              // 볼드체 제거
                              color: isCurrent
                                  ? Colors.white
                                  : AppColors.textPrimary,
                            ),
                          ),
                        ),
                      ),
                    );
                  })
                else
                  Text(
                    _formatSingleDate(schedule.date, schedule.time),
                    style: const TextStyle(
                      fontWeight: FontWeight.bold,
                      fontSize: 14,
                    ),
                  ),
                const SizedBox(height: 16),
                // 장소
                if (schedule.locationName != null) ...[
                  _buildSectionLabel(LucideIcons.mapPin, '장소'),
                  const SizedBox(height: 8),
                  Text(
                    schedule.locationName!,
                    style: const TextStyle(
                      fontWeight: FontWeight.w600,
                      fontSize: 14,
                    ),
                  ),
                  if (schedule.locationAddress != null) ...[
                    const SizedBox(height: 2),
                    Text(
                      schedule.locationAddress!,
                      style: const TextStyle(
                        fontSize: 12,
                        color: AppColors.textSecondary,
                      ),
                    ),
                  ],
                  const SizedBox(height: 16),
                ],
                // 위치 (지도)
                if (hasLocation) ...[
                  _buildSectionLabel(LucideIcons.navigation, '위치'),
                  const SizedBox(height: 8),
                  // 지도 플레이스홀더 (탭시 카카오맵으로 이동)
                  GestureDetector(
                    onTap: () => _launchUrl(
                      'https://map.kakao.com/link/map/${Uri.encodeComponent(schedule.locationName!)},${schedule.locationLat},${schedule.locationLng}',
                    ),
                    child: Container(
                      height: 160,
                      decoration: BoxDecoration(
                        color: Colors.grey[100],
                        borderRadius: BorderRadius.circular(12),
                        border: Border.all(color: AppColors.border),
                      ),
                      child: Stack(
                        children: [
                          // 지도 이미지 (카카오 Static Map API)
                          ClipRRect(
                            borderRadius: BorderRadius.circular(11),
                            child: CachedNetworkImage(
                              imageUrl: 'https://map.kakao.com/link/map/${Uri.encodeComponent(schedule.locationName!)},${schedule.locationLat},${schedule.locationLng}',
                              fit: BoxFit.cover,
                              width: double.infinity,
                              height: double.infinity,
                              placeholder: (_, _) => Container(
                                color: Colors.grey[200],
                                child: const Center(
                                  child: Icon(LucideIcons.map, size: 32, color: Colors.grey),
                                ),
                              ),
                              errorWidget: (_, _, _) => Container(
                                color: Colors.grey[200],
                                child: Center(
                                  child: Column(
                                    mainAxisAlignment: MainAxisAlignment.center,
                                    children: [
                                      Icon(LucideIcons.navigation, size: 28, color: Colors.grey[400]),
                                      const SizedBox(height: 8),
                                      Text(
                                        schedule.locationName!,
                                        style: TextStyle(
                                          fontSize: 13,
                                          fontWeight: FontWeight.w500,
                                          color: Colors.grey[600],
                                        ),
                                        textAlign: TextAlign.center,
                                      ),
                                      const SizedBox(height: 4),
                                      Text(
                                        '탭하여 지도에서 보기',
                                        style: TextStyle(
                                          fontSize: 11,
                                          color: Colors.grey[400],
                                        ),
                                      ),
                                    ],
                                  ),
                                ),
                              ),
                            ),
                          ),
                        ],
                      ),
                    ),
                  ),
                  const SizedBox(height: 16),
                ],
                // 설명
                if (schedule.description != null &&
                    schedule.description!.isNotEmpty) ...[
                  Container(
                    width: double.infinity,
                    padding: const EdgeInsets.only(top: 16),
                    decoration: BoxDecoration(
                      border: Border(
                        top: BorderSide(color: AppColors.divider),
                      ),
                    ),
                    child: Text(
                      decodeHtmlEntities(schedule.description!),
                      style: const TextStyle(
                        fontSize: 14,
                        color: AppColors.textSecondary,
                        height: 1.5,
                      ),
                    ),
                  ),
                ],
              ],
            ),
          ),
          // 버튼 영역
          Padding(
            padding: const EdgeInsets.fromLTRB(16, 0, 16, 16),
            child: Column(
              children: [
                // 길찾기 버튼 (파란색)
                if (hasLocation)
                  SizedBox(
                    width: double.infinity,
                    child: ElevatedButton(
                      onPressed: () => _launchUrl(
                          'https://map.kakao.com/link/to/${Uri.encodeComponent(schedule.locationName!)},${schedule.locationLat},${schedule.locationLng}'),
                      style: ElevatedButton.styleFrom(
                        backgroundColor: const Color(0xFF3B82F6), // blue-500
                        foregroundColor: Colors.white,
                        padding: const EdgeInsets.symmetric(vertical: 14),
                        shape: RoundedRectangleBorder(
                          borderRadius: BorderRadius.circular(12),
                        ),
                      ),
                      child: Row(
                        mainAxisAlignment: MainAxisAlignment.center,
                        children: const [
                          Icon(LucideIcons.navigation, size: 18),
                          SizedBox(width: 8),
                          Text('길찾기'),
                        ],
                      ),
                    ),
                  ),
                if (hasLocation && schedule.sourceUrl != null)
                  const SizedBox(height: 8),
                // 상세 정보 버튼
                if (schedule.sourceUrl != null)
                  SizedBox(
                    width: double.infinity,
                    child: ElevatedButton(
                      onPressed: () => _launchUrl(schedule.sourceUrl!),
                      style: ElevatedButton.styleFrom(
                        backgroundColor: Colors.grey[900],
                        foregroundColor: Colors.white,
                        padding: const EdgeInsets.symmetric(vertical: 14),
                        shape: RoundedRectangleBorder(
                          borderRadius: BorderRadius.circular(12),
                        ),
                      ),
                      child: Row(
                        mainAxisAlignment: MainAxisAlignment.center,
                        children: const [
                          Icon(LucideIcons.externalLink, size: 18),
                          SizedBox(width: 8),
                          Text('상세 정보 보기'),
                        ],
                      ),
                    ),
                  ),
              ],
            ),
          ),
        ],
      ),
    );
  }

  /// 기본 섹션
  Widget _buildDefaultSection(ScheduleDetail schedule) {
    return _buildInfoCard(
      schedule,
      bottomButton: schedule.sourceUrl != null
          ? SizedBox(
              width: double.infinity,
              child: ElevatedButton(
                onPressed: () => _launchUrl(schedule.sourceUrl!),
                style: ElevatedButton.styleFrom(
                  backgroundColor: Colors.grey[900],
                  foregroundColor: Colors.white,
                  padding: const EdgeInsets.symmetric(vertical: 14),
                  shape: RoundedRectangleBorder(
                    borderRadius: BorderRadius.circular(12),
                  ),
                ),
                child: Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: const [
                    Icon(LucideIcons.externalLink, size: 18),
                    SizedBox(width: 8),
                    Text('원본 보기'),
                  ],
                ),
              ),
            )
          : null,
    );
  }

  /// 정보 카드
  Widget _buildInfoCard(ScheduleDetail schedule, {Widget? bottomButton}) {
    final isFullGroup = schedule.members.length >= 5;

    return Container(
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.circular(12),
        boxShadow: [
          BoxShadow(
            color: Colors.black.withValues(alpha: 0.04),
            blurRadius: 12,
            offset: const Offset(0, 2),
          ),
        ],
      ),
      padding: const EdgeInsets.all(16),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          // 제목
          Text(
            decodeHtmlEntities(schedule.title),
            style: const TextStyle(
              fontSize: 16,
              fontWeight: FontWeight.bold,
              color: AppColors.textPrimary,
              height: 1.4,
            ),
          ),
          const SizedBox(height: 12),
          // 메타 정보
          Wrap(
            spacing: 12,
            runSpacing: 8,
            children: [
              _buildMetaItem(LucideIcons.calendar, _formatFullDate(schedule.date)),
              if (schedule.formattedTime != null)
                _buildMetaItem(LucideIcons.clock, schedule.formattedTime!),
              if (schedule.sourceName != null)
                _buildMetaItem(LucideIcons.link2, schedule.sourceName!),
            ],
          ),
          // 멤버
          if (schedule.members.isNotEmpty) ...[
            const SizedBox(height: 16),
            Container(
              width: double.infinity,
              height: 1,
              color: AppColors.divider,
            ),
            const SizedBox(height: 16),
            Wrap(
              spacing: 6,
              runSpacing: 6,
              children: isFullGroup
                  ? [const MemberChip(name: '프로미스나인')]
                  : schedule.members
                      .map((m) => MemberChip(name: m.name))
                      .toList(),
            ),
          ],
          // 설명
          if (schedule.description != null &&
              schedule.description!.isNotEmpty) ...[
            const SizedBox(height: 16),
            Text(
              decodeHtmlEntities(schedule.description!),
              style: const TextStyle(
                fontSize: 14,
                color: AppColors.textSecondary,
                height: 1.5,
              ),
            ),
          ],
          // 하단 버튼
          if (bottomButton != null) ...[
            const SizedBox(height: 16),
            bottomButton,
          ],
        ],
      ),
    );
  }

  /// 메타 아이템
  Widget _buildMetaItem(IconData icon, String text) {
    return Row(
      mainAxisSize: MainAxisSize.min,
      children: [
        Icon(icon, size: 14, color: AppColors.textSecondary),
        const SizedBox(width: 4),
        Text(
          text,
          style: const TextStyle(
            fontSize: 12,
            color: AppColors.textSecondary,
          ),
        ),
      ],
    );
  }

  /// 섹션 라벨
  Widget _buildSectionLabel(IconData icon, String text) {
    return Row(
      children: [
        Icon(icon, size: 14, color: AppColors.textSecondary),
        const SizedBox(width: 6),
        Text(
          text,
          style: const TextStyle(
            fontSize: 12,
            fontWeight: FontWeight.w500,
            color: AppColors.textSecondary,
          ),
        ),
      ],
    );
  }
}

/// 유튜브 재생 아이콘 페인터
class _YoutubePlayIconPainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    final paint = Paint()
      ..color = Colors.white
      ..style = PaintingStyle.fill;

    final path = Path()
      ..moveTo(size.width * 0.35, size.height * 0.25)
      ..lineTo(size.width * 0.35, size.height * 0.75)
      ..lineTo(size.width * 0.75, size.height * 0.5)
      ..close();

    canvas.drawPath(path, paint);
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
}

/// 인증 배지 페인터 (웹과 동일한 디자인)
class _VerifiedBadgePainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    final paint = Paint()
      ..color = const Color(0xFF3B82F6) // blue-500
      ..style = PaintingStyle.fill;

    // 배지 배경 (둥근 별 모양)
    final center = Offset(size.width / 2, size.height / 2);
    final radius = size.width / 2;
    canvas.drawCircle(center, radius, paint);

    // 체크마크
    final checkPaint = Paint()
      ..color = Colors.white
      ..style = PaintingStyle.stroke
      ..strokeWidth = 1.5
      ..strokeCap = StrokeCap.round
      ..strokeJoin = StrokeJoin.round;

    final checkPath = Path()
      ..moveTo(size.width * 0.28, size.height * 0.52)
      ..lineTo(size.width * 0.45, size.height * 0.68)
      ..lineTo(size.width * 0.72, size.height * 0.35);

    canvas.drawPath(checkPath, checkPaint);
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
}

/// X 로고 페인터
class _XLogoPainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    final paint = Paint()
      ..color = Colors.white
      ..style = PaintingStyle.fill;

    final path = Path();
    // X 로고 경로 (간소화)
    path.moveTo(size.width * 0.76, size.height * 0.09);
    path.lineTo(size.width * 0.9, size.height * 0.09);
    path.lineTo(size.width * 0.6, size.height * 0.44);
    path.lineTo(size.width * 0.95, size.height * 0.91);
    path.lineTo(size.width * 0.67, size.height * 0.91);
    path.lineTo(size.width * 0.46, size.height * 0.63);
    path.lineTo(size.width * 0.21, size.height * 0.91);
    path.lineTo(size.width * 0.07, size.height * 0.91);
    path.lineTo(size.width * 0.4, size.height * 0.53);
    path.lineTo(size.width * 0.05, size.height * 0.09);
    path.lineTo(size.width * 0.34, size.height * 0.09);
    path.lineTo(size.width * 0.52, size.height * 0.35);
    path.close();

    canvas.drawPath(path, paint);
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
}
