// ignore_for_file: unused_import, unnecessary_import

import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'dart:math' as math;
import 'package:file_selector/file_selector.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_markdown/flutter_markdown.dart';
import 'package:markdown/markdown.dart' as md;
import 'package:path_provider/path_provider.dart';
import 'package:super_clipboard/super_clipboard.dart';
import '../../app/app_controller.dart';
import '../../app/app_metadata.dart';
import '../../app/ui_feature_manifest.dart';
import '../../i18n/app_language.dart';
import '../../models/app_models.dart';
import '../../runtime/runtime_models.dart';
import '../../theme/app_palette.dart';
import '../../theme/app_theme.dart';
import '../../widgets/assistant_focus_panel.dart';
import '../../widgets/assistant_artifact_sidebar.dart';
import '../../widgets/desktop_workspace_scaffold.dart';
import '../../widgets/pane_resize_handle.dart';
import '../../widgets/surface_card.dart';
import 'assistant_page_main.dart';
import 'assistant_page_components.dart';
import 'assistant_page_composer_bar.dart';
import 'assistant_page_composer_state_helpers.dart';
import 'assistant_page_composer_support.dart';
import 'assistant_page_tooltip_labels.dart';
import 'assistant_page_message_widgets.dart';
import 'assistant_page_composer_skill_picker.dart';
import 'assistant_page_composer_clipboard.dart';
import 'assistant_page_components_core.dart';

enum BubbleToneInternal { user, assistant, agent }

enum TimelineItemKindInternal { user, assistant, agent, toolCall }

class TimelineItemInternal {
  const TimelineItemInternal._({
    required this.key,
    required this.kind,
    this.label,
    this.text,
    this.title,
    this.pending = false,
    this.error = false,
  });

  const TimelineItemInternal.message({
    required String key,
    required TimelineItemKindInternal kind,
    required String label,
    required String text,
    required bool pending,
    required bool error,
  }) : this._(
         key: key,
         kind: kind,
         label: label,
         text: text,
         pending: pending,
         error: error,
       );

  const TimelineItemInternal.toolCall({
    required String key,
    required String toolName,
    required String summary,
    required bool pending,
    required bool error,
  }) : this._(
         key: key,
         kind: TimelineItemKindInternal.toolCall,
         title: toolName,
         text: summary,
         pending: pending,
         error: error,
       );

  final String key;
  final TimelineItemKindInternal kind;
  final String? label;
  final String? text;
  final String? title;
  final bool pending;
  final bool error;
}

class AssistantTaskSeedInternal {
  const AssistantTaskSeedInternal({
    required this.sessionKey,
    required this.title,
    required this.preview,
    required this.status,
    required this.updatedAtMs,
    required this.owner,
    required this.surface,
    required this.executionTarget,
    required this.draft,
  });

  final String sessionKey;
  final String title;
  final String preview;
  final String status;
  final double updatedAtMs;
  final String owner;
  final String surface;
  final AssistantExecutionTarget executionTarget;
  final bool draft;

  AssistantTaskEntryInternal toEntry({required bool isCurrent}) {
    return AssistantTaskEntryInternal(
      sessionKey: sessionKey,
      title: title,
      preview: preview,
      status: status,
      updatedAtMs: updatedAtMs,
      owner: owner,
      surface: surface,
      executionTarget: executionTarget,
      isCurrent: isCurrent,
      draft: draft,
    );
  }
}

class AssistantTaskEntryInternal {
  const AssistantTaskEntryInternal({
    required this.sessionKey,
    required this.title,
    required this.preview,
    required this.status,
    required this.updatedAtMs,
    required this.owner,
    required this.surface,
    required this.executionTarget,
    required this.isCurrent,
    this.draft = false,
  });

  final String sessionKey;
  final String title;
  final String preview;
  final String status;
  final double? updatedAtMs;
  final String owner;
  final String surface;
  final AssistantExecutionTarget executionTarget;
  final bool isCurrent;
  final bool draft;

  AssistantTaskEntryInternal copyWith({
    String? sessionKey,
    String? title,
    String? preview,
    String? status,
    double? updatedAtMs,
    String? owner,
    String? surface,
    AssistantExecutionTarget? executionTarget,
    bool? isCurrent,
    bool? draft,
  }) {
    return AssistantTaskEntryInternal(
      sessionKey: sessionKey ?? this.sessionKey,
      title: title ?? this.title,
      preview: preview ?? this.preview,
      status: status ?? this.status,
      updatedAtMs: updatedAtMs ?? this.updatedAtMs,
      owner: owner ?? this.owner,
      surface: surface ?? this.surface,
      executionTarget: executionTarget ?? this.executionTarget,
      isCurrent: isCurrent ?? this.isCurrent,
      draft: draft ?? this.draft,
    );
  }

  String get updatedAtLabel => sessionUpdatedAtLabelInternal(updatedAtMs);
}

class AssistantTaskGroupInternal {
  const AssistantTaskGroupInternal({
    required this.executionTarget,
    required this.items,
  });

  final AssistantExecutionTarget executionTarget;
  final List<AssistantTaskEntryInternal> items;
}

class PillStyleInternal {
  const PillStyleInternal({
    required this.backgroundColor,
    required this.foregroundColor,
  });

  final Color backgroundColor;
  final Color foregroundColor;
}

class MetaPillInternal extends StatelessWidget {
  const MetaPillInternal({super.key, required this.label, required this.icon});

  final String label;
  final IconData icon;

