import 'dart:convert';
import 'dart:async';
import 'dart:io';
import 'package:dio/dio.dart';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:image_picker/image_picker.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/api_client.dart' show ApiException, baseUrl;
import '../../core/navigation_provider.dart';
import '../../providers/auth_provider.dart';
import '../../widgets/common_widgets.dart';
import '../../widgets/enterprise_widgets.dart';
import '../../widgets/app_error_state.dart';
import '../../widgets/app_empty_state.dart';
import '../../widgets/app_toast.dart';

const _reportPageColor = AppColors.report;
const _reportPageSoft = Color(0xFFF0F0FF);

final reportProvider = NotifierProvider<ReportNotifier, ReportState>(
  ReportNotifier.new,
);

Duration? reportAnalysisPollDelay(int attempt) {
  if (attempt > 15) return null;
  if (attempt <= 2) return const Duration(seconds: 4);
  if (attempt <= 5) return const Duration(seconds: 8);
  return const Duration(seconds: 12);
}

bool isPdfReport(String fileType, String url) {
  return fileType.toLowerCase() == 'pdf' ||
      Uri.tryParse(url)?.path.toLowerCase().endsWith('.pdf') == true;
}

class ReportState {
  final List<ReportItem> reports;
  final String? uploadingImage;
  final bool isAnalyzing;
  final ReportAnalysis? currentAnalysis;
  final String? uploadError;
  final bool isLoadingReports;
  final bool isRefreshingReports;
  final String? reportsError;
  final String? deletingReportId;
  final bool isLoadingDetail;
  final String? detailError;
  final String? reanalyzingReportId;
  final bool pollingTimedOut;

  ReportState({
    this.reports = const [],
    this.uploadingImage,
    this.isAnalyzing = false,
    this.currentAnalysis,
    this.uploadError,
    this.isLoadingReports = true,
    this.isRefreshingReports = false,
    this.reportsError,
    this.deletingReportId,
    this.isLoadingDetail = false,
    this.detailError,
    this.reanalyzingReportId,
    this.pollingTimedOut = false,
  });

  ReportState copyWith({
    List<ReportItem>? reports,
    String? uploadingImage,
    bool? isAnalyzing,
    ReportAnalysis? currentAnalysis,
    String? uploadError,
    bool? isLoadingReports,
    bool? isRefreshingReports,
    String? reportsError,
    String? deletingReportId,
    bool? isLoadingDetail,
    String? detailError,
    String? reanalyzingReportId,
    bool? pollingTimedOut,
    bool clearUploadingImage = false,
    bool clearCurrentAnalysis = false,
    bool clearUploadError = false,
    bool clearReportsError = false,
    bool clearDeletingReportId = false,
    bool clearDetailError = false,
    bool clearReanalyzingReportId = false,
  }) {
    return ReportState(
      reports: reports ?? this.reports,
      uploadingImage: clearUploadingImage
          ? null
          : uploadingImage ?? this.uploadingImage,
      isAnalyzing: isAnalyzing ?? this.isAnalyzing,
      currentAnalysis: clearCurrentAnalysis
          ? null
          : currentAnalysis ?? this.currentAnalysis,
      uploadError: clearUploadError ? null : uploadError ?? this.uploadError,
      isLoadingReports: isLoadingReports ?? this.isLoadingReports,
      isRefreshingReports: isRefreshingReports ?? this.isRefreshingReports,
      reportsError: clearReportsError
          ? null
          : reportsError ?? this.reportsError,
      deletingReportId: clearDeletingReportId
          ? null
          : deletingReportId ?? this.deletingReportId,
      isLoadingDetail: isLoadingDetail ?? this.isLoadingDetail,
      detailError: clearDetailError ? null : detailError ?? this.detailError,
      reanalyzingReportId: clearReanalyzingReportId
          ? null
          : reanalyzingReportId ?? this.reanalyzingReportId,
      pollingTimedOut: pollingTimedOut ?? this.pollingTimedOut,
    );
  }
}

class ReportItem {
  final String id;
  final String title;
  final String type;
  final DateTime uploadedAt;
  final String? fileUrl;
  final bool hasAnalysis;
  final String status; // Legacy combined status from backend.
  final String aiStatus; // Analyzing | Succeeded | Failed
  final String reviewStatus; // Pending | Reviewed
  final String? analysisSummary;
  final String? severity; // Normal | Abnormal | Severe | Critical
  final String? doctorComment;
  final String? doctorRecommendation;
  final String? doctorName;
  final DateTime? reviewedAt;

