import { FormOutlined, HourglassOutlined } from '@ant-design/icons'
import { Card, Descriptions, Divider, Skeleton, Steps, Tag } from 'antd'
import { ReactNode } from 'react'

import {
  EntityRemediationApprovalFlow,
  EntityRemediationApprovalFlowNodeStatus,
  EntityRemediationTicket,
  EntityRemediationTicketPhase,
  EntityRemediationTicketPhaseApproval,
  EntityRemediationTicketStatus
} from 'apiClient/services/devops/interface'

import { getPhaseSequence, PhaseInstance } from './phases'
import { findTicketApprovalByID } from './utils'

interface StepItem {
  phaseInstance: PhaseInstance
  title: string
  description?: string
  icon?: ReactNode
}

const clampStepIndex = (index: number, length: number) => {
  if (length <= 0) return 0
  return Math.min(Math.max(index, 0), length - 1)
}

const shouldRenderFlowNode = (
  ticket: EntityRemediationTicket,
  phase?: EntityRemediationTicketPhase,
  status?: EntityRemediationApprovalFlowNodeStatus
) => {
  if (!phase || status === EntityRemediationApprovalFlowNodeStatus.skipped) {
    return false
  }

  if (phase === EntityRemediationTicketPhase.closed) {
    return ticket.phase === EntityRemediationTicketPhase.closed
  }

  if (
    ticket.phase === EntityRemediationTicketPhase.closed &&
    phase === EntityRemediationTicketPhase.succeed
  ) {
    return false
  }

  return true
}

const remediationStatusMeta: Partial<
  Record<EntityRemediationTicketStatus, { color: string; text: string }>
> = {
  pending: { color: 'gold', text: 'Pending' },
  approving: { color: 'processing', text: 'Approving' },
  approved: { color: 'success', text: 'Approved' },
  rejected: { color: 'error', text: 'Rejected' },
  closed: { color: 'default', text: 'Closed' }
}
const RemediationTicketSteps = function ({
  ticket,
  ticketApprovals,
  approvalFlow
}: {
  ticket: EntityRemediationTicket
  ticketApprovals?: EntityRemediationTicketPhaseApproval[]
  approvalFlow?: EntityRemediationApprovalFlow
}) {
  if (!approvalFlow) {
    return (
      <Card>
        <Skeleton active paragraph={{ rows: 4 }} />
        <Divider />
        <RemdiationTicketSummary ticket={ticket} />
      </Card>
    )
  }

  if (approvalFlow.nodes?.length) {
    const phaseSteps = extractPhaseStepsFromApprovalFlow(ticket, approvalFlow)
    const current = clampStepIndex(
      phaseSteps.findIndex(
        (step) => step.phaseInstance.name === approvalFlow.current_phase
      ),
      phaseSteps.length
    )
    const currentNode = approvalFlow.nodes.find((node) => node.current)
    const currentNodeStatus = currentNode?.status
    const status: 'wait' | 'process' | 'error' =
      currentNodeStatus === 'rejected'
        ? 'error'
        : currentNodeStatus === 'pending' ||
          currentNodeStatus === 'approving' ||
          currentNodeStatus === 'approved'
        ? 'process'
        : 'wait'

    if (phaseSteps[current]) {
      if (currentNodeStatus === 'pending' || currentNodeStatus === 'rejected') {
        phaseSteps[current].icon = <FormOutlined />
      }
      if (currentNodeStatus === 'approving') {
        phaseSteps[current].icon = <HourglassOutlined />
      }
      if (currentNodeStatus === 'rejected' && currentNode?.message) {
        phaseSteps[current].description = currentNode.message
      }
    }

    return (
      <Card>
        <Steps
          labelPlacement="vertical"
          size="small"
          current={current}
          status={status}
        >
          {phaseSteps.map((step) => {
            return (
              <Steps.Step
                title={step.title}
                description={step.description}
                icon={step.icon}
              ></Steps.Step>
            )
          })}
        </Steps>
        <Divider />
        <RemdiationTicketSummary ticket={ticket} />
      </Card>
    )
  }

  return (
    <Card>
      <Skeleton active paragraph={{ rows: 4 }} />
      <Divider />
      <RemdiationTicketSummary ticket={ticket} />
    </Card>
  )
}

const extractPhaseStepsFromApprovalFlow = (
  ticket: EntityRemediationTicket,
  approvalFlow: EntityRemediationApprovalFlow
): StepItem[] => {
  const phaseMap = new Map(
    getPhaseSequence().map((phase) => [phase.name, phase] as const)
  )

  return (approvalFlow.nodes || [])
    .filter((node) => shouldRenderFlowNode(ticket, node.phase, node.status))
    .map((node) => {
      const fallbackPhase = node.phase ? phaseMap.get(node.phase) : undefined
      const phaseInstance: PhaseInstance = fallbackPhase
        ? {
            ...fallbackPhase,
            label: node.label || fallbackPhase.label
          }
        : {
            name: node.phase as EntityRemediationTicketPhase,
            label: node.label || node.phase || 'Unknown',
            isfinal: node.phase === 'succeed' || node.phase === 'closed'
          }

      return {
        phaseInstance,
        title: phaseInstance.label,
        icon: phaseInstance.icon
      }
    })
}

const RemdiationTicketSummary = function ({
  ticket
}: {
  ticket: EntityRemediationTicket
}) {
  const statusMeta = ticket.status
    ? remediationStatusMeta[ticket.status]
    : undefined

  return (
    <Descriptions title="Remediation Summary">
      <Descriptions.Item label="Status">
        {statusMeta ? (
          <Tag color={statusMeta.color}>{statusMeta.text}</Tag>
        ) : (
          ticket.status
        )}
      </Descriptions.Item>
      <Descriptions.Item label="Org ID">{ticket.tenant}</Descriptions.Item>
      <Descriptions.Item label="Cluster ID">{ticket.cluster}</Descriptions.Item>
      <Descriptions.Item label="Business Region">
        {ticket.biz_region}
      </Descriptions.Item>
      <Descriptions.Item label="Customer">{ticket.customer}</Descriptions.Item>
      <Descriptions.Item label="Cluster Type">
        {ticket.cluster_type}
      </Descriptions.Item>
      <Descriptions.Item label="Incident ID">
        {ticket.associated_incident_id}
      </Descriptions.Item>
      <Descriptions.Item label="Month">{ticket.month}</Descriptions.Item>
      <Descriptions.Item label="Monthly Uptime Percentage">
        {ticket.monthly_uptime_percentage}
      </Descriptions.Item>
    </Descriptions>
  )
}

export { RemediationTicketSteps }
