import React, { useCallback, useEffect, useState } from 'react';
import {
  Button,
  Card,
  Descriptions,
  message,
  Popconfirm,
  Space,
  Spin,
  Steps,
  Tag,
  Tooltip,
  Typography,
} from 'antd';
import {
  ArrowLeftOutlined,
  CheckCircleOutlined,
  ClockCircleOutlined,
  CloseCircleOutlined,
  LinkOutlined,
  LoadingOutlined,
  ReloadOutlined,
  StopOutlined,
} from '@ant-design/icons';
import { useNavigate, useParams } from 'react-router-dom';
import { customRequest } from 'helpers/http';
import { EnhancedFlowRenderer } from './components/EnhancedFlowRenderer';
import type { WorkflowDSL } from './types';

const { Title, Text } = Typography;

const STATUS_TAG: Record<
  string,
  { color: string; label: string; icon: React.ReactNode }
> = {
  PENDING: { color: 'gold', label: 'Pending', icon: <ClockCircleOutlined /> },
  RUNNING: { color: 'blue', label: 'Running', icon: <LoadingOutlined /> },
  COMPLETED: {
    color: 'green',
    label: 'Completed',
    icon: <CheckCircleOutlined />,
  },
  FAILED: { color: 'red', label: 'Failed', icon: <CloseCircleOutlined /> },
  CANCELLED: { color: 'default', label: 'Cancelled', icon: <StopOutlined /> },
};

interface NodeExecution {
  id: string;
  nodeId: string;
  nodeType: string;
  nodeLabel: string | null;
  status: string;
  input: any;
  output: any;
  error: any;
  startedAt: string | null;
  finishedAt: string | null;
}

interface InstanceDetail {
  id: string;
  workflowId: string;
  status: string;
  context: any;
  result: any;
  temporalRunId: string | null;
  startedAt: string | null;
  finishedAt: string | null;
  creator: string;
  createdAt: string;
  workflow: { name: string };
  nodeExecutions: NodeExecution[];
  dsl?: WorkflowDSL;
}

function formatDuration(start: string | null, end: string | null): string {
  if (!start) return '—';
  const endTime = end ? new Date(end).getTime() : Date.now();
  const ms = endTime - new Date(start).getTime();
  if (ms < 1000) return `${ms}ms`;
  const s = Math.floor(ms / 1000);
  if (s < 60) return `${s}s`;
  const m = Math.floor(s / 60);
  const rem = s % 60;
  return rem > 0 ? `${m}m ${rem}s` : `${m}m`;
}

function getStepStatus(
  status: string,
): 'wait' | 'process' | 'finish' | 'error' {
  switch (status) {
    case 'COMPLETED':
      return 'finish';
    case 'RUNNING':
      return 'process';
    case 'FAILED':
      return 'error';
    default:
      return 'wait';
  }
}

