import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:shadcn_ui/shadcn_ui.dart';

import '../../core/app_colors.dart';
import '../../core/app_design_tokens.dart';
import '../../core/app_module_visuals.dart';
import '../../core/app_theme.dart';
import '../../core/navigation_provider.dart';
import '../../providers/data_providers.dart';
import '../../services/in_app_notification_service.dart';

class NotificationCenterPage extends ConsumerStatefulWidget {
  const NotificationCenterPage({super.key});

  @override
  ConsumerState<NotificationCenterPage> createState() =>
      _NotificationCenterPageState();
}

class _NotificationCenterPageState
    extends ConsumerState<NotificationCenterPage> {
  InAppNotificationHistory? _history;
  bool _loading = true;
  bool _markingAll = false;
  bool _showEarlier = false;
  String? _error;

  InAppNotificationService get _service =>
      ref.read(inAppNotificationServiceProvider);

  @override
  void initState() {
    super.initState();
    Future.microtask(_load);
  }

  Future<void> _load() async {
    if (mounted) {
      setState(() {
        _loading = true;
        _error = null;
      });
    }
    try {
      final history = await _service.getHistory();
      if (!mounted) return;
      setState(() {
        _history = history;
        _loading = false;
      });
      ref.invalidate(notificationUnreadCountProvider);
    } catch (error) {
      if (!mounted) return;
      setState(() {
        _error = '$error';
        _loading = false;
      });
    }
  }

  Future<void> _open(InAppNotification item) async {
    if (!item.isRead) {
      await _service.acknowledge(item.id);
      if (!mounted) return;
      setState(() {
        final current = _history;
        if (current == null) return;
        _history = InAppNotificationHistory(
          unreadCount: (current.unreadCount - 1).clamp(0, current.unreadCount),
          items: current.items
              .map(
                (value) =>
                    value.id == item.id ? value.copyWith(isRead: true) : value,
              )
              .toList(),
        );
      });
      ref.invalidate(notificationUnreadCountProvider);
    }

    if (!mounted || item.actionType == null) return;
    switch (item.actionType) {
      case 'medication':
        pushRoute(ref, 'medCheckIn', params: {'id': item.actionTargetId ?? ''});
        return;
      case 'exercise':
        pushRoute(ref, 'exercisePlan');
        return;
      case 'health':
        pushRoute(ref, 'trend', params: {'type': item.actionTargetId ?? ''});
        return;
      case 'report':
        final reportId = item.actionTargetId;
        if (reportId != null && reportId.isNotEmpty) {
          pushRoute(ref, 'aiAnalysis', params: {'id': reportId});
        }
        return;
    }
  }

  Future<void> _markAllRead() async {
    if (_markingAll || (_history?.unreadCount ?? 0) == 0) return;
    setState(() => _markingAll = true);
    try {
      await _service.markAllRead();
      if (!mounted) return;
      final current = _history;
      if (current != null) {
        setState(
          () => _history = InAppNotificationHistory(
            unreadCount: 0,
            items: current.items
                .map((item) => item.copyWith(isRead: true))
                .toList(),
          ),
        );
      }
      ref.invalidate(notificationUnreadCountProvider);
    } finally {
      if (mounted) setState(() => _markingAll = false);
    }
  }

  Future<void> _delete(InAppNotification item) async {
    try {
      await _service.delete(item.id);
      if (!mounted) return;
      final current = _history;
      if (current != null) {
        setState(
          () => _history = InAppNotificationHistory(
            unreadCount: item.isRead
                ? current.unreadCount
                : (current.unreadCount - 1).clamp(0, current.unreadCount),
            items: current.items.where((value) => value.id != item.id).toList(),
          ),
        );
      }
      ref.invalidate(notificationUnreadCountProvider);
    } catch (_) {
      if (mounted) await _load();
    }
  }

  @override
  Widget build(BuildContext context) {
    final items = _history?.items ?? const <InAppNotification>[];
    final unread = _history?.unreadCount ?? 0;

    return Scaffold(
      backgroundColor: const Color(0xFFF6F8FC),
      appBar: AppBar(
        backgroundColor: Colors.white,
        elevation: 0,
        scrolledUnderElevation: 0.5,
        surfaceTintColor: Colors.transparent,
        leading: IconButton(
          icon: const Icon(Icons.arrow_back, color: AppColors.textPrimary),
          onPressed: () => popRoute(ref),
        ),
        title: const Text(
          '通知中心',
          style: TextStyle(
            fontSize: 19,
            fontWeight: FontWeight.w800,
            color: AppColors.textPrimary,
          ),
        ),
        centerTitle: true,
        actions: [
          if (unread > 0)
            TextButton(
              onPressed: _markingAll ? null : _markAllRead,
              child: _markingAll
                  ? const SizedBox(
                      width: 16,
                      height: 16,
                      child: CircularProgressIndicator(strokeWidth: 2),
                    )
                  : const Text(
                      '全部已读',
                      style: TextStyle(
                        fontSize: 15,
                        fontWeight: FontWeight.w700,
                      ),
                    ),
            ),
          IconButton(
            tooltip: '通知设置',
            icon: const Icon(Icons.settings_outlined),
            onPressed: () => pushRoute(ref, 'notificationPrefs'),
          ),
          const SizedBox(width: 4),
        ],
      ),
      body: RefreshIndicator(
        onRefresh: _load,
        color: AppColors.primary,
        child: _buildBody(items, unread),
      ),
    );
  }

  Widget _buildBody(List<InAppNotification> items, int unread) {
    if (_loading) return const Center(child: CircularProgressIndicator());
    if (_error != null) {
      return _MessageState(
        icon: LucideIcons.wifiOff,
        title: '通知加载失败',
        message: '请检查网络连接后重试',
        buttonText: '重新加载',
        onPressed: _load,
      );
    }
    if (items.isEmpty) {
      return const _MessageState(
        icon: LucideIcons.bellOff,
        title: '暂时没有通知',
        message: '用药、运动、健康指标和报告消息会显示在这里',
      );
    }

    final today = <InAppNotification>[];
    final earlier = <InAppNotification>[];
    final now = DateTime.now();
    for (final item in items) {
      final local = item.createdAt.toLocal();
      final isToday =
          local.year == now.year &&
          local.month == now.month &&
          local.day == now.day;
      (isToday ? today : earlier).add(item);
    }

    return ListView(
      physics: const AlwaysScrollableScrollPhysics(),
      padding: const EdgeInsets.fromLTRB(16, 14, 16, 32),
      children: [
        if (unread > 0) _UnreadHint(unreadCount: unread),
        if (today.isNotEmpty) ...[
          const _SectionTitle('今天'),
          const SizedBox(height: 10),
          _NotificationGroup(
            children: [
              for (var i = 0; i < today.length; i++)
                _buildDismissible(today[i], showDivider: i < today.length - 1),
            ],
          ),
        ],
        if (earlier.isNotEmpty) ...[
          if (today.isNotEmpty) const SizedBox(height: 18),
          _CollapsibleSectionTitle(
            text: '更早',
            count: earlier.length,
            expanded: _showEarlier,
            onTap: () => setState(() => _showEarlier = !_showEarlier),
          ),
          const SizedBox(height: 10),
          if (_showEarlier)
            _NotificationGroup(
              children: [
                for (var i = 0; i < earlier.length; i++)
                  _buildDismissible(
                    earlier[i],
                    showDivider: i < earlier.length - 1,
                  ),
              ],
            ),
        ],
      ],
    );
  }

  Widget _buildDismissible(
    InAppNotification item, {
    required bool showDivider,
  }) => Dismissible(
    key: ValueKey(item.id),
    direction: DismissDirection.endToStart,
    background: Container(
      alignment: Alignment.centerRight,
      padding: const EdgeInsets.only(right: 26),
      color: AppColors.error,
      child: const Row(
        mainAxisSize: MainAxisSize.min,
        children: [
          Icon(LucideIcons.trash2, color: Colors.white, size: 22),
          SizedBox(width: 8),
          Text(
            '删除',
            style: TextStyle(
              color: Colors.white,
              fontSize: 15,
              fontWeight: FontWeight.w700,
            ),
          ),
        ],
      ),
    ),
    onDismissed: (_) => _delete(item),
    child: _NotificationRow(
      item: item,
      showDivider: showDivider,
      onTap: () => _open(item),
    ),
  );
}

