import 'package:equatable/equatable.dart';
import '../../models/setting_generation_session.dart';
import '../../models/setting_node.dart';
import '../../models/setting_generation_event.dart' as event_model;
import '../../models/compose_preview.dart';
import '../../models/strategy_template_info.dart';
import '../../utils/setting_node_utils.dart'; // 导入工具类

abstract class SettingGenerationState extends Equatable {
  const SettingGenerationState();

  @override
  List<Object?> get props => [];
}

/// 初始状态
class SettingGenerationInitial extends SettingGenerationState {
  const SettingGenerationInitial();
}

/// 加载中
class SettingGenerationLoading extends SettingGenerationState {
  final String? message;

  const SettingGenerationLoading({this.message});

  @override
  List<Object?> get props => [message];
}

/// 策略已加载
class StrategiesLoaded extends SettingGenerationState {
  final List<StrategyTemplateInfo> strategies;

  const StrategiesLoaded(this.strategies);

  @override
  List<Object?> get props => [strategies];
}

/// 待机状态（准备开始生成）
class SettingGenerationReady extends SettingGenerationState {
  final List<StrategyTemplateInfo> strategies;
  final List<SettingGenerationSession> sessions;
  final String? activeSessionId;
  final String adjustmentPrompt;
  final String viewMode;

  const SettingGenerationReady({
    required this.strategies,
    this.sessions = const [],
    this.activeSessionId,
    this.adjustmentPrompt = '',
    this.viewMode = 'compact',
  });

  @override
  List<Object?> get props => [
        strategies,
        sessions,
        activeSessionId,
        adjustmentPrompt,
        viewMode,
      ];

  SettingGenerationReady copyWith({
    List<StrategyTemplateInfo>? strategies,
    List<SettingGenerationSession>? sessions,
    String? activeSessionId,
    String? adjustmentPrompt,
    String? viewMode,
  }) {
    return SettingGenerationReady(
      strategies: strategies ?? this.strategies,
      sessions: sessions ?? this.sessions,
      activeSessionId: activeSessionId ?? this.activeSessionId,
      adjustmentPrompt: adjustmentPrompt ?? this.adjustmentPrompt,
      viewMode: viewMode ?? this.viewMode,
    );
  }
}

/// 节点渲染状态枚举
enum NodeRenderState {
  pending,     // 待渲染（在队列中）
  rendering,   // 正在渲染（动画中）
  rendered,    // 已渲染完成
}

/// 节点渲染信息
class NodeRenderInfo {
  final String nodeId;
  final NodeRenderState state;
  final DateTime? renderStartTime;
  final Duration? renderDuration;

  const NodeRenderInfo({
    required this.nodeId,
    required this.state,
    this.renderStartTime,
    this.renderDuration,
  });

  NodeRenderInfo copyWith({
    NodeRenderState? state,
    DateTime? renderStartTime,
    Duration? renderDuration,
  }) {
    return NodeRenderInfo(
      nodeId: nodeId,
      state: state ?? this.state,
      renderStartTime: renderStartTime ?? this.renderStartTime,
      renderDuration: renderDuration ?? this.renderDuration,
    );
  }
}

/// 生成中
class SettingGenerationInProgress extends SettingGenerationState {
  final List<StrategyTemplateInfo> strategies;
  final List<SettingGenerationSession> sessions;
  final String activeSessionId;
  final SettingGenerationSession activeSession;
  final String? selectedNodeId;
  final String viewMode;
  final String adjustmentPrompt;
  final Map<String, SettingNode> pendingChanges;
  final Set<String> highlightedNodeIds;
  final Map<String, List<SettingNode>> editHistory;
  final List<event_model.SettingGenerationEvent> events;
  final bool isGenerating;
  final String? currentOperation;
  // 新增：写作编排流的预览缓存（仅前端展示，不落库）
  final List<ComposeChapterPreview> composePreview;
  
  // 新增的渲染状态管理字段
  final Map<String, NodeRenderInfo> nodeRenderStates;
  final List<String> renderQueue;
  final Set<String> renderedNodeIds;

  final List<event_model.NodeCreatedEvent> pendingNodes;
  // 粘性警告（例如余额不足提醒），不会被后续普通事件覆盖
  final String? stickyWarning;