  ReportItem({
    required this.id,
    required this.title,
    required this.type,
    required this.uploadedAt,
    this.fileUrl,
    this.hasAnalysis = false,
    this.status = 'PendingDoctor',
    this.aiStatus = 'Analyzing',
    this.reviewStatus = 'Pending',
    this.analysisSummary,
    this.severity,
    this.doctorComment,
    this.doctorRecommendation,
    this.doctorName,
    this.reviewedAt,
  });
}

class ReportAnalysis {
  final String reportId;
  final String reportType;
  final List<Indicator> indicators;
  final String summary;
  final String status;
  final String aiStatus;
  final String reviewStatus;
  final String? fileUrl;
  final String fileType;

  ReportAnalysis({
    required this.reportId,
    required this.reportType,
    required this.indicators,
    required this.summary,
    this.status = 'PendingDoctor',
    this.aiStatus = 'Analyzing',
    this.reviewStatus = 'Pending',
    this.fileUrl,
    this.fileType = 'Image',
  });
}

class Indicator {
  final String name;
  final String value;
  final String unit;
  final String status;
  final String? referenceRange;

  Indicator({
    required this.name,
    required this.value,
    required this.unit,
    required this.status,
    this.referenceRange,
  });
}

class ReportNotifier extends Notifier<ReportState> {
  Timer? _pollTimer;
  int _pollAttempt = 0;

  @override
  ReportState build() {
    ref.onDispose(() => _pollTimer?.cancel());
    Future.microtask(() => loadReports());
    return ReportState();
  }

  Future<void> loadReports({bool refresh = false}) async {
    if (refresh) {
      _pollTimer?.cancel();
      _pollTimer = null;
      _pollAttempt = 0;
    }
    final initialLoad = state.reports.isEmpty && !refresh;
    state = state.copyWith(
      isLoadingReports: initialLoad,
      isRefreshingReports: !initialLoad,
      clearReportsError: true,
      pollingTimedOut: refresh ? false : state.pollingTimedOut,
    );
    try {
      final api = ref.read(apiClientProvider);
      final res = await api.get('/api/reports');
      final list = (res.data['data'] as List?) ?? [];
      final reports = list.map((r) {
        final m = r as Map<String, dynamic>;
        final rawTitle = m['title']?.toString() ?? '';
        final rawCat = m['category']?.toString() ?? '';
        final title =
            rawTitle.isNotEmpty && rawTitle != 'Other' && rawTitle != 'other'
            ? rawTitle
            : _catTitle(rawCat);
        return ReportItem(
          id: m['id']?.toString() ?? '',
          title: title,
          type: m['fileType']?.toString() ?? 'Image',
          uploadedAt:
              DateTime.tryParse(m['createdAt']?.toString() ?? '') ??
              DateTime.now(),
          fileUrl: m['fileUrl']?.toString(),
          hasAnalysis: m['aiSummary'] != null,
          status: m['status']?.toString() ?? 'PendingDoctor',
          aiStatus: m['aiStatus']?.toString() ?? _deriveAiStatus(m),
          reviewStatus: m['reviewStatus']?.toString() ?? _deriveReviewStatus(m),
          analysisSummary: m['aiSummary']?.toString(),
          severity: m['severity']?.toString(),
          doctorComment: m['doctorComment']?.toString(),
          doctorRecommendation: m['doctorRecommendation']?.toString(),
          doctorName: m['doctorName']?.toString(),
          reviewedAt: DateTime.tryParse(m['reviewedAt']?.toString() ?? ''),
        );
      }).toList();
      state = state.copyWith(
        reports: reports,
        isLoadingReports: false,
        isRefreshingReports: false,
        clearReportsError: true,
      );
      _syncAnalysisPolling(reports);
    } catch (e) {
      debugPrint('[Report] 加载报告列表失败: $e');
      state = state.copyWith(
        isLoadingReports: false,
        isRefreshingReports: false,
        reportsError: _errorMessage(e, '报告加载失败，请检查网络后重试'),
      );
    }
  }

