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

import '../../core/api_client.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/auth_provider.dart';
import '../../providers/data_providers.dart';
import '../../widgets/app_empty_state.dart';
import '../../widgets/app_error_state.dart';
import '../../widgets/app_toast.dart';

class MedicationCheckInPage extends ConsumerStatefulWidget {
  final String? medId;

  const MedicationCheckInPage({super.key, this.medId});

  @override
  ConsumerState<MedicationCheckInPage> createState() =>
      _MedicationCheckInPageState();
}

class _MedicationCheckInPageState extends ConsumerState<MedicationCheckInPage> {
  Future<List<Map<String, dynamic>>>? _future;
  final Set<String> _busyDoses = {};

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

  void _load() => setState(() {
    _future = ref.read(medicationReminderProvider.future);
  });

  Future<void> _refresh() async {
    ref.invalidate(medicationReminderProvider);
    _load();
    await _future;
  }

  Future<void> _toggleDose(String medId, String time, bool taken) async {
    final doseKey = '$medId-$time';
    if (medId.isEmpty || time.isEmpty || _busyDoses.contains(doseKey)) return;
    setState(() => _busyDoses.add(doseKey));
    try {
      final api = ref.read(apiClientProvider);
      if (taken) {
        await api.delete('/api/medications/$medId/confirm-dose/$time');
      } else {
        final response = await api.post(
          '/api/medications/$medId/confirm-dose',
          data: {'scheduledTime': time, 'status': 'taken'},
        );
        final data = response.data is Map ? response.data['data'] : null;
        if (data is Map && data['success'] == false) {
          throw const ApiException('该次服药已经打卡');
        }
      }
      ref.invalidate(medicationReminderProvider);
      ref.invalidate(medicationListProvider);
      _load();
    } catch (error) {
      if (mounted) {
        AppToast.show(
          context,
          error is ApiException ? error.message : '打卡失败，请稍后重试',
          type: AppToastType.error,
        );
      }
    } finally {
      if (mounted) setState(() => _busyDoses.remove(doseKey));
    }
  }

  @override
  Widget build(BuildContext context) {
    return GradientScaffold(
      appBar: AppBar(
        leading: IconButton(
          icon: const Icon(Icons.arrow_back),
          onPressed: () => popRoute(ref),
        ),
        title: const Text('服药打卡'),
      ),
      body: FutureBuilder<List<Map<String, dynamic>>>(
        future: _future,
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.waiting &&
              !snapshot.hasData) {
            return const Center(child: CircularProgressIndicator());
          }
          if (snapshot.hasError) {
            return AppErrorState(title: '用药信息加载失败', onRetry: _load);
          }
          final reminders = _filterReminders(snapshot.data ?? const []);
          if (reminders.isEmpty) {
            return RefreshIndicator(
              onRefresh: _refresh,
              child: ListView(
                physics: const AlwaysScrollableScrollPhysics(),
                children: [
                  const SizedBox(height: 92),
                  AppEmptyState(
                    icon: AppModuleVisuals.medication.icon,
                    title: '今天没有服药安排',
                    subtitle: '今日可以安心休息，下拉可刷新最新计划',
                    iconColor: AppColors.medication,
                  ),
                ],
              ),
            );
          }
          final sorted = [...reminders]
            ..sort(
              (a, b) => _formatTime(
                a['scheduledTime']?.toString() ?? '',
              ).compareTo(_formatTime(b['scheduledTime']?.toString() ?? '')),
            );
          final taken = sorted.where(_isTaken).length;
          return RefreshIndicator(
            onRefresh: _refresh,
            child: ListView(
              physics: const AlwaysScrollableScrollPhysics(),
              padding: AppSpacing.page,
              children: [
                _DoseProgressHeader(total: sorted.length, taken: taken),
                const SizedBox(height: 18),
                Container(
                  clipBehavior: Clip.antiAlias,
                  decoration: BoxDecoration(
                    color: Colors.white,
                    borderRadius: AppRadius.lgBorder,
                  ),
                  child: Column(
                    children: List.generate(sorted.length, (index) {
                      final dose = sorted[index];
                      final key =
                          '${dose['id']?.toString() ?? ''}-${dose['scheduledTime']?.toString() ?? ''}';
                      return _DoseTimelineRow(
                        dose: dose,
                        isFirst: index == 0,
                        isLast: index == sorted.length - 1,
                        isBusy: _busyDoses.contains(key),
                        onToggle: _toggleDose,
                      );
                    }),
                  ),
                ),
                const SizedBox(height: 18),
                const Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    Icon(
                      LucideIcons.shield,
                      size: 16,
                      color: AppColors.textHint,
                    ),
                    SizedBox(width: 6),
                    Text(
                      '请按医嘱服药，如有不适及时咨询医生',
                      style: TextStyle(fontSize: 12, color: AppColors.textHint),
                    ),
                  ],
                ),
              ],
            ),
          );
        },
      ),
    );
  }

  List<Map<String, dynamic>> _filterReminders(
    List<Map<String, dynamic>> reminders,
  ) {
    if (widget.medId == null || widget.medId!.isEmpty) return reminders;
    return reminders
        .where((item) => item['id']?.toString() == widget.medId)
        .toList();
  }
}

