import { ReloadOutlined } from '@ant-design/icons'
import {
  Alert,
  Button,
  Descriptions,
  Drawer,
  Result,
  Table,
  Typography
} from 'antd'
import type { ColumnsType } from 'antd/lib/table'
import moment from 'moment-timezone'
import type { ReactNode } from 'react'
import { useEffect, useState } from 'react'

import type { V1Agent } from 'apiClient/services/agent-gateway/interface'
import { getErrorMessage } from 'utils/error'

export interface ResourcePageProps {
  active: boolean
  agent: V1Agent
}

interface ResourceTableProps<T> extends ResourcePageProps {
  title: string
  columns: ColumnsType<T>
  records: T[]
  loading: boolean
  failed: boolean
  error: unknown
  reload: () => Promise<unknown>
  recordKey: (record: T) => string
  renderDetail: (record: T) => ReactNode
}

export function ResourceTable<T extends object>({
  active,
  agent,
  title,
  columns,
  records,
  loading,
  failed,
  error,
  reload,
  recordKey,
  renderDetail
}: ResourceTableProps<T>) {
  const [selectedKey, setSelectedKey] = useState<string>()
  const selectedRecord = records.find(
    (record) => recordKey(record) === selectedKey
  )

  useEffect(() => {
    if (!active || (!loading && !failed && !selectedRecord)) {
      setSelectedKey(undefined)
    }
  }, [active, failed, loading, selectedRecord])

  if (!agent.projectManagementEnabled) {
    return (
      <Result
        status="info"
        title="Agent is not managed"
        subTitle={`${title} are not available for this Agent instance.`}
      />
    )
  }

  return (
    <div className="agents-resources">
      <div className="agents-resource-toolbar">
        <Button
          icon={<ReloadOutlined />}
          loading={loading}
          onClick={() => void reload()}
        >
          Reload
        </Button>
      </div>
      {failed && (
        <Alert
          action={<Button onClick={() => void reload()}>Retry</Button>}
          showIcon
          type="error"
          message={`${title} could not be loaded`}
          description={getErrorMessage(error)}
        />
      )}
      <Table<T>
        columns={[
          ...columns,
          {
            title: 'Actions',
            key: 'actions',
            width: 90,
            render: (_, record) => (
              <Button
                type="link"
                onClick={() => setSelectedKey(recordKey(record))}
              >
                Detail
              </Button>
            )
          }
        ]}
        dataSource={records}
        loading={loading}
        locale={{
          emptyText: failed
            ? 'Unable to load data'
            : `No ${title.toLowerCase()} yet`
        }}
        pagination={{ defaultPageSize: 20, showSizeChanger: true }}
        rowKey={recordKey}
        size="small"
        scroll={{ x: 'max-content' }}
      />
      <Drawer
        className="agents-resource-detail"
        title={`${title === 'Routes' ? 'Route' : 'Secret'} Detail: ${
          selectedKey || ''
        }`}
        placement="right"
        width={720}
        contentWrapperStyle={{ maxWidth: '100vw' }}
        visible={active && !!selectedRecord}
        destroyOnClose
        onClose={() => setSelectedKey(undefined)}
      >
        {selectedRecord && renderDetail(selectedRecord)}
      </Drawer>
    </div>
  )
}

export function DetailFields({
  title,
  fields
}: {
  title: string
  fields: Array<[string, ReactNode]>
}) {
  return (
    <Descriptions bordered column={1} size="small" title={title}>
      {fields.map(([label, value]) => (
        <Descriptions.Item key={label} label={label}>
          {value === undefined || value === null || value === '' ? '—' : value}
        </Descriptions.Item>
      ))}
    </Descriptions>
  )
}

export function DetailJSON({
  title,
  value
}: {
  title: string
  value: unknown
}) {
  return (
    <section className="agents-resource-section">
      <Typography.Title level={5}>{title}</Typography.Title>
      <pre className="agents-resource-json">
        {value === undefined || value === null
          ? '—'
          : JSON.stringify(value, null, 2)}
      </pre>
    </section>
  )
}

export function formatResourceTime(value?: string) {
  return value
    ? moment(value).tz(moment.tz.guess()).format('YYYY-MM-DD HH:mm:ss z')
    : '—'
}