  void _syncAnalysisPolling(List<ReportItem> reports) {
    final hasAnalyzing = reports.any((r) => r.aiStatus == 'Analyzing');
    if (!hasAnalyzing) {
      _pollTimer?.cancel();
      _pollTimer = null;
      _pollAttempt = 0;
      if (state.pollingTimedOut) {
        state = state.copyWith(pollingTimedOut: false);
      }
      return;
    }
    if (_pollTimer != null) return;
    final delay = reportAnalysisPollDelay(++_pollAttempt);
    if (delay == null) {
      if (!state.pollingTimedOut) {
        state = state.copyWith(pollingTimedOut: true);
      }
      return;
    }
    _pollTimer = Timer(delay, () {
      _pollTimer = null;
      loadReports();
    });
  }

  Future<void> fetchReportDetail(String reportId) async {
    state = state.copyWith(
      isLoadingDetail: true,
      clearCurrentAnalysis: true,
      clearDetailError: true,
    );
    try {
      final api = ref.read(apiClientProvider);
      final res = await api.get('/api/reports/$reportId');
      final m = (res.data['data'] as Map<String, dynamic>?) ?? {};
      if (m.isEmpty) {
        state = state.copyWith(
          isLoadingDetail: false,
          detailError: '没有找到这份报告，请返回后刷新列表',
        );
        return;
      }
      final indicators = _parseIndicators(m['aiIndicators']?.toString());
      final rawTitle = m['title']?.toString() ?? '';
      final rawCat = m['category']?.toString() ?? '';
      final displayType = rawTitle.isNotEmpty && rawTitle != 'Other'
          ? rawTitle
          : _catTitle(rawCat);
      final analysis = ReportAnalysis(
        reportId: m['id']?.toString() ?? reportId,
        reportType: displayType,
        indicators: indicators,
        summary: m['aiSummary']?.toString() ?? '',
        status: m['status']?.toString() ?? 'PendingDoctor',
        aiStatus: m['aiStatus']?.toString() ?? _deriveAiStatus(m),
        reviewStatus: m['reviewStatus']?.toString() ?? _deriveReviewStatus(m),
        fileUrl: m['fileUrl']?.toString(),
        fileType: m['fileType']?.toString() ?? 'Image',
      );
      state = state.copyWith(
        currentAnalysis: analysis,
        isLoadingDetail: false,
        clearDetailError: true,
      );
    } catch (e) {
      state = state.copyWith(
        isLoadingDetail: false,
        detailError: _errorMessage(e, '报告详情加载失败，请稍后重试'),
      );
    }
  }

  String _deriveAiStatus(Map<String, dynamic> m) {
    final status = m['status']?.toString();
    if (status == 'Analyzing') return 'Analyzing';
    if (status == 'AnalysisFailed') return 'Failed';
    return m['aiSummary'] != null ? 'Succeeded' : 'Analyzing';
  }

  String _deriveReviewStatus(Map<String, dynamic> m) =>
      m['status']?.toString() == 'DoctorReviewed' ? 'Reviewed' : 'Pending';

  List<Indicator> _parseIndicators(String? jsonStr) {
    if (jsonStr == null || jsonStr.isEmpty) return [];
    try {
      final list = jsonDecode(jsonStr) as List;
      return list.map((item) {
        final m = item as Map<String, dynamic>;
        return Indicator(
          name: m['name']?.toString() ?? '',
          value: m['value']?.toString() ?? '',
          unit: m['unit']?.toString() ?? '',
          status: m['status']?.toString() ?? 'normal',
          referenceRange: m['referenceRange']?.toString(),
        );
      }).toList();
    } catch (_) {
      return [];
    }
  }

  Future<void> uploadImage(String path) async {
    state = state.copyWith(
      uploadingImage: path,
      isAnalyzing: true,
      clearUploadError: true,
    );
    try {
      final api = ref.read(apiClientProvider);
      final file = File(path);
      final formData = FormData.fromMap({
        'file': await MultipartFile.fromFile(
          file.path,
          filename: file.path.split('/').last,
        ),
      });
      // 直接上传到报告端点，后端自动触发 VLM+LLM 分析
      final createRes = await api.dio.post('/api/reports', data: formData);
      final data = createRes.data;
      if (data is Map && data['code'] != 0) {
        final message = data['message']?.toString() ?? '上传失败，请稍后重试';
        state = state.copyWith(
          isAnalyzing: false,
          clearUploadingImage: true,
          uploadError: message,
        );
        return;
      }
      state = state.copyWith(
        isAnalyzing: false,
        clearUploadingImage: true,
        clearUploadError: true,
      );
      await loadReports();
    } catch (e) {
      debugPrint('[Report] 上传失败: $e');
      state = state.copyWith(
        isAnalyzing: false,
        clearUploadingImage: true,
        uploadError: '上传失败，请检查网络或文件格式后重试',
      );
    }
  }