  @override
  Widget build(BuildContext context) {
    final palette = context.palette;
    final theme = Theme.of(context);

    return LayoutBuilder(
      builder: (context, constraints) {
        final maxWidth = constraints.maxWidth;
        if (maxWidth.isFinite && maxWidth < 20) {
          return const SizedBox.shrink();
        }
        final showText = !maxWidth.isFinite || maxWidth >= 52;
        final horizontalPadding = showText ? 10.0 : 8.0;
        return Container(
          padding: EdgeInsets.symmetric(
            horizontal: horizontalPadding,
            vertical: 6,
          ),
          decoration: BoxDecoration(
            color: palette.surfaceSecondary,
            borderRadius: BorderRadius.circular(999),
            border: Border.all(color: palette.strokeSoft),
          ),
          child: Row(
            mainAxisSize: MainAxisSize.min,
            children: [
              Icon(icon, size: 14, color: palette.textMuted),
              if (showText) ...[
                const SizedBox(width: 6),
                Flexible(
                  child: Text(
                    label,
                    maxLines: 1,
                    overflow: TextOverflow.ellipsis,
                    style: theme.textTheme.labelMedium?.copyWith(
                      color: palette.textSecondary,
                    ),
                  ),
                ),
              ],
            ],
          ),
        );
      },
    );
  }
}

PillStyleInternal pillStyleForStatusInternal(
  BuildContext context,
  String label,
) {
  final theme = Theme.of(context);
  final normalized = normalizedTaskStatusInternal(label);
  return switch (normalized) {
    'running' => PillStyleInternal(
      backgroundColor: context.palette.accentMuted,
      foregroundColor: theme.colorScheme.primary,
    ),
    'queued' => PillStyleInternal(
      backgroundColor: context.palette.surfaceSecondary,
      foregroundColor: context.palette.textSecondary,
    ),
    'interrupted' || 'failed' || 'error' => PillStyleInternal(
      backgroundColor: context.palette.surfacePrimary,
      foregroundColor: theme.colorScheme.error,
    ),
    _ => PillStyleInternal(
      backgroundColor: context.palette.surfacePrimary,
      foregroundColor: theme.colorScheme.tertiary,
    ),
  };
}

String normalizedTaskStatusInternal(String status) {
  final value = status.trim().toLowerCase();
  return switch (value) {
    'running' => 'running',
    'interrupted' => 'interrupted',
    'queued' => 'queued',
    'failed' => 'failed',
    'error' => 'error',
    'open' => 'open',
    _ => 'open',
  };
}

String toolCallStatusLabelInternal(String status) =>
    switch (normalizedTaskStatusInternal(status)) {
      'running' => appText('运行中', 'Running'),
      'interrupted' => appText('已中断', 'Interrupted'),
      'failed' || 'error' => appText('错误', 'Error'),
      _ => appText('已完成', 'Completed'),
    };

String assistantThinkingLabelInternal(String level) => switch (level) {
  'low' => appText('低', 'Low'),
  'medium' => appText('中', 'Medium'),
  'max' => appText('超高', 'Max'),
  _ => appText('高', 'High'),
};

String sessionDisplayTitleInternal(GatewaySessionSummary session) {
  final label = session.label.trim();
  if (label.isEmpty || label == session.key) {
    return fallbackSessionTitleInternal(session.key);
  }
  return label;
}

String fallbackSessionTitleInternal(String sessionKey) {
  final trimmed = sessionKey.trim();
  if (trimmed.startsWith('draft:')) {
    return appText('新对话', 'New conversation');
  }
  return trimmed.isEmpty ? appText('未命名对话', 'Untitled conversation') : trimmed;
}

String? sessionPreviewInternal(GatewaySessionSummary session) {
  final preview = session.lastMessagePreview?.trim();
  if (preview != null && preview.isNotEmpty) {
    return preview;
  }
  final subject = session.subject?.trim();
  if (subject != null && subject.isNotEmpty) {
    return subject;
  }
  return null;
}

String sessionStatusInternal(
  GatewaySessionSummary session, {
  required bool sessionPending,
  String lifecycleStatus = '',
}) {
  final normalizedLifecycle = normalizedTaskStatusInternal(lifecycleStatus);
  if (session.abortedLastRun == true) {
    return 'failed';
  }
  if (normalizedLifecycle == 'queued') {
    return 'queued';
  }
  if (sessionPending) {
    return 'running';
  }
  if (normalizedLifecycle == 'interrupted') {
    return 'interrupted';
  }
  if ((session.lastMessagePreview ?? '').trim().isEmpty) {
    return 'queued';
  }
  return 'open';
}

String sessionUpdatedAtLabelInternal(double? updatedAtMs) {
  if (updatedAtMs == null) {
    return appText('未知', 'Unknown');
  }
  final delta = DateTime.now().difference(
    DateTime.fromMillisecondsSinceEpoch(updatedAtMs.toInt()),
  );
  if (delta.inMinutes < 1) {
    return appText('刚刚', 'Now');
  }
  if (delta.inHours < 1) {
    return '${delta.inMinutes}m';
  }
  if (delta.inDays < 1) {
    return '${delta.inHours}h';
  }
  return '${delta.inDays}d';
}

double estimatedComposerWrapSectionHeightInternal({
  required int itemCount,
  required double availableWidth,
  required double averageChipWidth,
}) {
  if (itemCount <= 0) {
    return 0;
  }
  final itemsPerRow = math.max(1, (availableWidth / averageChipWidth).floor());
  final rows = (itemCount / itemsPerRow).ceil();
  const chipHeight = 32.0;
  const runSpacing = 6.0;
  const sectionSpacing = 6.0;
  return sectionSpacing + (rows * chipHeight) + ((rows - 1) * runSpacing);
}

bool sessionKeysMatchInternal(String incoming, String current) {
  final left = incoming.trim().toLowerCase();
  final right = current.trim().toLowerCase();
  return left == right;
}