export default function WorkflowInstanceDetailPage() {
  const { instanceId } = useParams<{ instanceId: string }>();
  const navigate = useNavigate();
  const [data, setData] = useState<InstanceDetail | null>(null);
  const [loading, setLoading] = useState(true);
  const [actionLoading, setActionLoading] = useState(false);
  const [selectedNodeId, setSelectedNodeId] = useState<string | null>(null);
  const [viewMode, setViewMode] = useState<'timeline' | 'canvas'>('canvas');

  const fetchData = useCallback(async () => {
    if (!instanceId) return;
    try {
      const res = await customRequest<InstanceDetail>(
        `workflow/instance/${instanceId}`,
        'GET',
      );
      setData(res);
    } catch (e: any) {
      message.error(e?.message || 'Failed to load instance');
    } finally {
      setLoading(false);
    }
  }, [instanceId]);

  useEffect(() => {
    fetchData();
  }, [fetchData]);

  // Auto-refresh for running instances
  useEffect(() => {
    if (data?.status === 'RUNNING' || data?.status === 'PENDING') {
      const interval = setInterval(fetchData, 3000);
      return () => clearInterval(interval);
    }
  }, [data?.status, fetchData]);

  // Fallback to timeline if no DSL available
  useEffect(() => {
    if (data && !data.dsl && viewMode === 'canvas') {
      setViewMode('timeline');
    }
  }, [data, viewMode]);

  const handleCancel = async () => {
    setActionLoading(true);
    try {
      await customRequest(`workflow/instance/${instanceId}/cancel`, 'POST');
      message.success('Instance cancelled');
      fetchData();
    } catch (e: any) {
      message.error(e?.message || 'Failed to cancel');
    } finally {
      setActionLoading(false);
    }
  };

  const handleRetry = async () => {
    setActionLoading(true);
    try {
      const res = await customRequest<{ instanceId: string }>(
        `workflow/instance/${instanceId}/retry`,
        'POST',
      );
      message.success('Retry started');
      navigate(`/admin/workflow/instance/show/${res.instanceId}`);
    } catch (e: any) {
      message.error(e?.message || 'Failed to retry');
    } finally {
      setActionLoading(false);
    }
  };

  const handleApprove = async (nodeId: string, approved: boolean) => {
    setActionLoading(true);
    try {
      await customRequest(`workflow/instance/${instanceId}/signal`, 'POST', {
        signalName: 'approval',
        payload: { nodeId, approved, approvedBy: 'current_user', comment: '' },
      });
      message.success(approved ? 'Approved' : 'Rejected');
      fetchData();
    } catch (e: any) {
      message.error(e?.message || 'Failed to send signal');
    } finally {
      setActionLoading(false);
    }
  };

  if (loading) {
    return (
      <div
        style={{
          display: 'flex',
          justifyContent: 'center',
          alignItems: 'center',
          height: '100vh',
        }}
      >
        <Spin size="large" />
      </div>
    );
  }

  if (!data) return null;

  const statusCfg = STATUS_TAG[data.status] || STATUS_TAG.PENDING;
  const selectedExecution = selectedNodeId
    ? data.nodeExecutions.find((ne) => ne.nodeId === selectedNodeId)
    : null;
  const selectedDslNode =
    selectedNodeId && data.dsl
      ? data.dsl.nodes.find((n) => n.id === selectedNodeId)
      : null;

  return (
    <div
      style={{
        background: '#f0f2f5',
        minHeight: 'calc(100vh - 64px)',
        padding: 0,
      }}
    >
      {/* Header */}
      <Card style={{ marginBottom: 16 }}>
        <div
          style={{
            display: 'flex',
            justifyContent: 'space-between',
            alignItems: 'center',
          }}
        >
          <Space>
            <Button
              type="text"
              icon={<ArrowLeftOutlined />}
              onClick={() => navigate(-1)}
            ></Button>
            <Title level={4} style={{ margin: 0 }}>
              {data.workflow.name} — Instance #{data.id}
            </Title>
            <Tag color={statusCfg.color} icon={statusCfg.icon}>
              {statusCfg.label}
            </Tag>
          </Space>
          <Space>
            <Tooltip
              title={
                data.temporalRunId
                  ? '在 Temporal Web UI 中查看完整执行历史、Pending Activities 和 Worker 状态'
                  : '此实例无 Temporal Run ID（可能由 outbox-poller 创建或 Temporal 当时不可用）'
              }
            >
              <Button
                icon={<LinkOutlined />}
                disabled={!data.temporalRunId}
                onClick={() => {
                  if (!data.temporalRunId) return;
                  const base =
                    import.meta.env.VITE_TEMPORAL_UI_URL ||
                    'http://localhost:8080';
                  const ns =
                    import.meta.env.VITE_TEMPORAL_NAMESPACE || 'default';
                  window.open(
                    `${base}/namespaces/${ns}/workflows/${encodeURIComponent(
                      data.temporalRunId,
                    )}`,
                    '_blank',
                    'noopener,noreferrer',
                  );
                }}
              >
                在 Temporal 中查看
              </Button>
            </Tooltip>
            {(data.status === 'RUNNING' || data.status === 'PENDING') && (
              <Popconfirm
                title="Cancel this workflow execution?"
                onConfirm={handleCancel}
                okText="Yes"
                cancelText="No"
              >
                <Button danger loading={actionLoading} icon={<StopOutlined />}>
                  Cancel
                </Button>
              </Popconfirm>
            )}
            {data.status === 'FAILED' && (
              <Button
                type="primary"
                loading={actionLoading}
                onClick={handleRetry}
              >
                Retry
              </Button>
            )}
            <Button icon={<ReloadOutlined />} onClick={fetchData}>
              Refresh
            </Button>
          </Space>
        </div>
      </Card>

      {/* Instance Info */}
      <Card style={{ marginBottom: 16 }} title="Execution Details">
        <Descriptions column={3} size="small">
          <Descriptions.Item label="Instance ID">{data.id}</Descriptions.Item>
          <Descriptions.Item label="Temporal Run ID">
            <Text copyable style={{ fontSize: 12 }}>
              {data.temporalRunId || '—'}
            </Text>
          </Descriptions.Item>
          <Descriptions.Item label="Creator">{data.creator}</Descriptions.Item>
          <Descriptions.Item label="Started">
            {data.startedAt ? new Date(data.startedAt).toLocaleString() : '—'}
          </Descriptions.Item>
          <Descriptions.Item label="Finished">
            {data.finishedAt ? new Date(data.finishedAt).toLocaleString() : '—'}
          </Descriptions.Item>
          <Descriptions.Item label="Duration">
            {formatDuration(data.startedAt, data.finishedAt)}
          </Descriptions.Item>
        </Descriptions>
      </Card>

      {/* Node Execution Timeline / Canvas View */}
      <Card
        title={
          viewMode === 'timeline'
            ? 'Node Execution Timeline'
            : 'Flow Execution Visualization'
        }
        extra={
          data.dsl ? (
            <Space>
              <Button.Group>
                <Button
                  type={viewMode === 'canvas' ? 'primary' : 'default'}
                  onClick={() => {
                    setViewMode('canvas');
                    setSelectedNodeId(null);
                  }}
                >
                  Canvas
                </Button>
                <Button
                  type={viewMode === 'timeline' ? 'primary' : 'default'}
                  onClick={() => {
                    setViewMode('timeline');
                    setSelectedNodeId(null);
                  }}
                >
                  Timeline
                </Button>
              </Button.Group>
            </Space>
          ) : null
        }
      >
        {viewMode === 'timeline' ? (
          // Timeline View
          <div style={{ display: 'flex', gap: 16 }}>
            <div style={{ flex: 1 }}>
              {data.nodeExecutions.length === 0 ? (
                <Text type="secondary">No node executions recorded yet.</Text>
              ) : (
                <Steps
                  direction="vertical"
                  size="small"
                  current={-1}
                  items={data.nodeExecutions.map((ne) => {
                    const isApprovalPending =
                      ne.nodeType === 'approval' && ne.status === 'RUNNING';
                    const isSelected = selectedNodeId === ne.nodeId;
                    return {
                      title: (
                        <Space
                          style={{ cursor: 'pointer' }}
                          onClick={() =>
                            setSelectedNodeId(isSelected ? null : ne.nodeId)
                          }
                        >
                          <span style={{ fontWeight: isSelected ? 600 : 400 }}>
                            {ne.nodeLabel || ne.nodeId}
                          </span>
                          <Tag style={{ fontSize: 11 }}>{ne.nodeType}</Tag>
                          {isApprovalPending && (
                            <Space size={4}>
                              <Button
                                size="small"
                                type="primary"
                                onClick={(e) => {
                                  e.stopPropagation();
                                  handleApprove(ne.nodeId, true);
                                }}
                                loading={actionLoading}
                              >
                                Approve
                              </Button>
                              <Button
                                size="small"
                                danger
                                onClick={(e) => {
                                  e.stopPropagation();
                                  handleApprove(ne.nodeId, false);
                                }}
                                loading={actionLoading}
                              >
                                Reject
                              </Button>
                            </Space>
                          )}
                        </Space>
                      ),
                      description: (
                        <div
                          style={{
                            fontSize: 12,
                            color: '#666',
                            cursor: 'pointer',
                          }}
                          onClick={() =>
                            setSelectedNodeId(isSelected ? null : ne.nodeId)
                          }
                        >
                          <span>
                            Duration:{' '}
                            {formatDuration(ne.startedAt, ne.finishedAt)}
                          </span>
                          {ne.error && (
                            <div style={{ color: '#ff4d4f', marginTop: 4 }}>
                              Error:{' '}
                              {typeof ne.error === 'object'
                                ? JSON.stringify(ne.error)
                                : String(ne.error)}
                            </div>
                          )}
                        </div>
                      ),
                      status: getStepStatus(ne.status),
                      icon:
                        ne.status === 'RUNNING' ? (
                          <LoadingOutlined />
                        ) : undefined,
                    };
                  })}
                />
              )}
            </div>

            {/* Node Detail Panel (shared with canvas view) */}
            {selectedExecution && (
              <div
                style={{
                  width: 320,
                  borderLeft: '1px solid #f0f0f0',
                  paddingLeft: 16,
                  overflowY: 'auto',
                }}
              >
                <div style={{ marginBottom: 16 }}>
                  <Title level={5}>
                    {selectedExecution.nodeLabel || selectedExecution.nodeId}
                  </Title>
                  <Tag
                    color={
                      selectedExecution.status === 'COMPLETED'
                        ? 'green'
                        : selectedExecution.status === 'RUNNING'
                          ? 'blue'
                          : selectedExecution.status === 'FAILED'
                            ? 'red'
                            : 'gold'
                    }
                  >
                    {selectedExecution.status}
                  </Tag>
                </div>

                <Descriptions
                  column={1}
                  size="small"
                  style={{ marginBottom: 16 }}
                >
                  <Descriptions.Item label="Node Type">
                    {selectedExecution.nodeType}
                  </Descriptions.Item>
                  <Descriptions.Item label="Started">
                    {selectedExecution.startedAt
                      ? new Date(selectedExecution.startedAt).toLocaleString()
                      : '—'}
                  </Descriptions.Item>
                  <Descriptions.Item label="Finished">
                    {selectedExecution.finishedAt
                      ? new Date(selectedExecution.finishedAt).toLocaleString()
                      : '—'}
                  </Descriptions.Item>
                  <Descriptions.Item label="Duration">
                    {formatDuration(
                      selectedExecution.startedAt,
                      selectedExecution.finishedAt,
                    )}
                  </Descriptions.Item>
                </Descriptions>

                {selectedExecution.input && (
                  <div style={{ marginBottom: 12 }}>
                    <Text strong style={{ fontSize: 12 }}>
                      Input:
                    </Text>
                    <pre
                      style={{
                        background: '#fafafa',
                        padding: 8,
                        borderRadius: 4,
                        fontSize: 11,
                        maxHeight: 150,
                        overflow: 'auto',
                      }}
                    >
                      {JSON.stringify(selectedExecution.input, null, 2)}
                    </pre>
                  </div>
                )}

                {selectedExecution.output && (
                  <div style={{ marginBottom: 12 }}>
                    <Text strong style={{ fontSize: 12 }}>
                      Output:
                    </Text>
                    <pre
                      style={{
                        background: '#fafafa',
                        padding: 8,
                        borderRadius: 4,
                        fontSize: 11,
                        maxHeight: 150,
                        overflow: 'auto',
                      }}
                    >
                      {JSON.stringify(selectedExecution.output, null, 2)}
                    </pre>
                  </div>
                )}

                {selectedExecution.error && (
                  <div style={{ marginBottom: 12 }}>
                    <Text strong style={{ fontSize: 12, color: '#ff4d4f' }}>
                      Error:
                    </Text>
                    <pre
                      style={{
                        background: '#fff1f0',
                        padding: 8,
                        borderRadius: 4,
                        fontSize: 11,
                        color: '#ff4d4f',
                        maxHeight: 150,
                        overflow: 'auto',
                      }}
                    >
                      {typeof selectedExecution.error === 'object'
                        ? JSON.stringify(selectedExecution.error, null, 2)
                        : String(selectedExecution.error)}
                    </pre>
                  </div>
                )}
              </div>
            )}
          </div>
        ) : (
          // Canvas View
          <>
            {data.dsl ? (
              <div style={{ display: 'flex', gap: 16 }}>
                {/* Canvas */}
                <div style={{ flex: 1, height: 500, minHeight: 500 }}>
                  <EnhancedFlowRenderer
                    dsl={data.dsl}
                    nodeExecutions={data.nodeExecutions}
                    showExecutionStatus={true}
                    selectedNodeId={selectedNodeId}
                    readonly={true}
                    onNodeClick={(nodeId) => setSelectedNodeId(nodeId)}
                  />
                </div>

                {/* Node Detail Panel */}
                {selectedNodeId && (
                  <div
                    style={{
                      width: 320,
                      borderLeft: '1px solid #f0f0f0',
                      paddingLeft: 16,
                      overflowY: 'auto',
                    }}
                  >
                    {selectedExecution ? (
                      <>
                        <div style={{ marginBottom: 16 }}>
                          <Title level={5}>
                            {selectedExecution.nodeLabel ||
                              selectedExecution.nodeId}
                          </Title>
                          <Tag
                            color={
                              selectedExecution.status === 'COMPLETED'
                                ? 'green'
                                : selectedExecution.status === 'RUNNING'
                                  ? 'blue'
                                  : selectedExecution.status === 'FAILED'
                                    ? 'red'
                                    : 'gold'
                            }
                          >
                            {selectedExecution.status}
                          </Tag>
                        </div>

                        <Descriptions
                          column={1}
                          size="small"
                          style={{ marginBottom: 16 }}
                        >
                          <Descriptions.Item label="Node Type">
                            {selectedExecution.nodeType}
                          </Descriptions.Item>
                          <Descriptions.Item label="Started">
                            {selectedExecution.startedAt
                              ? new Date(
                                  selectedExecution.startedAt,
                                ).toLocaleString()
                              : '—'}
                          </Descriptions.Item>
                          <Descriptions.Item label="Finished">
                            {selectedExecution.finishedAt
                              ? new Date(
                                  selectedExecution.finishedAt,
                                ).toLocaleString()
                              : '—'}
                          </Descriptions.Item>
                          <Descriptions.Item label="Duration">
                            {formatDuration(
                              selectedExecution.startedAt,
                              selectedExecution.finishedAt,
                            )}
                          </Descriptions.Item>
                        </Descriptions>

                        {selectedExecution.input && (
                          <div style={{ marginBottom: 12 }}>
                            <Text strong style={{ fontSize: 12 }}>
                              Input:
                            </Text>
                            <pre
                              style={{
                                background: '#fafafa',
                                padding: 8,
                                borderRadius: 4,
                                fontSize: 11,
                                maxHeight: 150,
                                overflow: 'auto',
                              }}
                            >
                              {JSON.stringify(selectedExecution.input, null, 2)}
                            </pre>
                          </div>
                        )}

                        {selectedExecution.output && (
                          <div style={{ marginBottom: 12 }}>
                            <Text strong style={{ fontSize: 12 }}>
                              Output:
                            </Text>
                            <pre
                              style={{
                                background: '#fafafa',
                                padding: 8,
                                borderRadius: 4,
                                fontSize: 11,
                                maxHeight: 150,
                                overflow: 'auto',
                              }}
                            >
                              {JSON.stringify(
                                selectedExecution.output,
                                null,
                                2,
                              )}
                            </pre>
                          </div>
                        )}

                        {selectedExecution.error && (
                          <div style={{ marginBottom: 12 }}>
                            <Text
                              strong
                              style={{ fontSize: 12, color: '#ff4d4f' }}
                            >
                              Error:
                            </Text>
                            <pre
                              style={{
                                background: '#fff1f0',
                                padding: 8,
                                borderRadius: 4,
                                fontSize: 11,
                                color: '#ff4d4f',
                                maxHeight: 150,
                                overflow: 'auto',
                              }}
                            >
                              {typeof selectedExecution.error === 'object'
                                ? JSON.stringify(
                                    selectedExecution.error,
                                    null,
                                    2,
                                  )
                                : String(selectedExecution.error)}
                            </pre>
                          </div>
                        )}

                        {/* Approval actions */}
                        {selectedExecution.nodeType === 'approval' &&
                          selectedExecution.status === 'RUNNING' && (
                            <Space style={{ width: '100%' }}>
                              <Button
                                type="primary"
                                block
                                onClick={() =>
                                  handleApprove(selectedExecution.nodeId, true)
                                }
                                loading={actionLoading}
                              >
                                Approve
                              </Button>
                              <Button
                                danger
                                block
                                onClick={() =>
                                  handleApprove(selectedExecution.nodeId, false)
                                }
                                loading={actionLoading}
                              >
                                Reject
                              </Button>
                            </Space>
                          )}
                      </>
                    ) : selectedDslNode ? (
                      <div>
                        <div style={{ marginBottom: 16 }}>
                          <Title level={5}>{selectedDslNode.label}</Title>
                          <Tag color="default">Not Executed</Tag>
                        </div>
                        <Descriptions column={1} size="small">
                          <Descriptions.Item label="Node Type">
                            {selectedDslNode.type}
                          </Descriptions.Item>
                          <Descriptions.Item label="Status">
                            <Text type="secondary">Waiting for execution</Text>
                          </Descriptions.Item>
                        </Descriptions>
                      </div>
                    ) : null}
                  </div>
                )}
              </div>
            ) : (
              <Text type="secondary">
                Workflow DSL not available for visualization.
              </Text>
            )}
          </>
        )}
      </Card>
    </div>
  );
}