  Future<void> uploadFile(String path) => uploadImage(path);

  void viewAnalysis(String reportId) {
    fetchReportDetail(reportId);
  }

  Future<void> deleteReport(String id) async {
    if (id.isEmpty || state.deletingReportId != null) return;
    state = state.copyWith(deletingReportId: id);
    try {
      await ref.read(apiClientProvider).delete('/api/reports/$id');
      final remaining = state.reports
          .where((report) => report.id != id)
          .toList();
      state = state.copyWith(reports: remaining, clearDeletingReportId: true);
      _syncAnalysisPolling(remaining);
    } catch (e) {
      debugPrint('[Report] 删除失败: $e');
      state = state.copyWith(clearDeletingReportId: true);
      throw Exception(_errorMessage(e, '删除失败，请稍后重试'));
    }
  }

  Future<void> reanalyzeReport(String id) async {
    if (state.reanalyzingReportId != null) return;
    state = state.copyWith(reanalyzingReportId: id, clearDetailError: true);
    try {
      final res = await ref
          .read(apiClientProvider)
          .post('/api/reports/$id/reanalyze');
      final data = res.data;
      if (data is Map && data['code'] != 0) {
        throw Exception(data['message']?.toString() ?? '重新分析失败');
      }
      state = state.copyWith(
        clearCurrentAnalysis: true,
        clearUploadError: true,
      );
      await loadReports();
      await fetchReportDetail(id);
    } catch (e) {
      debugPrint('[Report] 重新分析失败: $e');
      state = state.copyWith(detailError: _errorMessage(e, '重新分析失败，请稍后重试'));
    } finally {
      state = state.copyWith(clearReanalyzingReportId: true);
    }
  }

  void clearAnalysis() {
    state = state.copyWith(
      clearCurrentAnalysis: true,
      clearDetailError: true,
      isLoadingDetail: false,
    );
  }

  String _errorMessage(Object error, String fallback) {
    if (error is ApiException && error.message.trim().isNotEmpty) {
      return error.message;
    }
    final raw = error.toString().replaceFirst('Exception: ', '').trim();
    return raw.isEmpty ? fallback : raw;
  }
}

/// 报告列表页
class ReportListPage extends ConsumerStatefulWidget {
  final bool openUploadOnEnter;

  const ReportListPage({super.key, this.openUploadOnEnter = false});

  @override
  ConsumerState<ReportListPage> createState() => _ReportListPageState();
}

class _ReportListPageState extends ConsumerState<ReportListPage> {
  static const _reportVisual = AppModuleVisuals.report;
  static const _reportBlue = _reportPageColor;
  static const _reportAccent = _reportPageColor;

  @override
  void initState() {
    super.initState();
    if (widget.openUploadOnEnter) {
      WidgetsBinding.instance.addPostFrameCallback((_) {
        if (mounted) _showUploadOptions(context, ref);
      });
    }
  }