  const SettingGenerationInProgress({
    required this.strategies,
    required this.sessions,
    required this.activeSessionId,
    required this.activeSession,
    this.selectedNodeId,
    this.viewMode = 'compact',
    this.adjustmentPrompt = '',
    this.pendingChanges = const {},
    this.highlightedNodeIds = const {},
    this.editHistory = const {},
    this.isGenerating = false,
    this.currentOperation,
    this.composePreview = const [],
    this.events = const [],
    this.nodeRenderStates = const {},
    this.renderQueue = const [],
    this.renderedNodeIds = const {},
    this.pendingNodes = const [],
    this.stickyWarning,
  });

  @override
  List<Object?> get props => [
    strategies,
    sessions,
    activeSessionId,
    activeSession,
    selectedNodeId,
    viewMode,
    adjustmentPrompt,
    pendingChanges,
    highlightedNodeIds,
    editHistory,
    isGenerating,
    currentOperation,
    composePreview,
    events,
    nodeRenderStates,
    renderQueue,
    renderedNodeIds,
    stickyWarning,
  ];

  SettingGenerationInProgress copyWith({
    List<StrategyTemplateInfo>? strategies,
    List<SettingGenerationSession>? sessions,
    String? activeSessionId,
    SettingGenerationSession? activeSession,
    String? selectedNodeId,
    String? viewMode,
    String? adjustmentPrompt,
    Map<String, SettingNode>? pendingChanges,
    Set<String>? highlightedNodeIds,
    Map<String, List<SettingNode>>? editHistory,
    bool? isGenerating,
    String? currentOperation,
    List<ComposeChapterPreview>? composePreview,
    List<event_model.SettingGenerationEvent>? events,
    Map<String, NodeRenderInfo>? nodeRenderStates,
    List<String>? renderQueue,
    Set<String>? renderedNodeIds,
    List<event_model.NodeCreatedEvent>? pendingNodes,
    String? stickyWarning,
  }) {
    return SettingGenerationInProgress(
      strategies: strategies ?? this.strategies,
      sessions: sessions ?? this.sessions,
      activeSessionId: activeSessionId ?? this.activeSessionId,
      activeSession: activeSession ?? this.activeSession,
      selectedNodeId: selectedNodeId ?? this.selectedNodeId,
      viewMode: viewMode ?? this.viewMode,
      adjustmentPrompt: adjustmentPrompt ?? this.adjustmentPrompt,
      pendingChanges: pendingChanges ?? this.pendingChanges,
      highlightedNodeIds: highlightedNodeIds ?? this.highlightedNodeIds,
      editHistory: editHistory ?? this.editHistory,
      isGenerating: isGenerating ?? this.isGenerating,
      currentOperation: currentOperation ?? this.currentOperation,
      composePreview: composePreview ?? this.composePreview,
      events: events ?? this.events,
      nodeRenderStates: nodeRenderStates ?? this.nodeRenderStates,
      renderQueue: renderQueue ?? this.renderQueue,
      renderedNodeIds: renderedNodeIds ?? this.renderedNodeIds,
      pendingNodes: pendingNodes ?? this.pendingNodes,
      stickyWarning: stickyWarning ?? this.stickyWarning,
    );
  }

  /// 获取当前选中的节点
  SettingNode? get selectedNode {
    if (selectedNodeId == null) return null;
    return SettingNodeUtils.findNodeInTree(activeSession.rootNodes, selectedNodeId!);
  }

  /// 获取可以渲染的节点列表（父节点为空或已渲染）
  List<String> get renderableNodeIds {
    return SettingNodeUtils.getRenderableNodeIds(
      activeSession.rootNodes,
      renderQueue,
      renderedNodeIds,
    );
  }
}

/// 生成完成
class SettingGenerationCompleted extends SettingGenerationState {
  final List<StrategyTemplateInfo> strategies;
  final List<SettingGenerationSession> sessions;
  final String activeSessionId;
  final SettingGenerationSession activeSession;
  final String? selectedNodeId;
  final String viewMode;
  final String adjustmentPrompt;
  final Map<String, SettingNode> pendingChanges;
  final Set<String> highlightedNodeIds;
  final Map<String, List<SettingNode>> editHistory;
  final List<event_model.SettingGenerationEvent> events;
  final String message;
  
  // 新增的渲染状态管理字段
  final Map<String, NodeRenderInfo> nodeRenderStates;
  final Set<String> renderedNodeIds;
  final String? stickyWarning;

