import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../../../../core/theme/app_colors.dart';
import '../../domain/entities/chat_message.dart';
import '../providers/chat_providers.dart';
import '../widgets/timeline_event_node.dart';
import '../widgets/stream_text_widget.dart';
import '../widgets/approval_action_card.dart';
import '../../../agent_call/presentation/pages/agent_call_page.dart';

// ---------------------------------------------------------------------------
// Chat page – Timeline workflow style (inspired by Claude Code VSCode)
// ---------------------------------------------------------------------------

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

  @override
  ConsumerState<ChatPage> createState() => _ChatPageState();
}

class _ChatPageState extends ConsumerState<ChatPage> {
  final _messageController = TextEditingController();
  final _scrollController = ScrollController();

  // -- Send ------------------------------------------------------------------

  void _send() {
    final text = _messageController.text.trim();
    if (text.isEmpty) return;
    _messageController.clear();
    ref.read(chatProvider.notifier).sendMessage(text);
    _scrollToBottom();
  }

  void _scrollToBottom() {
    WidgetsBinding.instance.addPostFrameCallback((_) {
      if (_scrollController.hasClients) {
        _scrollController.animateTo(
          _scrollController.position.maxScrollExtent + 80,
          duration: const Duration(milliseconds: 300),
          curve: Curves.easeOut,
        );
      }
    });
  }

  void _openVoiceCall() {
    Navigator.of(context).push(
      MaterialPageRoute(builder: (_) => const AgentCallPage()),
    );
  }

  /// Whether to show a virtual "working" node at the bottom of the timeline.
  /// True when the agent is streaming but no assistant message has appeared yet.
  bool _needsWorkingNode(ChatState chatState) {
    if (!chatState.isStreaming) return false;
    if (chatState.messages.isEmpty) return false;
    // Show working node if the last message is still the user's prompt
    return chatState.messages.last.role == MessageRole.user;
  }

  // -- Timeline node builder ------------------------------------------------

  Widget _buildTimelineNode(
    ChatMessage message,
    ChatState chatState, {
    required bool isFirst,
    required bool isLast,
  }) {
    final isLastMessage = chatState.messages.last.id == message.id;
    final isStreamingNow = isLastMessage && chatState.isStreaming;

    // User message — special "prompt" node
    if (message.role == MessageRole.user) {
      return TimelineEventNode(
        status: NodeStatus.completed,
        label: message.content,
        isFirst: isFirst,
        isLast: isLast,
        icon: Icons.person_outline,
      );
    }

    switch (message.type) {
      case MessageType.thinking:
        return TimelineEventNode(
          status: isStreamingNow ? NodeStatus.active : NodeStatus.completed,
          label: '思考中...',
          isFirst: isFirst,
          isLast: isLast,
          content: _CollapsibleThinking(
            text: message.content,
            isStreaming: isStreamingNow,
          ),
        );

      case MessageType.toolUse:
        final tool = message.toolExecution;
        final toolName = tool?.toolName ?? 'unknown';
        final isExecuting = tool?.status == ToolStatus.executing;
        return TimelineEventNode(
          status: isExecuting ? NodeStatus.active : NodeStatus.completed,
          label: toolName,
          isFirst: isFirst,
          isLast: isLast,
          icon: isExecuting ? null : Icons.check_circle_outline,
          content: tool != null && tool.input.isNotEmpty
              ? CodeBlock(text: tool.input)
              : null,
        );

      case MessageType.toolResult:
        final tool = message.toolExecution;
        final isError = tool?.status == ToolStatus.error;
        return TimelineEventNode(
          status: isError ? NodeStatus.error : NodeStatus.completed,
          label: isError ? '执行失败' : '执行结果',
          isFirst: isFirst,
          isLast: isLast,
          icon: isError ? Icons.cancel_outlined : Icons.check_circle_outline,
          content: tool?.output != null && tool!.output!.isNotEmpty
              ? CodeBlock(
                  text: tool.output!,
                  textColor: isError ? AppColors.error : null,
                )
              : null,
        );

      case MessageType.approval:
        return TimelineEventNode(
          status: NodeStatus.warning,
          label: '需要审批',
          isFirst: isFirst,
          isLast: isLast,
          icon: Icons.shield_outlined,
          content: message.approvalRequest != null
              ? ApprovalActionCard(
                  approvalRequest: message.approvalRequest!,
                  onApprove: () => ref.read(chatProvider.notifier)
                      .approveCommand(message.approvalRequest!.taskId),
                  onReject: (reason) => ref.read(chatProvider.notifier)
                      .rejectCommand(message.approvalRequest!.taskId, reason: reason),
                )
              : null,
        );

      case MessageType.standingOrderDraft:
        return TimelineEventNode(
          status: NodeStatus.warning,
          label: '常驻指令草案',
          isFirst: isFirst,
          isLast: isLast,
          icon: Icons.schedule,
          content: _StandingOrderContent(
            draft: message.metadata ?? {},
            onConfirm: () => ref.read(chatProvider.notifier)
                .confirmStandingOrder(message.metadata ?? {}),
          ),
        );

      case MessageType.text:
      default:
        return TimelineEventNode(
          status: isStreamingNow ? NodeStatus.active : NodeStatus.completed,
          label: isStreamingNow ? '回复中...' : '回复',
          isFirst: isFirst,
          isLast: isLast,
          icon: isStreamingNow ? null : Icons.check_circle_outline,
          content: StreamTextWidget(
            text: message.content,
            isStreaming: isStreamingNow,
            style: const TextStyle(
              color: AppColors.textPrimary,
              fontSize: 14,
            ),
          ),
        );
    }
  }