Map<String, List<Map<String, dynamic>>> groupMedicationReminders(
  List<Map<String, dynamic>> reminders,
) {
  final grouped = <String, List<Map<String, dynamic>>>{};
  for (var index = 0; index < reminders.length; index++) {
    final reminder = reminders[index];
    final medicationId = reminder['id']?.toString().trim();
    final key = medicationId?.isNotEmpty == true
        ? medicationId!
        : 'unknown-$index';
    grouped.putIfAbsent(key, () => <Map<String, dynamic>>[]).add(reminder);
  }
  for (final doses in grouped.values) {
    doses.sort(
      (a, b) => _formatTime(
        a['scheduledTime']?.toString() ?? '',
      ).compareTo(_formatTime(b['scheduledTime']?.toString() ?? '')),
    );
  }
  return grouped;
}

class _DoseProgressHeader extends StatelessWidget {
  final int total;
  final int taken;

  const _DoseProgressHeader({required this.total, required this.taken});

  @override
  Widget build(BuildContext context) {
    final now = DateTime.now();
    final progress = total == 0 ? 0.0 : taken / total;
    return Container(
      padding: const EdgeInsets.fromLTRB(16, 16, 16, 15),
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: AppRadius.lgBorder,
      ),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Row(
            children: [
              Expanded(
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(
                      '${now.month}月${now.day}日 · 今日用药',
                      style: AppTextStyles.sectionTitle,
                    ),
                    const SizedBox(height: 3),
                    Text(
                      '$taken / $total 已完成',
                      style: AppTextStyles.listSubtitle,
                    ),
                  ],
                ),
              ),
              Text(
                '${(progress * 100).round()}%',
                style: AppTextStyles.summaryTitle.copyWith(
                  color: AppColors.medication,
                ),
              ),
            ],
          ),
          const SizedBox(height: 12),
          ClipRRect(
            borderRadius: AppRadius.pillBorder,
            child: LinearProgressIndicator(
              minHeight: 5,
              value: progress,
              backgroundColor: AppColors.cardInner,
              valueColor: const AlwaysStoppedAnimation(AppColors.medication),
            ),
          ),
        ],
      ),
    );
  }
}

class _DoseTimelineRow extends StatelessWidget {
  final Map<String, dynamic> dose;
  final bool isFirst;
  final bool isLast;
  final bool isBusy;
  final Future<void> Function(String, String, bool) onToggle;

  const _DoseTimelineRow({
    required this.dose,
    required this.isFirst,
    required this.isLast,
    required this.isBusy,
    required this.onToggle,
  });