  const SettingGenerationCompleted({
    required this.strategies,
    required this.sessions,
    required this.activeSessionId,
    required this.activeSession,
    this.selectedNodeId,
    this.viewMode = 'compact',
    this.adjustmentPrompt = '',
    this.pendingChanges = const {},
    this.highlightedNodeIds = const {},
    this.editHistory = const {},
    this.events = const [],
    required this.message,
    this.nodeRenderStates = const {},
    this.renderedNodeIds = const {},
    this.stickyWarning,
  });

  @override
  List<Object?> get props => [
    strategies,
    sessions,
    activeSessionId,
    activeSession,
    selectedNodeId,
    viewMode,
    adjustmentPrompt,
    pendingChanges,
    highlightedNodeIds,
    editHistory,
    events,
    message,
    nodeRenderStates,
    renderedNodeIds,
    stickyWarning,
  ];

  SettingGenerationCompleted copyWith({
    List<StrategyTemplateInfo>? strategies,
    List<SettingGenerationSession>? sessions,
    String? activeSessionId,
    SettingGenerationSession? activeSession,
    String? selectedNodeId,
    String? viewMode,
    String? adjustmentPrompt,
    Map<String, SettingNode>? pendingChanges,
    Set<String>? highlightedNodeIds,
    Map<String, List<SettingNode>>? editHistory,
    List<event_model.SettingGenerationEvent>? events,
    String? message,
    Map<String, NodeRenderInfo>? nodeRenderStates,
    Set<String>? renderedNodeIds,
    String? stickyWarning,
  }) {
    return SettingGenerationCompleted(
      strategies: strategies ?? this.strategies,
      sessions: sessions ?? this.sessions,
      activeSessionId: activeSessionId ?? this.activeSessionId,
      activeSession: activeSession ?? this.activeSession,
      selectedNodeId: selectedNodeId ?? this.selectedNodeId,
      viewMode: viewMode ?? this.viewMode,
      adjustmentPrompt: adjustmentPrompt ?? this.adjustmentPrompt,
      pendingChanges: pendingChanges ?? this.pendingChanges,
      highlightedNodeIds: highlightedNodeIds ?? this.highlightedNodeIds,
      editHistory: editHistory ?? this.editHistory,
      events: events ?? this.events,
      message: message ?? this.message,
      nodeRenderStates: nodeRenderStates ?? this.nodeRenderStates,
      renderedNodeIds: renderedNodeIds ?? this.renderedNodeIds,
      stickyWarning: stickyWarning ?? this.stickyWarning,
    );
  }

  /// 获取当前选中的节点
  SettingNode? get selectedNode {
    if (selectedNodeId == null) return null;
    return SettingNodeUtils.findNodeInTree(activeSession.rootNodes, selectedNodeId!);
  }
}

/// 节点修改中状态（专门用于节点修改，避免整个设定树重新渲染）
class SettingGenerationNodeUpdating extends SettingGenerationState {
  final List<StrategyTemplateInfo> strategies;
  final List<SettingGenerationSession> sessions;
  final String activeSessionId;
  final SettingGenerationSession activeSession;
  final String? selectedNodeId;
  final String viewMode;
  final String adjustmentPrompt;
  final Map<String, SettingNode> pendingChanges;
  final Set<String> highlightedNodeIds;
  final Map<String, List<SettingNode>> editHistory;
  final List<event_model.SettingGenerationEvent> events;
  final String message;
  
  // 节点修改特有字段
  final String updatingNodeId; // 正在修改的节点ID
  final String modificationPrompt; // 修改提示词
  final String scope; // 修改范围
  final bool isUpdating; // 是否正在更新中
  
  // 渲染状态管理字段
  final Map<String, NodeRenderInfo> nodeRenderStates;
  final Set<String> renderedNodeIds;

  const SettingGenerationNodeUpdating({
    required this.strategies,
    required this.sessions,
    required this.activeSessionId,
    required this.activeSession,
    this.selectedNodeId,
    this.viewMode = 'compact',
    this.adjustmentPrompt = '',
    this.pendingChanges = const {},
    this.highlightedNodeIds = const {},
    this.editHistory = const {},
    this.events = const [],
    this.message = '',
    required this.updatingNodeId,
    this.modificationPrompt = '',
    this.scope = 'self',
    this.isUpdating = false,
    this.nodeRenderStates = const {},
    this.renderedNodeIds = const {},
  });

