import {
  PlayCircleOutlined,
  ReloadOutlined,
  SafetyCertificateOutlined,
  StopOutlined
} from '@ant-design/icons'
import {
  Alert,
  Button,
  Card,
  Collapse,
  Descriptions,
  Modal,
  PageHeader,
  Progress,
  Space,
  Spin,
  Table,
  Tag,
  Typography,
  message
} from 'antd'
import type { ColumnsType } from 'antd/lib/table'
import { useEffect, useMemo, useState } from 'react'
import { useQuery } from 'react-query'
import { Link, useHistory, useParams } from 'react-router-dom'

import {
  premiumUpgradeControllerApplyPlan as applyPremiumUpgradePlan,
  premiumUpgradeControllerApplyStep as applyPremiumUpgradeStep,
  premiumUpgradeControllerCancelPlan as cancelPremiumUpgradePlan,
  premiumUpgradeControllerGetPlan as getPremiumUpgradePlan,
  premiumUpgradeControllerRetryStep as retryPremiumUpgradeStep
} from 'apiClient/services/devops'
import type {
  PremiumupgradeUpgradeStep as PremiumUpgradeStep,
  PremiumupgradeUpgradeTarget as PremiumUpgradeTarget
} from 'apiClient/services/devops/interface'
import ApprovalTable from 'components/ApprovalTable'

import {
  applyGroupName,
  componentName,
  executionModeName,
  formatDateTime,
  renderUpgradeStatus,
  TERMINAL_PLAN_STATUSES
} from './utils'

import './index.less'

const { Text } = Typography

type RouteParams = {
  planId: string
}

type StepRow = {
  key: string
  target: PremiumUpgradeTarget
  step: PremiumUpgradeStep
}

const getConfigChangeDetailPath = (changeId: number) =>
  `/confighistories/${changeId}`

const getErrorMessage = (error: unknown) => {
  const candidate = error as {
    message?: string
    response?: { data?: { errmsg?: string; message?: string } }
  }
  return (
    candidate.response?.data?.errmsg ||
    candidate.response?.data?.message ||
    candidate.message ||
    'The request could not be completed'
  )
}