  // -- Build -----------------------------------------------------------------

  @override
  Widget build(BuildContext context) {
    final chatState = ref.watch(chatProvider);

    // Auto-scroll when messages change
    ref.listen(chatProvider, (_, __) => _scrollToBottom());

    return Scaffold(
      appBar: AppBar(
        title: const Text('iAgent'),
        actions: [
          // Stop button during streaming
          if (chatState.isStreaming)
            IconButton(
              icon: const Icon(Icons.stop_circle_outlined),
              tooltip: '停止',
              onPressed: () => ref.read(chatProvider.notifier).cancelCurrentTask(),
            ),
          if (chatState.messages.isNotEmpty)
            IconButton(
              icon: const Icon(Icons.delete_outline),
              tooltip: '清空对话',
              onPressed: () => ref.read(chatProvider.notifier).clearChat(),
            ),
          // Voice call button
          IconButton(
            icon: const Icon(Icons.call),
            tooltip: '语音通话',
            onPressed: _openVoiceCall,
          ),
        ],
      ),
      body: Column(
        children: [
          // Error banner
          if (chatState.error != null)
            Container(
              width: double.infinity,
              padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
              color: AppColors.error.withOpacity(0.1),
              child: Row(
                children: [
                  const Icon(Icons.error_outline, size: 16, color: AppColors.error),
                  const SizedBox(width: 8),
                  Expanded(
                    child: Text(
                      chatState.error!,
                      style: const TextStyle(color: AppColors.error, fontSize: 13),
                    ),
                  ),
                  GestureDetector(
                    onTap: () => ref.read(chatProvider.notifier).clearChat(),
                    child: const Icon(Icons.close, size: 16, color: AppColors.error),
                  ),
                ],
              ),
            ),

          // Timeline message list
          Expanded(
            child: chatState.messages.isEmpty
                ? _buildEmptyState()
                : ListView.builder(
                    controller: _scrollController,
                    padding: const EdgeInsets.fromLTRB(12, 8, 12, 8),
                    // Extra item for the "working" placeholder when streaming
                    // and the last message is still a user message (no agent
                    // response has arrived yet).
                    itemCount: chatState.messages.length +
                        (_needsWorkingNode(chatState) ? 1 : 0),
                    itemBuilder: (context, index) {
                      // Render the virtual "working" node at the end
                      if (index == chatState.messages.length &&
                          _needsWorkingNode(chatState)) {
                        return TimelineEventNode(
                          status: NodeStatus.active,
                          label: '处理中...',
                          isFirst: false,
                          isLast: false,
                        );
                      }
                      final isRealLast =
                          index == chatState.messages.length - 1;
                      return _buildTimelineNode(
                        chatState.messages[index],
                        chatState,
                        isFirst: index == 0,
                        isLast: isRealLast &&
                            !chatState.isStreaming &&
                            !_needsWorkingNode(chatState),
                      );
                    },
                  ),
          ),

          // Input row
          _buildInputArea(chatState),
        ],
      ),
    );
  }