  Future<void> _confirmDelete(ReportItem report) async {
    if (ref.read(reportProvider).deletingReportId != null) return;
    final confirmed = await showDialog<bool>(
      context: context,
      builder: (dialogContext) => AlertDialog(
        title: const Text('删除报告'),
        content: Text('确定删除“${report.title}”吗？删除后无法恢复。'),
        actions: [
          TextButton(
            onPressed: () => Navigator.pop(dialogContext, false),
            child: const Text('取消'),
          ),
          TextButton(
            onPressed: () => Navigator.pop(dialogContext, true),
            style: TextButton.styleFrom(foregroundColor: AppColors.errorText),
            child: const Text('删除'),
          ),
        ],
      ),
    );
    if (confirmed != true || !mounted) return;
    try {
      await ref.read(reportProvider.notifier).deleteReport(report.id);
      if (mounted) {
        AppToast.show(context, '报告已删除', type: AppToastType.success);
      }
    } catch (error) {
      if (mounted) {
        AppToast.show(
          context,
          error.toString().replaceFirst('Exception: ', ''),
          type: AppToastType.error,
        );
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    final state = ref.watch(reportProvider);

    if (state.isLoadingReports && state.reports.isEmpty) {
      return GradientScaffold(
        appBar: AppBar(
          leading: IconButton(
            icon: const Icon(Icons.arrow_back),
            onPressed: () => popRoute(ref),
          ),
          title: const Text('报告管理'),
        ),
        body: const Center(
          child: CircularProgressIndicator(color: _reportBlue),
        ),
      );
    }

    if (state.reportsError != null && state.reports.isEmpty) {
      return GradientScaffold(
        appBar: AppBar(
          leading: IconButton(
            icon: const Icon(Icons.arrow_back),
            onPressed: () => popRoute(ref),
          ),
          title: const Text('报告管理'),
        ),
        body: AppErrorState(
          title: '报告加载失败',
          subtitle: state.reportsError,
          onRetry: () => ref.read(reportProvider.notifier).loadReports(),
        ),
      );
    }

    return GradientScaffold(
      appBar: AppBar(
        leading: IconButton(
          icon: const Icon(Icons.arrow_back),
          onPressed: () => popRoute(ref),
        ),
        title: const Text('报告管理'),
        centerTitle: true,
      ),
      floatingActionButton: _buildUploadButton(context, ref),
      body: RefreshIndicator(
        onRefresh: () =>
            ref.read(reportProvider.notifier).loadReports(refresh: true),
        child: ListView(
          padding: const EdgeInsets.all(16),
          children: [
            if (state.isRefreshingReports) ...[
              const LinearProgressIndicator(
                minHeight: 2,
                color: _reportBlue,
                backgroundColor: Colors.transparent,
              ),
              const SizedBox(height: 10),
            ],
            EnterpriseHeader(
              title: '报告处理概览',
              subtitle: '上传检查报告后自动进行 AI 结构化解读',
              icon: _reportVisual.icon,
              color: _reportBlue,
              accent: _reportAccent,
              showIcon: false,
              stats: [
                EnterpriseStat(
                  label: '报告总数',
                  value: '${state.reports.length} 份',
                ),
                EnterpriseStat(
                  label: 'AI 分析中',
                  value:
                      '${state.reports.where((r) => r.aiStatus == 'Analyzing').length} 份',
                ),
                EnterpriseStat(
                  label: '待医生审核',
                  value:
                      '${state.reports.where((r) => r.reviewStatus != 'Reviewed').length} 份',
                ),
              ],
            ),
            const SizedBox(height: 10),
            if (state.isAnalyzing) ...[
              _buildInfoBanner(
                state.uploadingImage == null ? '报告已上传，AI 正在分析' : '正在上传报告，请稍候',
                Icons.cloud_upload_outlined,
              ),
              const SizedBox(height: 12),
            ],
            if (state.pollingTimedOut) ...[
              _buildInfoBanner(
                '分析时间比预期更长，可稍后下拉刷新查看结果',
                Icons.schedule_outlined,
              ),
              const SizedBox(height: 12),
            ],
            if (state.reportsError != null) ...[
              _buildUploadError(state.reportsError!),
              const SizedBox(height: 12),
            ],
            if (state.uploadError != null) ...[
              _buildUploadError(state.uploadError!),
              const SizedBox(height: 12),
            ],
            if (state.reports.isEmpty)
              _buildEmptyState(context)
            else
              _ReportListGroup(
                children: [
                  for (var i = 0; i < state.reports.length; i++)
                    SwipeDeleteTile(
                      key: Key(state.reports[i].id),
                      onDelete: () => _confirmDelete(state.reports[i]),
                      onTap: () => pushRoute(
                        ref,
                        'aiAnalysis',
                        params: {'id': state.reports[i].id},
                      ),
                      margin: EdgeInsets.zero,
                      borderRadius: BorderRadius.zero,
                      enabled: state.deletingReportId == null,
                      child: _buildReportRow(
                        state.reports[i],
                        showDivider: i < state.reports.length - 1,
                        deleting: state.deletingReportId == state.reports[i].id,
                      ),
                    ),
                ],
              ),
          ],
        ),
      ),
    );
  }

  Widget _buildUploadError(String message) {
    return Container(
      padding: const EdgeInsets.all(12),
      decoration: BoxDecoration(
        color: AppColors.errorLight,
        borderRadius: AppRadius.mdBorder,
        border: Border.all(color: AppColors.errorText.withValues(alpha: 0.18)),
      ),
      child: Row(
        children: [
          const Icon(Icons.error_outline, color: AppColors.errorText, size: 20),
          const SizedBox(width: 8),
          Expanded(
            child: Text(
              message,
              style: const TextStyle(
                fontSize: 14,
                color: AppColors.errorText,
                fontWeight: FontWeight.w600,
              ),
            ),
          ),
        ],
      ),
    );
  }

  Widget _buildInfoBanner(String message, IconData icon) {
    return Container(
      padding: const EdgeInsets.all(12),
      decoration: BoxDecoration(
        color: _reportBlue.withValues(alpha: 0.07),
        borderRadius: AppRadius.mdBorder,
      ),
      child: Row(
        children: [
          Icon(icon, color: _reportBlue, size: 20),
          const SizedBox(width: 9),
          Expanded(
            child: Text(
              message,
              style: const TextStyle(
                fontSize: 14,
                color: AppColors.textPrimary,
                fontWeight: FontWeight.w600,
              ),
            ),
          ),
        ],
      ),
    );
  }

  Widget _buildUploadButton(BuildContext context, WidgetRef ref) {
    return AppCreateFab(
      tooltip: '上传健康报告',
      onPressed: () => _showUploadOptions(context, ref),
    );
  }

  void _showUploadOptions(BuildContext context, WidgetRef ref) {
    showModalBottomSheet(
      context: context,
      backgroundColor: Colors.white,
      showDragHandle: true,
      shape: const RoundedRectangleBorder(
        borderRadius: BorderRadius.vertical(top: Radius.circular(AppRadius.xl)),
      ),
      builder: (ctx) => SafeArea(
        top: false,
        child: Padding(
          padding: const EdgeInsets.fromLTRB(20, 2, 20, 20),
          child: Column(
            mainAxisSize: MainAxisSize.min,
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              const Text('上传健康报告', style: AppTextStyles.sectionTitle),
              const SizedBox(height: 10),
              _ReportUploadOption(
                icon: LucideIcons.camera,
                label: '拍照上传',
                onTap: () async {
                  Navigator.pop(ctx);
                  final picker = ImagePicker();
                  final picked = await picker.pickImage(
                    source: ImageSource.camera,
                    imageQuality: 85,
                  );
                  if (picked != null) {
                    ref.read(reportProvider.notifier).uploadImage(picked.path);
                  }
                },
              ),
              const Padding(
                padding: EdgeInsets.only(left: 50),
                child: Divider(height: 1, color: AppColors.divider),
              ),
              _ReportUploadOption(
                icon: LucideIcons.images,
                label: '从相册选择',
                onTap: () async {
                  Navigator.pop(ctx);
                  final picker = ImagePicker();
                  final picked = await picker.pickImage(
                    source: ImageSource.gallery,
                    imageQuality: 85,
                  );
                  if (picked != null) {
                    ref.read(reportProvider.notifier).uploadImage(picked.path);
                  }
                },
              ),
              const Padding(
                padding: EdgeInsets.only(left: 50),
                child: Divider(height: 1, color: AppColors.divider),
              ),
              _ReportUploadOption(
                icon: LucideIcons.fileText,
                label: '上传 PDF',
                onTap: () async {
                  Navigator.pop(ctx);
                  final result = await FilePicker.platform.pickFiles(
                    type: FileType.custom,
                    allowedExtensions: ['pdf'],
                    withData: false,
                  );
                  if (result == null || result.files.isEmpty) return;
                  final path = result.files.first.path;
                  if (path == null || path.isEmpty) return;
                  ref.read(reportProvider.notifier).uploadFile(path);
                },
              ),
            ],
          ),
        ),
      ),
    );
  }

  Widget _buildEmptyState(BuildContext context) {
    return AppEmptyState(
      icon: _reportVisual.icon,
      iconColor: _reportVisual.color,
      title: '暂无检查报告',
      subtitle: '点击右下角按钮上传报告',
    );
  }

  Widget _buildReportRow(
    ReportItem report, {
    required bool showDivider,
    required bool deleting,
  }) {
    final displayTitle = (report.title == 'Other' || report.title == 'other')
        ? '检查报告'
        : report.title;
    return Material(
      color: Colors.white,
      child: InkWell(
        child: Column(
          children: [
            Padding(
              padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 13),
              child: Row(
                children: [
                  Container(
                    width: 44,
                    height: 44,
                    decoration: BoxDecoration(
                      color: _reportBlue.withValues(alpha: 0.10),
                      borderRadius: AppRadius.mdBorder,
                    ),
                    child: Icon(
                      _reportVisual.icon,
                      size: 24,
                      color: _reportBlue,
                    ),
                  ),
                  const SizedBox(width: 13),
                  Expanded(
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        Text(
                          displayTitle,
                          maxLines: 1,
                          overflow: TextOverflow.ellipsis,
                          style: AppTextStyles.listTitle.copyWith(
                            fontWeight: FontWeight.w600,
                          ),
                        ),
                        const SizedBox(height: 3),
                        Text(
                          _formatDate(report.uploadedAt),
                          style: AppTextStyles.listSubtitle,
                        ),
                        const SizedBox(height: 6),
                        _buildStatusBadges(report),
                        if (report.aiStatus == 'Failed') ...[
                          const SizedBox(height: 4),
                          Text(
                            _failureSummary(report),
                            maxLines: 2,
                            overflow: TextOverflow.ellipsis,
                            style: const TextStyle(
                              fontSize: 13,
                              height: 1.35,
                              color: AppColors.errorText,
                              fontWeight: FontWeight.w600,
                            ),
                          ),
                        ],
                      ],
                    ),
                  ),
                  const SizedBox(width: 8),
                  if (deleting)
                    const SizedBox(
                      width: 20,
                      height: 20,
                      child: CircularProgressIndicator(strokeWidth: 2),
                    )
                  else
                    const Icon(
                      Icons.chevron_right,
                      size: 21,
                      color: AppColors.textHint,
                    ),
                ],
              ),
            ),
            if (showDivider)
              const Padding(
                padding: EdgeInsets.only(left: 71),
                child: Divider(
                  height: 1,
                  thickness: 0.7,
                  color: Color(0xFFE8ECF2),
                ),
              ),
          ],
        ),
      ),
    );
  }

  Widget _statusBadge(String label, Color bg, Color fg) {
    return Container(
      padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 3),
      decoration: BoxDecoration(
        color: bg,
        borderRadius: AppRadius.pillBorder,
        border: Border.all(color: fg.withValues(alpha: 0.12)),
      ),
      child: Text(
        label,
        style: TextStyle(fontSize: 13, color: fg, fontWeight: FontWeight.w700),
      ),
    );
  }

  Widget _buildStatusBadges(ReportItem report) {
    final aiBadge = switch (report.aiStatus) {
      'Succeeded' => _statusBadge(
        'AI 已分析',
        AppColors.successLight,
        AppColors.successText,
      ),
      'Failed' => _statusBadge(
        'AI 分析失败',
        AppColors.error.withValues(alpha: 0.08),
        AppColors.errorText,
      ),
      _ => _statusBadge(
        'AI 分析中',
        _reportBlue.withValues(alpha: 0.08),
        _reportBlue,
      ),
    };
    final reviewBadge = report.reviewStatus == 'Reviewed'
        ? _statusBadge('医生已审核', AppColors.successLight, AppColors.successText)
        : _statusBadge('待医生审核', AppColors.warningLight, AppColors.warningText);
    return Wrap(spacing: 6, runSpacing: 4, children: [aiBadge, reviewBadge]);
  }

  String _failureSummary(ReportItem report) {
    final summary = report.analysisSummary?.trim();
    if (summary != null && summary.isNotEmpty) {
      return summary;
    }
    return 'AI 暂时无法解读，请稍后重试或重新上传清晰图片';
  }

  String _formatDate(DateTime date) {
    final now = DateTime.now();
    final diff = now.difference(date);
    if (diff.inDays == 0) return '今天';
    if (diff.inDays == 1) return '昨天';
    if (diff.inDays < 7) return '${diff.inDays}天前';
    return '${date.month}月${date.day}日';
  }
}

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

  const _ReportListGroup({required this.children});

  @override
  Widget build(BuildContext context) {
    return Container(
      clipBehavior: Clip.antiAlias,
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: AppRadius.xlBorder,
      ),
      child: Column(children: children),
    );
  }
}

