import {
  CheckCircleOutlined,
  ClockCircleOutlined,
  CloseCircleOutlined,
  MinusCircleOutlined
} from '@ant-design/icons'
import {
  Button,
  Descriptions,
  Modal,
  Timeline,
  Card,
  Spin,
  Tag,
  Space,
  Tooltip
} from 'antd'
import { useEffect, useState } from 'react'

import {
  approvalControllerGetApproval,
  approvalControllerUserApprove,
  approvalControllerUserReject,
  approvalControllerAdminApprove
} from 'apiClient/services/devops'
import {
  EntityApproval,
  EntityApprovalNodeStatus,
  EntityApprovalStatus,
  EntityApprovalTaskStatus,
  EntityApprovalTask,
  EntityApprovalAdminTask
} from 'apiClient/services/devops/interface'
import { toLocal } from 'pages/Devops/Maintenance/Detail'

export default function ApprovalTable({ id }: { id: number }) {
  const [reload, setReload] = useState(false)
  const [loading, setLoading] = useState(true)
  const [approval, setApproval] = useState<EntityApproval>()
  const [permCanApprove, setPermCanApprove] = useState(false)
  const [permCanAdminApprove, setPermCanAdminApprove] = useState(false)

  useEffect(() => {
    async function fetchData() {
      setLoading(true)
      try {
        const resp = (await approvalControllerGetApproval(id)).data
        setApproval(resp.approval)
        setPermCanApprove(resp.can_approve ?? false)
        setPermCanAdminApprove(resp.can_admin_approve ?? false)
      } catch (e) {
        console.error(e)
      } finally {
        setLoading(false)
      }
    }
    fetchData()
  }, [reload, id])

  const handleAction = async (actionType: 'APPROVE' | 'REJECT') => {
    const isApprove = actionType === 'APPROVE'
    Modal.info({
      title: 'Confirmation',
      closable: true,
      content: (
        <div>
          <p>
            Are you sure to <b>{actionType}</b>?
          </p>
        </div>
      ),
      okText: 'Confirm',
      async onOk() {
        try {
          if (isApprove) await approvalControllerUserApprove(id)
          else await approvalControllerUserReject(id)

          Modal.success({
            title: 'Info',
            content: `Successfully ${isApprove ? 'Approved' : 'Rejected'}`
          })
          setReload((pre) => !pre)
        } catch (error: any) {
          Modal.error({
            title: error?.response?.data?.errcode || 'Error',
            content: error?.response?.data?.errmsg || 'Operation failed'
          })
          setReload((pre) => !pre)
        }
      }
    })
  }

  const handleAdminApprove = async () => {
    Modal.info({
      title: 'Admin Approval',
      content: 'Are you sure to Force Approve?',
      okText: 'Confirm',
      async onOk() {
        try {
          await approvalControllerAdminApprove(id)
          Modal.success({ title: 'Success', content: 'Approved by Admin' })
          setReload((pre) => !pre)
        } catch (error: any) {
          Modal.error({
            title: 'Error',
            content: error?.response?.data?.errmsg
          })
        }
      }
    })
  }

  if (loading) {
    return (
      <div
        style={{
          display: 'flex',
          justifyContent: 'center',
          alignItems: 'center',
          height: '300px'
        }}
      >
        <Spin tip="Loading..." />
      </div>
    )
  }

  return (
    <div>
      <Descriptions column={2}>
        <Descriptions.Item label="ID">{approval?.id}</Descriptions.Item>
        <Descriptions.Item label="Name">{approval?.name}</Descriptions.Item>
        <Descriptions.Item label="Status">
          <Tag color={getStatusColor(approval?.status!)}>
            {approval?.status}
          </Tag>
        </Descriptions.Item>
        <Descriptions.Item label="Template">
          {approval?.from_template}
        </Descriptions.Item>
        <Descriptions.Item label="Start Time">
          {toLocal(approval?.start_at)}
        </Descriptions.Item>
        <Descriptions.Item label="End Time">
          {toLocal(approval?.end_at)}
        </Descriptions.Item>
      </Descriptions>

      <br />

      <Card
        title="Approval Workflow"
        extra={
          <Space>
            <Button
              type="primary"
              disabled={!permCanApprove}
              onClick={() => handleAction('APPROVE')}
            >
              Approve
            </Button>
            <Button
              danger
              disabled={!permCanApprove}
              onClick={() => handleAction('REJECT')}
            >
              Reject
            </Button>
          </Space>
        }
        style={{ width: '100%' }}
      >
        <Timeline mode="left">
          {approval?.levels?.map((level, index) => {
            return (
              <Timeline.Item key={level.level || index} color="blue">
                <div style={{ marginBottom: 8, color: '#888' }}>
                  Level {level.level}
                </div>

                <div
                  style={{
                    display: 'flex',
                    flexWrap: 'wrap',
                    gap: '16px',
                    alignItems: 'flex-start'
                  }}
                >
                  {level.nodes?.map((node, nodeIndex) => (
                    <ApprovalNodeCard
                      key={nodeIndex}
                      title={node.name || 'Approval Node'}
                      status={node.status}
                      tasks={node.tasks}
                      backupTasks={node.backup_tasks}
                    />
                  ))}
                </div>
              </Timeline.Item>
            )
          })}
        </Timeline>
      </Card>

      <br />

      {permCanAdminApprove &&
        approval?.admin_tasks &&
        approval.admin_tasks.length > 0 && (
          <Card
            title="Admin Control"
            extra={
              <Button type="primary" onClick={handleAdminApprove}>
                Force Approve
              </Button>
            }
          >
            <GenericNodeCard
              title="Admin Administrators"
              status={approval?.status as unknown as EntityApprovalNodeStatus}
              tasks={approval?.admin_tasks}
            />
          </Card>
        )}
    </div>
  )
}