  @override
  Widget build(BuildContext context) {
    final medId = dose['id']?.toString() ?? '';
    final rawTime = dose['scheduledTime']?.toString() ?? '';
    final time = _formatTime(rawTime);
    final name = dose['name']?.toString().trim().isNotEmpty == true
        ? dose['name'].toString().trim()
        : '未命名药品';
    final dosage = dose['dosage']?.toString().trim() ?? '';
    final status = dose['status']?.toString().toLowerCase() ?? 'scheduled';
    final taken = status == 'taken';
    final scheduled = status == 'scheduled';
    final color = _statusColor(status);

    return ConstrainedBox(
      constraints: const BoxConstraints(minHeight: 92),
      child: Stack(
        children: [
          Padding(
            padding: const EdgeInsets.symmetric(horizontal: 14),
            child: Row(
              children: [
                SizedBox(
                  width: 54,
                  child: Text(
                    time,
                    style: AppTextStyles.listTitle.copyWith(fontSize: 18),
                  ),
                ),
                SizedBox(
                  width: 28,
                  height: 92,
                  child: Stack(
                    alignment: Alignment.center,
                    children: [
                      if (!isFirst)
                        Positioned(
                          top: 0,
                          bottom: 46,
                          child: Container(width: 2, color: AppColors.divider),
                        ),
                      if (!isLast)
                        Positioned(
                          top: 46,
                          bottom: 0,
                          child: Container(width: 2, color: AppColors.divider),
                        ),
                      Container(
                        width: 20,
                        height: 20,
                        decoration: BoxDecoration(
                          color: taken ? color : Colors.white,
                          shape: BoxShape.circle,
                          border: Border.all(color: color, width: 2),
                        ),
                        child: taken
                            ? const Icon(
                                Icons.check,
                                size: 13,
                                color: Colors.white,
                              )
                            : null,
                      ),
                    ],
                  ),
                ),
                const SizedBox(width: 10),
                Expanded(
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      Text(
                        name,
                        maxLines: 1,
                        overflow: TextOverflow.ellipsis,
                        style: AppTextStyles.listTitle.copyWith(fontSize: 16),
                      ),
                      const SizedBox(height: 3),
                      Text(
                        [
                          dosage,
                          _statusLabel(status),
                        ].where((text) => text.isNotEmpty).join(' · '),
                        style: AppTextStyles.listSubtitle.copyWith(
                          fontSize: 13,
                          color: color,
                        ),
                      ),
                    ],
                  ),
                ),
                const SizedBox(width: 8),
                SizedBox(
                  height: 36,
                  child: OutlinedButton(
                    onPressed: isBusy || scheduled
                        ? null
                        : () => onToggle(medId, rawTime, taken),
                    style: OutlinedButton.styleFrom(
                      padding: const EdgeInsets.symmetric(horizontal: 13),
                      backgroundColor: taken
                          ? AppColors.successLight
                          : Colors.white,
                      foregroundColor: taken
                          ? AppColors.successText
                          : AppColors.medication,
                      disabledForegroundColor: AppColors.textHint,
                      side: BorderSide(
                        color: scheduled
                            ? AppColors.borderLight
                            : (taken
                                  ? AppColors.successText
                                  : AppColors.medication),
                      ),
                      shape: RoundedRectangleBorder(
                        borderRadius: AppRadius.smBorder,
                      ),
                    ),
                    child: isBusy
                        ? const SizedBox(
                            width: 14,
                            height: 14,
                            child: CircularProgressIndicator(strokeWidth: 2),
                          )
                        : Text(
                            scheduled ? '未到时间' : (taken ? '撤销' : '打卡'),
                            style: AppTextStyles.miniButton,
                          ),
                  ),
                ),
              ],
            ),
          ),
          if (!isLast)
            const Positioned(
              left: 96,
              right: 0,
              bottom: 0,
              child: Divider(
                height: 1,
                thickness: 0.7,
                color: AppColors.divider,
              ),
            ),
        ],
      ),
    );
  }
}

bool _isTaken(Map<String, dynamic> dose) =>
    dose['status']?.toString().toLowerCase() == 'taken';

String _formatTime(String raw) {
  final value = raw.trim();
  return value.length >= 5 ? value.substring(0, 5) : value;
}

String _statusLabel(String status) => switch (status) {
  'taken' => '已完成',
  'overdue' => '已超时',
  'upcoming' => '待完成',
  'skipped' => '已跳过',
  _ => '未到时间',
};

Color _statusColor(String status) => switch (status) {
  'taken' => AppColors.successText,
  'overdue' => AppColors.errorText,
  'upcoming' => AppColors.blueMeasure,
  'skipped' => AppColors.textHint,
  _ => AppColors.textHint,
};