class _NotificationGroup extends StatelessWidget {
  final List<Widget> children;

  const _NotificationGroup({required this.children});

  @override
  Widget build(BuildContext context) {
    return Container(
      clipBehavior: Clip.antiAlias,
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: AppRadius.xlBorder,
        boxShadow: [
          BoxShadow(
            color: const Color(0xFF101828).withValues(alpha: 0.035),
            blurRadius: 14,
            offset: const Offset(0, 6),
          ),
        ],
      ),
      child: Column(children: children),
    );
  }
}

class _UnreadHint extends StatelessWidget {
  final int unreadCount;

  const _UnreadHint({required this.unreadCount});

  @override
  Widget build(BuildContext context) => Container(
    margin: const EdgeInsets.fromLTRB(0, 2, 0, 14),
    padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 11),
    decoration: BoxDecoration(
      color: const Color(0xFFFFFBEB),
      borderRadius: AppRadius.mdBorder,
      border: Border.all(color: const Color(0xFFFDE68A)),
    ),
    child: Row(
      children: [
        const Icon(LucideIcons.bellRing, size: 18, color: Color(0xFFF97316)),
        const SizedBox(width: 9),
        Text(
          '你有 $unreadCount 条未读消息',
          style: const TextStyle(
            fontSize: 15,
            fontWeight: FontWeight.w800,
            color: Color(0xFF92400E),
          ),
        ),
      ],
    ),
  );
}