const TaskList = ({
  tasks
}: {
  tasks?: (EntityApprovalTask | EntityApprovalAdminTask)[]
}) => (
  <div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>
    {tasks?.map((task, i) => (
      <div
        key={i}
        style={{
          display: 'flex',
          flexDirection: 'column',
          paddingBottom: '8px',
          borderBottom:
            i === (tasks.length || 0) - 1 ? 'none' : '1px solid #f0f0f0'
        }}
      >
        <div
          style={{
            display: 'flex',
            justifyContent: 'space-between',
            alignItems: 'center',
            marginBottom: '2px'
          }}
        >
          <Tooltip title={task.user_email}>
            <span
              style={{
                fontWeight: 500,
                fontSize: '13px',
                whiteSpace: 'nowrap',
                overflow: 'hidden',
                textOverflow: 'ellipsis',
                maxWidth: '85%'
              }}
            >
              {task.user_email}
            </span>
          </Tooltip>
          {getStatusIcon(task.status!)}
        </div>

        <div style={{ fontSize: '11px', color: '#999' }}>
          {toLocal((task as EntityApprovalTask).start_at ?? undefined)}
          <span style={{ margin: '0 4px' }}>~</span>
          {toLocal(task.end_at)}
        </div>
      </div>
    ))}
    {(!tasks || tasks.length === 0) && (
      <span style={{ color: '#ccc', fontSize: '12px' }}>No Approvers</span>
    )}
  </div>
)

interface ApprovalNodeCardProps {
  title: string
  status?: string
  tasks?: EntityApprovalTask[]
  backupTasks?: EntityApprovalTask[]
}