const PremiumUpgradePlanDetail = () => {
  const history = useHistory()
  const { planId } = useParams<RouteParams>()
  const numericPlanId = Number(planId)
  const [actionLoading, setActionLoading] = useState('')
  const [approvalExpanded, setApprovalExpanded] = useState<boolean>()

  const planQuery = useQuery(
    ['premiumUpgradePlan', planId],
    async () => {
      const response = await getPremiumUpgradePlan(numericPlanId)
      if (!response.data.plan)
        throw new Error('The backend returned an empty plan')
      return response.data.plan
    },
    {
      refetchInterval: (data) =>
        data?.status && TERMINAL_PLAN_STATUSES.has(data.status) ? false : 10000
    }
  )

  const plan = planQuery.data
  const approvalPassed = Boolean(
    plan?.approval_status === 'APPROVED' ||
      [
        'approved',
        'running',
        'cancelling',
        'completed',
        'partial_failed',
        'failed'
      ].includes(plan?.status || '')
  )

  useEffect(() => {
    if (!plan?.approval_id) return
    setApprovalExpanded(!approvalPassed)
  }, [approvalPassed, plan?.approval_id])

  const stepRows = useMemo<StepRow[]>(
    () =>
      (plan?.targets || [])
        .flatMap((target) =>
          (target.steps || []).map((step) => ({
            key: `${target.id}/${step.id}`,
            target,
            step
          }))
        )
        .sort(
          (left, right) =>
            (left.step.sequence || 0) - (right.step.sequence || 0) ||
            (left.target.id || 0) - (right.target.id || 0) ||
            (left.step.id || 0) - (right.step.id || 0)
        ),
    [plan?.targets]
  )

  const terminalSteps = stepRows.filter((row) =>
    ['succeeded', 'failed', 'skipped', 'cancelled'].includes(
      row.step.status || ''
    )
  ).length
  const progress = stepRows.length
    ? Math.round((terminalSteps / stepRows.length) * 100)
    : 0

  const retryStep = async (stepId: number) => {
    setActionLoading(`retry-${stepId}`)
    try {
      await retryPremiumUpgradeStep(numericPlanId, stepId)
      message.success(`Step #${stepId} queued for retry`)
      await planQuery.refetch()
    } catch (error) {
      message.error(getErrorMessage(error))
    } finally {
      setActionLoading('')
    }
  }

  const applyStep = async (stepId: number) => {
    setActionLoading(`apply-step-${stepId}`)
    try {
      await applyPremiumUpgradeStep(numericPlanId, stepId)
      message.success(`ConfigurationChange for step #${stepId} started`)
      await planQuery.refetch()
    } catch (error) {
      message.error(getErrorMessage(error))
    } finally {
      setActionLoading('')
    }
  }

  const confirmApplyPlan = () => {
    if (!plan?.id) return
    Modal.confirm({
      title: `Run Premium upgrade plan #${plan.id}?`,
      content:
        'All managed ConfigurationChanges will be applied in the server-defined sequence. Later stages start only after earlier stages finish.',
      okText: 'Run Plan',
      onOk: async () => {
        setActionLoading('apply-plan')
        try {
          await applyPremiumUpgradePlan(plan.id!)
          message.success('Premium upgrade plan started')
          await planQuery.refetch()
        } catch (error) {
          message.error(getErrorMessage(error))
        } finally {
          setActionLoading('')
        }
      }
    })
  }

  const confirmCancel = () => {
    if (!plan?.id) return
    const planIdToCancel = plan.id
    Modal.confirm({
      title: `Cancel Premium upgrade plan #${plan.id}?`,
      content:
        'No new ConfigurationChanges will start. Running changes are reconciled according to their current state.',
      okText: 'Cancel Plan',
      okButtonProps: { danger: true },
      onOk: async () => {
        setActionLoading('cancel')
        try {
          await cancelPremiumUpgradePlan(planIdToCancel)
          message.success('Cancellation requested')
          await planQuery.refetch()
        } catch (error) {
          message.error(getErrorMessage(error))
        } finally {
          setActionLoading('')
        }
      }
    })
  }

  const columns: ColumnsType<StepRow> = [
    {
      title: 'Sequence',
      dataIndex: ['step', 'sequence'],
      width: 90,
      render: (sequence: number) => <Tag color="blue">{sequence}</Tag>
    },
    {
      title: 'Actual Target',
      dataIndex: 'target',
      width: 250,
      render: (target: PremiumUpgradeTarget) => (
        <Space direction="vertical" size={0}>
          <Text strong>
            {target.cluster_type} / {target.cluster_id}
          </Text>
          <Text type="secondary">
            Source: {(target.source_cluster_ids || []).join(', ') || '-'}
          </Text>
        </Space>
      )
    },
    {
      title: 'Apply Group',
      dataIndex: ['step', 'apply_group'],
      width: 190,
      render: (group: string) => <Text strong>{applyGroupName(group)}</Text>
    },
    {
      title: 'Components',
      dataIndex: ['step', 'components'],
      width: 360,
      render: (components: PremiumUpgradeStep['components']) => (
        <Space direction="vertical" size={2}>
          {(components || []).map((component) => (
            <span key={component.component}>
              <Tag>{componentName(component.component || 'unknown')}</Tag>
              <Text type="secondary">{component.from_version}</Text>
              <Text> → </Text>
              <Text strong>{component.to_version}</Text>
              {(component.from_image_tag || component.to_image_tag) && (
                <>
                  <br />
                  <Text type="secondary">Image: </Text>
                  <Text code>{component.from_image_tag || '-'}</Text>
                  <Text type="secondary"> → </Text>
                  <Text code>{component.to_image_tag || '-'}</Text>
                </>
              )}
            </span>
          ))}
        </Space>
      )
    },
    {
      title: 'ConfigurationChange',
      dataIndex: ['step', 'configuration_change_id'],
      width: 180,
      render: (changeId?: number) =>
        changeId ? (
          <Link
            rel="noopener noreferrer"
            target="_blank"
            to={getConfigChangeDetailPath(changeId)}
          >
            <Text code>#{changeId}</Text>
          </Link>
        ) : (
          <Text type="secondary">Not created</Text>
        )
    },
    {
      title: 'Status',
      dataIndex: ['step', 'status'],
      width: 170,
      render: renderUpgradeStatus
    },
    {
      title: 'Message',
      key: 'message',
      width: 300,
      render: (_, row) =>
        row.step.last_error_message || row.step.status_reason || '-'
    },
    {
      title: 'Action',
      key: 'action',
      fixed: 'right',
      width: 110,
      render: (_, row) => {
        if (
          plan?.execution_mode === 'step_by_step' &&
          row.step.status === 'waiting_manual_apply' &&
          row.step.id
        ) {
          return (
            <Button
              type="link"
              loading={actionLoading === `apply-step-${row.step.id}`}
              onClick={() => applyStep(row.step.id!)}
            >
              Apply
            </Button>
          )
        }
        return row.step.status === 'failed' &&
          !row.step.configuration_change_id &&
          row.step.id ? (
          <Button
            type="link"
            loading={actionLoading === `retry-${row.step.id}`}
            onClick={() => retryStep(row.step.id!)}
          >
            Retry
          </Button>
        ) : (
          '-'
        )
      }
    }
  ]

  if (planQuery.isLoading) {
    return (
      <div className="premium-upgrade-plan__detail-loading">
        <Spin size="large" tip="Loading Premium upgrade plan..." />
      </div>
    )
  }

  if (planQuery.isError || !plan) {
    return (
      <div className="premium-upgrade-plan-page">
        <PageHeader
          title="Premium Upgrade Plan"
          onBack={() => history.push('/premiumUpgradePlans')}
        />
        <Alert
          type="error"
          showIcon
          message="Unable to load plan"
          description={getErrorMessage(planQuery.error)}
        />
      </div>
    )
  }

  const canCancel =
    Boolean(plan.status) &&
    !TERMINAL_PLAN_STATUSES.has(plan.status!) &&
    plan.status !== 'cancelling'
  const canApplyPlan =
    plan.status === 'approved' && plan.execution_mode !== 'step_by_step'

  return (
    <div className="premium-upgrade-plan-page premium-upgrade-plan__detail-page">
      <PageHeader
        title={plan.name}
        subTitle={`Premium Upgrade Plan #${plan.id}`}
        tags={renderUpgradeStatus(plan.status)}
        onBack={() => history.push('/premiumUpgradePlans')}
        extra={[
          <Button
            key="refresh"
            icon={<ReloadOutlined />}
            loading={planQuery.isFetching}
            onClick={() => planQuery.refetch()}
          >
            Refresh
          </Button>,
          canCancel && (
            <Button
              key="cancel"
              danger
              icon={<StopOutlined />}
              loading={actionLoading === 'cancel'}
              onClick={confirmCancel}
            >
              Cancel Plan
            </Button>
          )
        ]}
      />

      {plan.last_error && (
        <Alert
          type="error"
          showIcon
          message="Plan requires attention"
          description={plan.last_error}
        />
      )}

      {canApplyPlan && (
        <Alert
          type="info"
          showIcon
          message="Approval completed — this plan is ready to run"
          description="Use Run Plan in Managed ConfigurationChanges to apply every step in the fixed sequence."
        />
      )}

      {plan.execution_mode === 'step_by_step' && plan.status === 'running' && (
        <Alert
          type="info"
          showIcon
          message="This plan requires step-by-step Apply actions"
          description="When a ConfigurationChange is ready, its row shows an Apply action. Pending later steps remain locked until the current sequence finishes."
        />
      )}

      <div className="premium-upgrade-plan__detail-grid">
        <Card size="small" title="Plan Summary">
          <Descriptions bordered size="small" column={2}>
            <Descriptions.Item label="Target Version">
              <Text strong>{plan.desired_version}</Text>
            </Descriptions.Item>
            <Descriptions.Item label="Scope">
              {plan.scope_mode === 'all_present'
                ? 'All present components'
                : 'Selected Apply Groups'}
            </Descriptions.Item>
            <Descriptions.Item label="Execution Mode">
              <Tag
                color={plan.execution_mode === 'step_by_step' ? 'cyan' : 'blue'}
              >
                {executionModeName(plan.execution_mode)}
              </Tag>
            </Descriptions.Item>
            <Descriptions.Item label="Applicant">
              {plan.applicant}
            </Descriptions.Item>
            <Descriptions.Item label="Created At">
              {formatDateTime(plan.created_at)}
            </Descriptions.Item>
            <Descriptions.Item label="Selected Clusters">
              {plan.requested_cluster_ids?.length || 0}
            </Descriptions.Item>
            <Descriptions.Item label="Actual Targets">
              {plan.targets?.length || 0}
            </Descriptions.Item>
            <Descriptions.Item label="Order Revision">
              {plan.component_order_revision}
            </Descriptions.Item>
            <Descriptions.Item label="Max Parallel Targets">
              {plan.max_parallel_targets}
            </Descriptions.Item>
            <Descriptions.Item label="Started At">
              {formatDateTime(plan.started_at)}
            </Descriptions.Item>
            <Descriptions.Item label="Reason" span={2}>
              {plan.reason}
            </Descriptions.Item>
          </Descriptions>
        </Card>

        <Card
          size="small"
          title={
            <Space>
              <SafetyCertificateOutlined /> Parent Approval
            </Space>
          }
        >
          <Space direction="vertical" size="middle" style={{ width: '100%' }}>
            <Descriptions size="small" column={1}>
              <Descriptions.Item label="Approval ID">
                {plan.approval_id ? `#${plan.approval_id}` : 'Pending creation'}
              </Descriptions.Item>
              <Descriptions.Item label="Approval Status">
                {plan.approval_status || '-'}
              </Descriptions.Item>
              <Descriptions.Item label="Manifest Hash">
                <Text code ellipsis={{ tooltip: plan.manifest_hash }}>
                  {plan.manifest_hash?.slice(0, 20) || '-'}
                </Text>
              </Descriptions.Item>
            </Descriptions>
            <div>
              <Text type="secondary">Execution progress</Text>
              <Progress percent={progress} />
            </div>
          </Space>
        </Card>
      </div>

      {plan.approval_id && (
        <Collapse
          className="premium-upgrade-plan__approval-details"
          activeKey={
            approvalExpanded ?? !approvalPassed ? ['approval-details'] : []
          }
          destroyInactivePanel
          onChange={(activeKey) =>
            setApprovalExpanded(
              Array.isArray(activeKey)
                ? activeKey.includes('approval-details')
                : activeKey === 'approval-details'
            )
          }
        >
          <Collapse.Panel
            key="approval-details"
            header={
              <Space size="small">
                <SafetyCertificateOutlined />
                <Text strong>Parent Approval Details</Text>
                <Text type="secondary">#{plan.approval_id}</Text>
                <Tag
                  color={
                    plan.approval_status === 'APPROVED'
                      ? 'success'
                      : plan.approval_status === 'PENDING'
                      ? 'gold'
                      : plan.approval_status === 'REJECTED'
                      ? 'error'
                      : 'default'
                  }
                >
                  {plan.approval_status || 'Unknown'}
                </Tag>
              </Space>
            }
          >
            <ApprovalTable id={plan.approval_id} />
          </Collapse.Panel>
        </Collapse>
      )}

      <Card
        size="small"
        title="Managed ConfigurationChanges"
        extra={
          <Space size="small">
            <Tag>{stepRows.length} Steps</Tag>
            {canApplyPlan && (
              <Button
                size="small"
                type="primary"
                icon={<PlayCircleOutlined />}
                loading={actionLoading === 'apply-plan'}
                onClick={confirmApplyPlan}
              >
                Run Plan
              </Button>
            )}
          </Space>
        }
      >
        <Table<StepRow>
          rowKey="key"
          size="small"
          columns={columns}
          dataSource={stepRows}
          pagination={false}
          scroll={{ x: 1650 }}
        />
      </Card>
    </div>
  )
}

export default PremiumUpgradePlanDetail
