import { ReloadOutlined } from '@ant-design/icons'
import {
  Button,
  Card,
  Descriptions,
  Divider,
  Empty,
  Modal,
  Result,
  Space,
  Spin,
  Tag,
  message
} from 'antd'
import { useCallback, useEffect, useMemo, useState } from 'react'
import { useParams } from 'react-router-dom'

import {
  deploymentControllerCancel,
  deploymentControllerGetDeployment,
  deploymentControllerRetryApply,
  deploymentControllerStartApply,
  deploymentControllerStartPreview
} from 'apiClient/services/deployment'
import { Deployment } from 'apiClient/services/deployment/interface'
import { toLocal } from 'pages/Devops/Maintenance/Detail'

import { PhaseDisplay, scenarioLabel } from './helpers'

export default function DeploymentDetail() {
  const { deployment_id } = useParams<{ deployment_id: string }>()
  const id = useMemo(() => Number(deployment_id), [deployment_id])
  const [deployment, setDeployment] = useState<Deployment>()
  const [loading, setLoading] = useState(false)

  const fetch = useCallback(async () => {
    if (isNaN(id)) return
    try {
      setLoading(true)
      const { data } = await deploymentControllerGetDeployment(id)
      setDeployment(data.deployment ?? undefined)
    } catch (error: any) {
      message.error('Failed to load deployment')
    } finally {
      setLoading(false)
    }
  }, [id])

  useEffect(() => {
    fetch()
  }, [fetch])

  const confirmAction = (
    title: string,
    action: () => Promise<any>,
    successMsg: string
  ) => {
    Modal.confirm({
      title,
      okText: 'Confirm',
      async onOk() {
        try {
          await action()
          message.success(successMsg)
          fetch()
        } catch (error: any) {
          if (error?.response?.data) {
            Modal.error({
              title: error.response.data.errcode,
              content: error.response.data.errmsg
            })
          }
        }
      }
    })
  }

  const handleStartPreview = () => {
    confirmAction(
      'Start preview workflow?',
      () => deploymentControllerStartPreview(id),
      'Preview started'
    )
  }

  const handleStartApply = () => {
    confirmAction(
      'Start apply workflow? This will deploy to the target environment.',
      () => deploymentControllerStartApply(id),
      'Apply started'
    )
  }

  const handleRetryApply = () => {
    confirmAction(
      'Retry the failed apply?',
      () => deploymentControllerRetryApply(id),
      'Retry started'
    )
  }

  const handleCancel = () => {
    confirmAction(
      'Cancel this deployment?',
      () => deploymentControllerCancel(id),
      'Deployment canceled'
    )
  }

  const renderActions = () => {
    if (!deployment) return null
    const phase = deployment.phase
    const buttons: React.ReactNode[] = []

    if (phase === 'created' || phase === 'preview_failed') {
      buttons.push(
        <Button key="preview" type="primary" onClick={handleStartPreview}>
          Start Preview
        </Button>
      )
    }
    if (phase === 'apply_pending') {
      buttons.push(
        <Button key="apply" type="primary" onClick={handleStartApply}>
          Start Apply
        </Button>
      )
    }
    if (phase === 'apply_failed') {
      buttons.push(
        <Button key="retry" type="primary" onClick={handleRetryApply}>
          Retry Apply
        </Button>
      )
    }
    if (phase && !['apply_succeeded', 'canceled'].includes(phase)) {
      buttons.push(
        <Button key="cancel" danger onClick={handleCancel}>
          Cancel
        </Button>
      )
    }

    return buttons.length > 0 ? <Space>{buttons}</Space> : null
  }

  const renderWorkflowMeta = (
    title: string,
    meta?: Deployment['preview_meta']
  ) => {
    if (!meta) return null
    return (
      <Card title={title} size="small" style={{ marginTop: 16 }}>
        <Descriptions column={2} size="small" bordered>
          <Descriptions.Item label="Workflow">
            {meta.workflow_name}
          </Descriptions.Item>
          <Descriptions.Item label="Run ID">{meta.run_id}</Descriptions.Item>
          <Descriptions.Item label="Status">
            <Tag
              color={
                meta.status === 'success' || meta.status === 'completed'
                  ? 'green'
                  : meta.status === 'failure' || meta.status === 'failed'
                  ? 'red'
                  : meta.status === 'in_progress'
                  ? 'blue'
                  : 'default'
              }
            >
              {meta.status}
            </Tag>
          </Descriptions.Item>
          <Descriptions.Item label="Retry Count">
            {meta.retry_count || 0}
          </Descriptions.Item>
          {meta.run_url && (
            <Descriptions.Item label="Run URL" span={2}>
              <a href={meta.run_url} target="_blank" rel="noopener noreferrer">
                View on GitHub
              </a>
            </Descriptions.Item>
          )}
          {meta.summary && (
            <Descriptions.Item label="Summary" span={2}>
              {meta.summary}
            </Descriptions.Item>
          )}
        </Descriptions>
      </Card>
    )
  }

  const renderFrozenSnapshot = () => {
    const snap = deployment?.frozen_snapshot
    if (!snap) return null
    return (
      <Card title="Frozen Snapshot" size="small" style={{ marginTop: 16 }}>
        <Descriptions column={2} size="small" bordered>
          <Descriptions.Item label="Workflow">
            {snap.workflow_name}
          </Descriptions.Item>
          <Descriptions.Item label="Frozen At">
            {toLocal(snap.frozen_at)}
          </Descriptions.Item>
        </Descriptions>
        <Divider orientation="left" plain style={{ margin: '12px 0' }}>
          Params
        </Divider>
        {Object.keys(snap.params || {}).length > 0 ? (
          <Descriptions column={2} size="small" bordered>
            {Object.entries(snap.params || {}).map(([k, v]) => (
              <Descriptions.Item key={k} label={k}>
                {v}
              </Descriptions.Item>
            ))}
          </Descriptions>
        ) : (
          <Empty description="No params" image={Empty.PRESENTED_IMAGE_SIMPLE} />
        )}
        <Divider orientation="left" plain style={{ margin: '12px 0' }}>
          Workflow Inputs
        </Divider>
        {Object.keys(snap.workflow_inputs || {}).length > 0 ? (
          <Descriptions column={2} size="small" bordered>
            {Object.entries(snap.workflow_inputs || {}).map(([k, v]) => (
              <Descriptions.Item key={k} label={k}>
                {v}
              </Descriptions.Item>
            ))}
          </Descriptions>
        ) : (
          <Empty
            description="No workflow inputs"
            image={Empty.PRESENTED_IMAGE_SIMPLE}
          />
        )}
      </Card>
    )
  }

  if (isNaN(id)) {
    return <Result status="error" title="Invalid deployment ID" />
  }

  if (loading && !deployment) {
    return <Spin style={{ display: 'block', marginTop: 100 }} />
  }

  return (
    <div>
      <div
        style={{
          display: 'flex',
          justifyContent: 'space-between',
          marginBottom: 16
        }}
      >
        <h2 style={{ margin: 0 }}>Deployment #{deployment_id}</h2>
        <Space>
          {renderActions()}
          <Button icon={<ReloadOutlined />} onClick={fetch}>
            Refresh
          </Button>
        </Space>
      </div>

      <Card title="Basic Info" size="small">
        <Descriptions column={2} size="small" bordered>
          <Descriptions.Item label="ID">{deployment?.id}</Descriptions.Item>
          <Descriptions.Item label="Scenario">
            {scenarioLabel(deployment?.scenario)}
          </Descriptions.Item>
          <Descriptions.Item label="Phase">
            <PhaseDisplay phase={deployment?.phase} />
          </Descriptions.Item>
          <Descriptions.Item label="Applicant">
            {deployment?.applicant}
          </Descriptions.Item>
          <Descriptions.Item label="Created At">
            {toLocal(deployment?.created_at)}
          </Descriptions.Item>
          <Descriptions.Item label="Closed At">
            {deployment?.closed_at ? toLocal(deployment.closed_at) : '-'}
          </Descriptions.Item>
          {deployment?.approval_id && (
            <Descriptions.Item label="Approval ID">
              {deployment.approval_id}
            </Descriptions.Item>
          )}
        </Descriptions>
      </Card>

      {deployment?.params && (
        <Card title="Parameters" size="small" style={{ marginTop: 16 }}>
          {Object.keys(deployment.params).length > 0 ? (
            <Descriptions column={2} size="small" bordered>
              {Object.entries(deployment.params).map(([k, v]) => (
                <Descriptions.Item key={k} label={k}>
                  {v}
                </Descriptions.Item>
              ))}
            </Descriptions>
          ) : (
            <Empty
              description="No parameters"
              image={Empty.PRESENTED_IMAGE_SIMPLE}
            />
          )}
        </Card>
      )}

      {renderWorkflowMeta('Preview Workflow', deployment?.preview_meta)}
      {renderWorkflowMeta('Apply Workflow', deployment?.apply_meta)}
      {renderFrozenSnapshot()}
    </div>
  )
}