const ApprovalNodeCard = ({
  title,
  status,
  tasks,
  backupTasks
}: ApprovalNodeCardProps) => {
  const statusColor = getStatusColor(status!)
  const isPending = status === EntityApprovalNodeStatus.PENDING
  const hasBackup = backupTasks && backupTasks.length > 0

  return (
    <Card
      size="small"
      title={
        <div
          style={{
            display: 'flex',
            justifyContent: 'space-between',
            alignItems: 'center'
          }}
        >
          <span>{title}</span>
          {status && <Tag color={statusColor}>{status}</Tag>}
        </div>
      }
      style={{
        width: hasBackup ? 580 : 300,
        borderColor: isPending ? '#1890ff' : '#f0f0f0',
        boxShadow: isPending ? '0 2px 8px rgba(0,0,0,0.09)' : 'none'
      }}
      headStyle={{ backgroundColor: '#fafafa', fontSize: '14px' }}
      bodyStyle={{ padding: '8px 12px' }}
    >
      <div style={{ display: 'flex', gap: '16px' }}>
        <div style={{ flex: 1, minWidth: 0 }}>
          <div
            style={{
              fontSize: '12px',
              color: '#888',
              marginBottom: '6px',
              fontWeight: 500
            }}
          >
            Approvers
          </div>
          <div style={{ fontSize: '11px', color: '#aaa', marginBottom: '8px' }}>
            Notified via Lark automatically
          </div>
          <TaskList tasks={tasks} />
        </div>

        {hasBackup && (
          <>
            <div
              style={{
                width: '1px',
                backgroundColor: '#f0f0f0',
                alignSelf: 'stretch'
              }}
            />
            <div style={{ flex: 1, minWidth: 0 }}>
              <div
                style={{
                  fontSize: '12px',
                  color: '#888',
                  marginBottom: '6px',
                  fontWeight: 500
                }}
              >
                Backup Approvers
              </div>
              <div
                style={{
                  fontSize: '11px',
                  color: '#aaa',
                  marginBottom: '8px'
                }}
              >
                Not notified, but eligible to approve
              </div>
              <TaskList tasks={backupTasks} />
            </div>
          </>
        )}
      </div>
    </Card>
  )
}

interface GenericNodeCardProps {
  title: string
  status?: string
  tasks?: (EntityApprovalTask | EntityApprovalAdminTask)[]
  width?: string | number
}

const GenericNodeCard = ({
  title,
  status,
  tasks,
  width = 300
}: GenericNodeCardProps) => {
  const statusColor = getStatusColor(status!)
  const isPending =
    status === EntityApprovalNodeStatus.PENDING ||
    status === EntityApprovalStatus.PENDING

  return (
    <Card
      size="small"
      title={
        <div
          style={{
            display: 'flex',
            justifyContent: 'space-between',
            alignItems: 'center'
          }}
        >
          <span>{title}</span>
          {status && <Tag color={statusColor}>{status}</Tag>}
        </div>
      }
      style={{
        width: width,
        borderColor: isPending ? '#1890ff' : '#f0f0f0',
        boxShadow: isPending ? '0 2px 8px rgba(0,0,0,0.09)' : 'none'
      }}
      headStyle={{ backgroundColor: '#fafafa', fontSize: '14px' }}
      bodyStyle={{ padding: '8px 12px' }}
    >
      <TaskList tasks={tasks} />
    </Card>
  )
}

const getStatusIcon = (status: string) => {
  switch (status) {
    case EntityApprovalTaskStatus.APPROVED:
      return <CheckCircleOutlined style={{ color: 'green' }} />
    case EntityApprovalTaskStatus.REJECTED:
      return <CloseCircleOutlined style={{ color: 'red' }} />
    case EntityApprovalTaskStatus.PENDING:
      return <ClockCircleOutlined style={{ color: 'orange' }} />
    default:
      return <MinusCircleOutlined style={{ color: '#d9d9d9' }} />
  }
}

const getStatusColor = (status: string) => {
  switch (status) {
    case EntityApprovalStatus.PENDING:
    case EntityApprovalNodeStatus.PENDING:
    case EntityApprovalTaskStatus.PENDING:
      return 'orange'

    case EntityApprovalStatus.APPROVED:
    case EntityApprovalNodeStatus.APPROVED:
    case EntityApprovalTaskStatus.APPROVED:
      return 'green'

    case EntityApprovalStatus.REJECTED:
    case EntityApprovalNodeStatus.REJECTED:
    case EntityApprovalTaskStatus.REJECTED:
      return 'red'

    case EntityApprovalStatus.CANCELED:
    case EntityApprovalNodeStatus.CANCELED:
    case EntityApprovalTaskStatus.Done:
      return 'grey'

    default:
      return 'blue'
  }
}