  Widget _buildEmptyState() {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Icon(Icons.smart_toy_outlined, size: 64, color: AppColors.textMuted),
          const SizedBox(height: 16),
          Text(
            '开始与 iAgent 对话',
            style: TextStyle(color: AppColors.textSecondary, fontSize: 16),
          ),
          const SizedBox(height: 8),
          Text(
            '输入指令或拨打语音通话',
            style: TextStyle(color: AppColors.textMuted, fontSize: 13),
          ),
          const SizedBox(height: 24),
          OutlinedButton.icon(
            onPressed: _openVoiceCall,
            icon: const Icon(Icons.call),
            label: const Text('语音通话'),
            style: OutlinedButton.styleFrom(
              foregroundColor: AppColors.success,
              side: const BorderSide(color: AppColors.success),
              padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12),
            ),
          ),
        ],
      ),
    );
  }

  Widget _buildInputArea(ChatState chatState) {
    final isDisabled = chatState.isStreaming ||
        chatState.agentStatus == AgentStatus.awaitingApproval;

    return Container(
      padding: const EdgeInsets.all(8),
      decoration: BoxDecoration(
        color: AppColors.surface,
        border: Border(top: BorderSide(color: AppColors.surfaceLight.withOpacity(0.5))),
      ),
      child: SafeArea(
        child: Row(
          children: [
            Expanded(
              child: TextField(
                controller: _messageController,
                decoration: const InputDecoration(
                  hintText: '输入指令...',
                  border: OutlineInputBorder(
                    borderRadius: BorderRadius.all(Radius.circular(24)),
                  ),
                  contentPadding: EdgeInsets.symmetric(horizontal: 16, vertical: 10),
                ),
                textInputAction: TextInputAction.send,
                onSubmitted: (_) => _send(),
                enabled: !isDisabled,
              ),
            ),
            const SizedBox(width: 8),
            if (chatState.isStreaming)
              IconButton(
                icon: const Icon(Icons.stop_circle_outlined, color: AppColors.error),
                tooltip: '停止',
                onPressed: () => ref.read(chatProvider.notifier).cancelCurrentTask(),
              )
            else
              IconButton(
                icon: const Icon(Icons.send),
                onPressed: isDisabled ? null : _send,
              ),
          ],
        ),
      ),
    );
  }

  @override
  void dispose() {
    _messageController.dispose();
    _scrollController.dispose();
    super.dispose();
  }
}

// ---------------------------------------------------------------------------
// Standing order content (embedded in timeline node)
// ---------------------------------------------------------------------------

// ---------------------------------------------------------------------------
// Collapsible thinking content – expanded while streaming, collapsed when done
// ---------------------------------------------------------------------------

class _CollapsibleThinking extends StatefulWidget {
  final String text;
  final bool isStreaming;

  const _CollapsibleThinking({
    required this.text,
    required this.isStreaming,
  });

  @override
  State<_CollapsibleThinking> createState() => _CollapsibleThinkingState();
}

class _CollapsibleThinkingState extends State<_CollapsibleThinking> {
  bool _expanded = true;

  @override
  void didUpdateWidget(covariant _CollapsibleThinking oldWidget) {
    super.didUpdateWidget(oldWidget);
    // Auto-collapse when streaming ends
    if (oldWidget.isStreaming && !widget.isStreaming) {
      setState(() => _expanded = false);
    }
  }