class _SectionTitle extends StatelessWidget {
  final String text;

  const _SectionTitle(this.text);

  @override
  Widget build(BuildContext context) => _SectionShell(
    child: Row(
      children: [
        const Icon(
          LucideIcons.calendarDays,
          size: 18,
          color: AppColors.primary,
        ),
        const SizedBox(width: 8),
        Text(
          text,
          style: const TextStyle(
            fontSize: 15,
            fontWeight: FontWeight.w900,
            color: AppColors.textPrimary,
          ),
        ),
      ],
    ),
  );
}

class _SectionShell extends StatelessWidget {
  final Widget child;

  const _SectionShell({required this.child});

  @override
  Widget build(BuildContext context) =>
      Padding(padding: const EdgeInsets.fromLTRB(2, 12, 2, 8), child: child);
}

class _CollapsibleSectionTitle extends StatelessWidget {
  final String text;
  final int count;
  final bool expanded;
  final VoidCallback onTap;

  const _CollapsibleSectionTitle({
    required this.text,
    required this.count,
    required this.expanded,
    required this.onTap,
  });

  @override
  Widget build(BuildContext context) => GestureDetector(
    behavior: HitTestBehavior.opaque,
    onTap: onTap,
    child: _SectionShell(
      child: Row(
        children: [
          const Icon(
            LucideIcons.history,
            size: 18,
            color: AppColors.textSecondary,
          ),
          const SizedBox(width: 8),
          Text(
            '$text · $count',
            style: const TextStyle(
              fontSize: 15,
              fontWeight: FontWeight.w900,
              color: AppColors.textPrimary,
            ),
          ),
          const Spacer(),
          Text(
            expanded ? '收起' : '展开',
            style: const TextStyle(
              fontSize: 13,
              fontWeight: FontWeight.w800,
              color: AppColors.textSecondary,
            ),
          ),
          const SizedBox(width: 8),
          Icon(
            expanded ? Icons.keyboard_arrow_up : Icons.keyboard_arrow_down,
            size: 22,
            color: AppColors.textSecondary,
          ),
        ],
      ),
    ),
  );
}