String _catTitle(String c) => switch (c) {
  'BloodTest' => '抽血化验单',
  'Biochemistry' => '生化检验报告',
  'Ecg' => '心电图报告',
  'Ultrasound' => '超声检查报告',
  'Discharge' => '出院小结',
  'Image' => '影像检查报告',
  _ => '检查报告',
};

class ReportOriginalPage extends ConsumerStatefulWidget {
  final String url;
  final String title;
  final String fileType;

  const ReportOriginalPage({
    super.key,
    required this.url,
    this.title = '原始报告',
    this.fileType = 'Image',
  });

  @override
  ConsumerState<ReportOriginalPage> createState() => _ReportOriginalPageState();
}

class _ReportOriginalPageState extends ConsumerState<ReportOriginalPage> {
  int _reloadToken = 0;

  @override
  Widget build(BuildContext context) {
    final rawUrl = widget.url.trim();
    final fileUrl = rawUrl.isEmpty ? null : _absoluteUrl(rawUrl);
    return GradientScaffold(
      appBar: AppBar(
        leading: IconButton(
          icon: const Icon(Icons.arrow_back),
          onPressed: () => popRoute(ref),
        ),
        title: Text(widget.title),
      ),
      body: fileUrl == null
          ? AppErrorState(title: '无法打开原始报告', subtitle: '报告文件地址为空，请返回后刷新列表')
          : isPdfReport(widget.fileType, fileUrl)
          ? _buildPdf(fileUrl)
          : _buildImage(fileUrl),
    );
  }