  @override
  List<Object?> get props => [
    strategies,
    sessions,
    activeSessionId,
    activeSession,
    selectedNodeId,
    viewMode,
    adjustmentPrompt,
    pendingChanges,
    highlightedNodeIds,
    editHistory,
    events,
    message,
    updatingNodeId,
    modificationPrompt,
    scope,
    isUpdating,
    nodeRenderStates,
    renderedNodeIds,
  ];

  SettingGenerationNodeUpdating copyWith({
    List<StrategyTemplateInfo>? strategies,
    List<SettingGenerationSession>? sessions,
    String? activeSessionId,
    SettingGenerationSession? activeSession,
    String? selectedNodeId,
    String? viewMode,
    String? adjustmentPrompt,
    Map<String, SettingNode>? pendingChanges,
    Set<String>? highlightedNodeIds,
    Map<String, List<SettingNode>>? editHistory,
    List<event_model.SettingGenerationEvent>? events,
    String? message,
    String? updatingNodeId,
    String? modificationPrompt,
    String? scope,
    bool? isUpdating,
    Map<String, NodeRenderInfo>? nodeRenderStates,
    Set<String>? renderedNodeIds,
  }) {
    return SettingGenerationNodeUpdating(
      strategies: strategies ?? this.strategies,
      sessions: sessions ?? this.sessions,
      activeSessionId: activeSessionId ?? this.activeSessionId,
      activeSession: activeSession ?? this.activeSession,
      selectedNodeId: selectedNodeId ?? this.selectedNodeId,
      viewMode: viewMode ?? this.viewMode,
      adjustmentPrompt: adjustmentPrompt ?? this.adjustmentPrompt,
      pendingChanges: pendingChanges ?? this.pendingChanges,
      highlightedNodeIds: highlightedNodeIds ?? this.highlightedNodeIds,
      editHistory: editHistory ?? this.editHistory,
      events: events ?? this.events,
      message: message ?? this.message,
      updatingNodeId: updatingNodeId ?? this.updatingNodeId,
      modificationPrompt: modificationPrompt ?? this.modificationPrompt,
      scope: scope ?? this.scope,
      isUpdating: isUpdating ?? this.isUpdating,
      nodeRenderStates: nodeRenderStates ?? this.nodeRenderStates,
      renderedNodeIds: renderedNodeIds ?? this.renderedNodeIds,
    );
  }

  /// 获取当前选中的节点
  SettingNode? get selectedNode {
    if (selectedNodeId == null) return null;
    return SettingNodeUtils.findNodeInTree(activeSession.rootNodes, selectedNodeId!);
  }

  /// 获取正在修改的节点
  SettingNode? get updatingNode {
    return SettingNodeUtils.findNodeInTree(activeSession.rootNodes, updatingNodeId);
  }
}

/// 保存成功
class SettingGenerationSaved extends SettingGenerationState {
  final List<String> savedSettingIds;
  final String message;
  // 新增：保留会话列表和当前活跃会话ID，避免UI刷新
  final List<SettingGenerationSession> sessions;
  final String? activeSessionId;

  const SettingGenerationSaved({
    required this.savedSettingIds,
    this.message = '设定已成功保存',
    this.sessions = const [],
    this.activeSessionId,
  });

  @override
  List<Object?> get props => [savedSettingIds, message, sessions, activeSessionId];
}

/// 错误状态
class SettingGenerationError extends SettingGenerationState {
  final String message;
  final dynamic error;
  final StackTrace? stackTrace;
  final bool isRecoverable;
  // 新增：保留会话列表和当前活跃会话 ID，避免 UI 在错误时丢失历史记录
  final List<SettingGenerationSession> sessions;
  final String? activeSessionId;

  const SettingGenerationError({
    required this.message,
    this.error,
    this.stackTrace,
    this.isRecoverable = true,
    this.sessions = const [],
    this.activeSessionId,
  });

  @override
  List<Object?> get props => [
    message,
    error,
    stackTrace,
    isRecoverable,
    sessions,
    activeSessionId,
  ];

  SettingGenerationError copyWith({
    String? message,
    dynamic error,
    StackTrace? stackTrace,
    bool? isRecoverable,
    List<SettingGenerationSession>? sessions,
    String? activeSessionId,
  }) {
    return SettingGenerationError(
      message: message ?? this.message,
      error: error ?? this.error,
      stackTrace: stackTrace ?? this.stackTrace,
      isRecoverable: isRecoverable ?? this.isRecoverable,
      sessions: sessions ?? this.sessions,
      activeSessionId: activeSessionId ?? this.activeSessionId,
    );
  }
}