class _NotificationRow extends StatelessWidget {
  final InAppNotification item;
  final bool showDivider;
  final VoidCallback onTap;

  const _NotificationRow({
    required this.item,
    required this.showDivider,
    required this.onTap,
  });

  @override
  Widget build(BuildContext context) {
    final visual = _NotificationVisual.of(item);
    return Material(
      color: Colors.white,
      child: InkWell(
        onTap: onTap,
        child: Container(
          constraints: const BoxConstraints(minHeight: 94),
          color: Colors.white,
          child: Column(
            children: [
              Padding(
                padding: const EdgeInsets.fromLTRB(14, 13, 12, 12),
                child: Row(
                  children: [
                    Stack(
                      clipBehavior: Clip.none,
                      children: [
                        Container(
                          width: 48,
                          height: 48,
                          decoration: BoxDecoration(
                            gradient: LinearGradient(
                              begin: Alignment.topLeft,
                              end: Alignment.bottomRight,
                              colors: [
                                visual.color.withValues(alpha: 0.18),
                                visual.lightColor,
                              ],
                            ),
                            borderRadius: AppRadius.mdBorder,
                            border: Border.all(
                              color: visual.color.withValues(alpha: 0.22),
                            ),
                          ),
                          child: Icon(
                            visual.icon,
                            size: 24,
                            color: visual.color,
                          ),
                        ),
                        if (!item.isRead)
                          Positioned(
                            top: -2,
                            right: -2,
                            child: Container(
                              width: 10,
                              height: 10,
                              decoration: BoxDecoration(
                                color: AppColors.error,
                                shape: BoxShape.circle,
                                border: Border.all(
                                  color: Colors.white,
                                  width: 1.5,
                                ),
                              ),
                            ),
                          ),
                      ],
                    ),
                    const SizedBox(width: 13),
                    Expanded(
                      child: Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        mainAxisAlignment: MainAxisAlignment.center,
                        children: [
                          Row(
                            children: [
                              Container(
                                padding: const EdgeInsets.symmetric(
                                  horizontal: 7,
                                  vertical: 3,
                                ),
                                decoration: BoxDecoration(
                                  color: visual.lightColor,
                                  borderRadius: AppRadius.pillBorder,
                                ),
                                child: Text(
                                  visual.label,
                                  style: TextStyle(
                                    fontSize: 12,
                                    fontWeight: FontWeight.w800,
                                    color: visual.color,
                                  ),
                                ),
                              ),
                              const SizedBox(width: 8),
                              Text(
                                _formatTime(item.createdAt),
                                style: const TextStyle(
                                  fontSize: 12,
                                  fontWeight: FontWeight.w700,
                                  color: AppColors.textHint,
                                ),
                              ),
                            ],
                          ),
                          const SizedBox(height: 5),
                          Text(
                            item.title,
                            maxLines: 1,
                            overflow: TextOverflow.ellipsis,
                            style: TextStyle(
                              fontSize: 16,
                              fontWeight: item.isRead
                                  ? FontWeight.w700
                                  : FontWeight.w800,
                              color: AppColors.textPrimary,
                              height: 1.2,
                            ),
                          ),
                          const SizedBox(height: 4),
                          Text(
                            item.message,
                            maxLines: 1,
                            overflow: TextOverflow.ellipsis,
                            style: const TextStyle(
                              fontSize: 14,
                              height: 1.25,
                              fontWeight: FontWeight.w500,
                              color: AppColors.textSecondary,
                            ),
                          ),
                        ],
                      ),
                    ),
                    if (item.actionType != null) ...[
                      const SizedBox(width: 6),
                      const Icon(
                        Icons.chevron_right_rounded,
                        size: 22,
                        color: AppColors.textSecondary,
                      ),
                    ],
                  ],
                ),
              ),
              if (showDivider)
                const Padding(
                  padding: EdgeInsets.only(left: 75),
                  child: Divider(
                    height: 1,
                    thickness: 0.7,
                    color: Color(0xFFE8ECF2),
                  ),
                ),
            ],
          ),
        ),
      ),
    );
  }

  static String _formatTime(DateTime value) {
    final local = value.toLocal();
    final now = DateTime.now();
    final time =
        '${local.hour.toString().padLeft(2, '0')}:'
        '${local.minute.toString().padLeft(2, '0')}';
    if (local.year == now.year &&
        local.month == now.month &&
        local.day == now.day) {
      return time;
    }
    if (local.year == now.year) return '${local.month}/${local.day} $time';
    return '${local.year}/${local.month}/${local.day} $time';
  }
}