  @override
  Widget build(BuildContext context) {
    // While streaming, always show expanded content
    if (widget.isStreaming) {
      return StreamTextWidget(
        text: widget.text,
        isStreaming: true,
        style: const TextStyle(
          color: AppColors.textSecondary,
          fontSize: 13,
          fontStyle: FontStyle.italic,
        ),
      );
    }

    // Completed – show collapsible toggle
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        GestureDetector(
          onTap: () => setState(() => _expanded = !_expanded),
          child: Row(
            mainAxisSize: MainAxisSize.min,
            children: [
              Text(
                'Thinking',
                style: TextStyle(
                  color: AppColors.textMuted,
                  fontSize: 12,
                  fontWeight: FontWeight.w500,
                ),
              ),
              const SizedBox(width: 4),
              AnimatedRotation(
                turns: _expanded ? 0.5 : 0.0,
                duration: const Duration(milliseconds: 200),
                child: Icon(
                  Icons.expand_more,
                  size: 16,
                  color: AppColors.textMuted,
                ),
              ),
            ],
          ),
        ),
        AnimatedCrossFade(
          firstChild: Padding(
            padding: const EdgeInsets.only(top: 6),
            child: StreamTextWidget(
              text: widget.text,
              isStreaming: false,
              style: const TextStyle(
                color: AppColors.textSecondary,
                fontSize: 13,
                fontStyle: FontStyle.italic,
              ),
            ),
          ),
          secondChild: const SizedBox.shrink(),
          crossFadeState: _expanded
              ? CrossFadeState.showFirst
              : CrossFadeState.showSecond,
          duration: const Duration(milliseconds: 200),
        ),
      ],
    );
  }
}

// ---------------------------------------------------------------------------
// Standing order content (embedded in timeline node)
// ---------------------------------------------------------------------------

class _StandingOrderContent extends StatelessWidget {
  final Map<String, dynamic> draft;
  final VoidCallback onConfirm;

  const _StandingOrderContent({
    required this.draft,
    required this.onConfirm,
  });

  @override
  Widget build(BuildContext context) {
    final name = draft['name'] as String? ?? draft['orderName'] as String? ?? '未命名指令';
    final cron = draft['cron'] as String? ?? draft['schedule'] as String? ?? '';
    final command = draft['command'] as String? ?? draft['prompt'] as String? ?? '';
    final targets = draft['targets'] as List? ?? draft['servers'] as List? ?? [];

    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Text(name, style: const TextStyle(fontWeight: FontWeight.w600, fontSize: 14)),
        if (cron.isNotEmpty) ...[
          const SizedBox(height: 4),
          Text(
            cron,
            style: const TextStyle(
              color: AppColors.textSecondary,
              fontSize: 12,
              fontFamily: 'monospace',
            ),
          ),
        ],
        if (command.isNotEmpty) ...[
          const SizedBox(height: 6),
          CodeBlock(text: command),
        ],
        if (targets.isNotEmpty) ...[
          const SizedBox(height: 4),
          Text(
            '目标: ${targets.join(", ")}',
            style: const TextStyle(color: AppColors.textSecondary, fontSize: 12),
          ),
        ],
        const SizedBox(height: 8),
        Row(
          children: [
            OutlinedButton(
              onPressed: () {},
              style: OutlinedButton.styleFrom(
                foregroundColor: AppColors.textSecondary,
                padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 6),
                minimumSize: Size.zero,
              ),
              child: const Text('取消', style: TextStyle(fontSize: 12)),
            ),
            const SizedBox(width: 8),
            FilledButton(
              onPressed: onConfirm,
              style: FilledButton.styleFrom(
                backgroundColor: AppColors.primary,
                padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 6),
                minimumSize: Size.zero,
              ),
              child: const Text('确认', style: TextStyle(fontSize: 12)),
            ),
          ],
        ),
      ],
    );
  }
}
