import type { WorkflowPausedDetailsResponse } from '@/models/log'
import { fireEvent, render, screen } from '@testing-library/react'
import { cloneElement, isValidElement } from 'react'
import { createDocLinkMock, resolveDocLink } from '../../__tests__/i18n'
import Status from '../status'

const mockDocLink = createDocLinkMock()
const mockUseWorkflowPausedDetails = vi.fn()

vi.mock('react-i18next', () => ({
  useTranslation: () => ({
    t: (key: string, options?: Record<string, unknown>) => {
      const fullKey = options?.ns ? `${options.ns}.${key}` : key
      if (fullKey === 'workflow.nodes.common.errorHandle.partialSucceeded.tip')
        return 'There are {{num}} nodes in the process running abnormally, please go to TRACING to check the logs.'

      const params = { ...options }
      delete params.ns
      const suffix = Object.keys(params).length > 0 ? `:${JSON.stringify(params)}` : ''
      return `${fullKey}${suffix}`
    },
  }),
  Trans: ({
    i18nKey,
    values,
    components,
  }: {
    i18nKey: string
    values?: {
      num?: string | number
    }
    components?: Record<string, React.ReactNode>
  }) => {
    if (i18nKey !== 'nodes.common.errorHandle.partialSucceeded.tip')
      return <span>{i18nKey}</span>

    const tracingLink = components?.tracingLink
    const tracingNode = isValidElement(tracingLink)
      ? cloneElement(tracingLink, undefined, 'TRACING')
      : 'TRACING'

    return (
      <span>
        There are
        {' '}
        {values?.num}
        {' '}
        nodes in the process running abnormally, please go to
        {' '}
        {tracingNode}
        {' '}
        to check the logs.
      </span>
    )
  },
}))

vi.mock('@/context/i18n', () => ({
  useDocLink: () => mockDocLink,
}))

vi.mock('@/service/use-log', () => ({
  useWorkflowPausedDetails: (params: { workflowRunId: string, enabled?: boolean }) => mockUseWorkflowPausedDetails(params),
}))

const createPausedDetails = (overrides: Partial<WorkflowPausedDetailsResponse> = {}): WorkflowPausedDetailsResponse => ({
  paused_at: '2026-03-18T00:00:00Z',
  paused_nodes: [],
  ...overrides,
})

describe('Status', () => {
  beforeEach(() => {
    vi.clearAllMocks()
    mockUseWorkflowPausedDetails.mockReturnValue({ data: undefined })
  })

  it('renders the running status and loading placeholders', () => {
    render(<Status status="running" workflowRunId="run-1" />)

    expect(screen.getByText('Running')).toBeInTheDocument()
    expect(document.querySelectorAll('.bg-text-quaternary')).toHaveLength(2)
    expect(mockUseWorkflowPausedDetails).toHaveBeenCalledWith({
      workflowRunId: 'run-1',
      enabled: false,
    })
  })

  it('renders the listening label when the run is waiting for input', () => {
    render(<Status status="running" isListening workflowRunId="run-2" />)

    expect(screen.getByText('Listening')).toBeInTheDocument()
  })

  it('renders succeeded metadata values', () => {
    render(<Status status="succeeded" time={1.234} tokens={8} />)

    expect(screen.getByText('SUCCESS')).toBeInTheDocument()
    expect(screen.getByText('1.234s')).toBeInTheDocument()
    expect(screen.getByText('8 Tokens')).toBeInTheDocument()
  })

  it('renders stopped fallbacks when time and tokens are missing', () => {
    render(<Status status="stopped" />)

    expect(screen.getByText('STOP')).toBeInTheDocument()
    expect(screen.getByText('-')).toBeInTheDocument()
    expect(screen.getByText('0 Tokens')).toBeInTheDocument()
  })

  it('renders failed details and the partial-success exception tip', () => {
    render(<Status status="failed" error="Something broke" exceptionCounts={2} />)

    expect(screen.getByText('FAIL')).toBeInTheDocument()
    expect(screen.getByText('Something broke')).toBeInTheDocument()
    expect(screen.getAllByText((_, element) => element?.textContent === 'There are 2 nodes in the process running abnormally, please go to TRACING to check the logs.')).toHaveLength(2)
  })

  it('renders the partial-succeeded warning summary', () => {
    render(<Status status="partial-succeeded" exceptionCounts={3} />)

    expect(screen.getByText('PARTIAL SUCCESS')).toBeInTheDocument()
    expect(screen.getAllByText((_, element) => element?.textContent === 'There are 3 nodes in the process running abnormally, please go to TRACING to check the logs.')).toHaveLength(2)
  })

  it('opens the tracing tab when clicking the TRACING link', () => {
    const onOpenTracingTab = vi.fn()

    render(<Status status="partial-succeeded" exceptionCounts={3} onOpenTracingTab={onOpenTracingTab} />)

    fireEvent.click(screen.getByRole('link', { name: 'TRACING' }))

    expect(onOpenTracingTab).toHaveBeenCalledTimes(1)
  })

  it('renders the exception learn-more link', () => {
    render(<Status status="exception" error="Bad request" />)

    const learnMoreLink = screen.getByRole('link', { name: 'workflow.common.learnMore' })

    expect(screen.getByText('EXCEPTION')).toBeInTheDocument()
    expect(learnMoreLink).toHaveAttribute('href', resolveDocLink('/use-dify/debug/error-type'))
    expect(mockDocLink).toHaveBeenCalledWith('/use-dify/debug/error-type')
  })

  it('renders paused placeholders when pause details have not loaded yet', () => {
    render(<Status status="paused" workflowRunId="run-3" />)

    expect(screen.getByText('PENDING')).toBeInTheDocument()
    expect(screen.getByText('workflow.nodes.humanInput.log.reason')).toBeInTheDocument()
    expect(document.querySelectorAll('.bg-text-quaternary')).toHaveLength(3)
    expect(mockUseWorkflowPausedDetails).toHaveBeenCalledWith({
      workflowRunId: 'run-3',
      enabled: true,
    })
  })

  it('renders paused human-input reasons and backstage URLs', () => {
    mockUseWorkflowPausedDetails.mockReturnValue({
      data: createPausedDetails({
        paused_nodes: [
          {
            node_id: 'node-1',
            node_title: 'Need review',
            pause_type: {
              type: 'human_input',
              form_id: 'form-1',
              backstage_input_url: 'https://example.com/a',
            },
          },
          {
            node_id: 'node-2',
            node_title: 'Need review 2',
            pause_type: {
              type: 'human_input',
              form_id: 'form-2',
              backstage_input_url: 'https://example.com/b',
            },
          },
        ],
      }),
    })

    render(<Status status="paused" workflowRunId="run-4" />)

    expect(screen.getByText('workflow.nodes.humanInput.log.reasonContent')).toBeInTheDocument()
    expect(screen.getByText('workflow.nodes.humanInput.log.backstageInputURL')).toBeInTheDocument()
    expect(screen.getByRole('link', { name: 'https://example.com/a' })).toHaveAttribute('href', 'https://example.com/a')
    expect(screen.getByRole('link', { name: 'https://example.com/b' })).toHaveAttribute('href', 'https://example.com/b')
  })
})