class _NotificationVisual {
  final IconData icon;
  final Color color;
  final Color lightColor;
  final String label;

  const _NotificationVisual(this.icon, this.color, this.lightColor, this.label);

  factory _NotificationVisual.fromModule(AppModuleVisual visual) {
    return _NotificationVisual(
      visual.icon,
      visual.color,
      visual.lightColor,
      visual.label,
    );
  }

  factory _NotificationVisual.of(InAppNotification item) {
    switch (item.actionType) {
      case 'exercise':
        return _NotificationVisual.fromModule(AppModuleVisuals.exercise);
      case 'health':
        return item.severity == 'critical'
            ? const _NotificationVisual(
                LucideIcons.triangleAlert,
                Color(0xFFEF4444),
                Color(0xFFFEE2E2),
                '紧急',
              )
            : _NotificationVisual.fromModule(AppModuleVisuals.health);
      case 'report':
        return item.severity == 'error'
            ? const _NotificationVisual(
                LucideIcons.fileWarning,
                Color(0xFFEF4444),
                Color(0xFFFEE2E2),
                '报告',
              )
            : _NotificationVisual.fromModule(AppModuleVisuals.report);
      default:
        return _NotificationVisual.fromModule(AppModuleVisuals.medication);
    }
  }
}

class _MessageState extends StatelessWidget {
  final IconData icon;
  final String title;
  final String message;
  final String? buttonText;
  final VoidCallback? onPressed;

  const _MessageState({
    required this.icon,
    required this.title,
    required this.message,
    this.buttonText,
    this.onPressed,
  });

  @override
  Widget build(BuildContext context) => ListView(
    physics: const AlwaysScrollableScrollPhysics(),
    padding: const EdgeInsets.fromLTRB(28, 120, 28, 32),
    children: [
      Container(
        padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 36),
        decoration: BoxDecoration(
          color: Colors.white,
          borderRadius: BorderRadius.circular(16),
          border: Border.all(color: AppColors.borderLight),
          boxShadow: [AppTheme.shadowLight],
        ),
        child: Column(
          children: [
            Container(
              width: 72,
              height: 72,
              decoration: BoxDecoration(
                color: AppColors.primaryLight,
                borderRadius: BorderRadius.circular(18),
              ),
              child: Icon(icon, size: 32, color: AppColors.primary),
            ),
            const SizedBox(height: 20),
            Text(
              title,
              style: const TextStyle(
                fontSize: 18,
                fontWeight: FontWeight.w800,
                color: AppColors.textPrimary,
              ),
            ),
            const SizedBox(height: 8),
            Text(
              message,
              textAlign: TextAlign.center,
              style: const TextStyle(
                fontSize: 14,
                height: 1.5,
                color: AppColors.textSecondary,
              ),
            ),
            if (buttonText != null) ...[
              const SizedBox(height: 22),
              FilledButton(
                onPressed: onPressed,
                style: FilledButton.styleFrom(
                  backgroundColor: AppColors.primary,
                  padding: const EdgeInsets.symmetric(
                    horizontal: 28,
                    vertical: 12,
                  ),
                ),
                child: Text(buttonText!),
              ),
            ],
          ],
        ),
      ),
    ],
  );
}