  Widget _buildImage(String imageUrl) {
    return Center(
      child: InteractiveViewer(
        minScale: 0.7,
        maxScale: 4,
        child: Image.network(
          imageUrl,
          key: ValueKey('$imageUrl-$_reloadToken'),
          fit: BoxFit.contain,
          loadingBuilder: (context, child, progress) {
            if (progress == null) return child;
            return const Center(
              child: CircularProgressIndicator(color: AppColors.report),
            );
          },
          errorBuilder: (_, _, _) => AppErrorState(
            title: '原始报告加载失败',
            subtitle: '请检查网络后重试',
            onRetry: () => setState(() => _reloadToken++),
          ),
        ),
      ),
    );
  }

  Widget _buildPdf(String _) {
    return AppEmptyState(
      icon: AppModuleVisuals.report.icon,
      iconColor: AppModuleVisuals.report.color,
      title: '暂不支持预览 PDF',
      subtitle: '当前版本优先支持图片报告，PDF 预览将在后续版本接入',
    );
  }

  String _absoluteUrl(String value) {
    if (value.startsWith('http://') || value.startsWith('https://')) {
      return value;
    }
    if (value.startsWith('/')) {
      return '$baseUrl$value';
    }
    return '$baseUrl/$value';
  }
}

class _ReportUploadOption extends StatelessWidget {
  final IconData icon;
  final String label;
  final VoidCallback onTap;

  const _ReportUploadOption({
    required this.icon,
    required this.label,
    required this.onTap,
  });

  @override
  Widget build(BuildContext context) {
    return InkWell(
      borderRadius: AppRadius.mdBorder,
      onTap: onTap,
      child: Padding(
        padding: const EdgeInsets.symmetric(vertical: 13),
        child: Row(
          children: [
            Container(
              width: 38,
              height: 38,
              decoration: BoxDecoration(
                color: _reportPageSoft,
                borderRadius: AppRadius.smBorder,
              ),
              child: Icon(icon, size: 20, color: _reportPageColor),
            ),
            const SizedBox(width: 12),
            Expanded(
              child: Text(
                label,
                style: const TextStyle(
                  fontSize: 16,
                  fontWeight: FontWeight.w700,
                  color: AppColors.textPrimary,
                ),
              ),
            ),
            const Icon(
              LucideIcons.chevronRight,
              size: 18,
              color: AppColors.textHint,
            ),
          ],
        ),
      ),
    );
  }
}
