import { PlusOutlined } from '@ant-design/icons'
import {
  Alert,
  Button,
  Space,
  Table,
  Typography,
  FormInstance,
  Form,
  Input,
  Select,
  message
} from 'antd'
import { AxiosError } from 'axios'
import { useCallback, useEffect, useMemo, useState } from 'react'
import { Link } from 'react-router-dom'

import {
  getCluster,
  getIncident,
  getTenant,
  listIncidents,
  remediationTicketControllerCreateTicket,
  remediationTicketControllerListTickets
} from 'apiClient/services/devops'
import {
  EntityIncident,
  EntityRemediationTicket,
  EntityRemediationTicketClusterType,
  TenantTenantRegion
} from 'apiClient/services/devops/interface'
import ModalForm from 'components/ModalForm'
import { ListToolBar, useTable } from 'components/Table'

import { getPhaseLabel } from './RemediationTicketDetail/phases'

interface CreateYearMonth {
  year: string
  month: string
}

interface CreateFormFields {
  biz_region?: string
  cluster_id?: string
  cluster_type?: EntityRemediationTicketClusterType
  customer?: string
  incident_id?: number
  incident_name?: string
  tenant_id?: string
  year_month?: CreateYearMonth
}

const renderCreateTicketFormFields = (
  formInstance: FormInstance,
  incidents: EntityIncident[],
  incidentOptionsLoading: boolean,
  lockIncident: boolean
) => {
  const updateClusterInfo = async (event: any) => {
    try {
      const cluster = (await getCluster(event.target.value)).data
      const tenant = (await getTenant(cluster.tenant_id!)).data

      var clusterType: string = ''
      if (cluster.deploy_type === 'DEPLOY_TYPE_SERVERLESS') {
        clusterType = EntityRemediationTicketClusterType.serverless
      } else {
        const components = cluster.cluster_components
        if (components?.tidb?.replicas && components.tidb.replicas === 1) {
          clusterType = EntityRemediationTicketClusterType.dedicated_single_tidb
        } else if (components?.tidb?.replicas && components.tidb.replicas > 1) {
          clusterType = EntityRemediationTicketClusterType.dedicated_multi_tidb
        }
      }

      formInstance.setFieldsValue({
        tenant_id: cluster.tenant_id,
        biz_region: tenant.region,
        cluster_type: clusterType
      })
    } catch (e) {
      formInstance.setFieldsValue({
        tenant_id: undefined,
        biz_region: undefined,
        cluster_type: undefined
      })
      console.log(
        'get cluster failed',
        'cluster_id',
        event.target.value,
        'error',
        e
      )
    }
  }

  const incidentOptions = incidents
    .filter((incident) => incident.id)
    .map((incident) => ({
      value: incident.id!,
      label: `#${incident.id} ${incident.name || ''}`,
      incident,
      searchText: `${incident.id} ${incident.name || ''}`
    }))

  return (
    <>
      <Form.Item
        name="incident_id"
        label="Incident ID"
        rules={[{ required: true }]}
        shouldUpdate
      >
        {lockIncident ? (
          <Input style={{ width: 200 }} disabled />
        ) : (
          <Select
            showSearch
            loading={incidentOptionsLoading}
            options={incidentOptions}
            optionFilterProp="searchText"
            filterOption={(input, option) =>
              (option?.searchText || '')
                .toString()
                .toLowerCase()
                .includes(input.toLowerCase())
            }
            onChange={(_, option: any) => {
              formInstance.setFieldsValue({
                incident_name: option?.incident?.name
              })
            }}
            placeholder="Search incident ID"
            style={{ width: 300 }}
          />
        )}
      </Form.Item>
      <Form.Item name="incident_name" label="Incident Name">
        <Input style={{ width: 300 }} disabled />
      </Form.Item>
      <Form.Item label="Month" required>
        <Input.Group compact>
          <Form.Item name={['year_month', 'year']} rules={[{ required: true }]}>
            <Select
              options={[
                {
                  value: '2023',
                  label: '2023'
                },
                {
                  value: '2024',
                  label: '2024'
                },
                {
                  value: '2025',
                  label: '2025'
                },
                {
                  value: '2026',
                  label: '2026'
                }
              ]}
              style={{ width: 100 }}
            />
          </Form.Item>
          <Form.Item
            name={['year_month', 'month']}
            rules={[{ required: true }]}
          >
            <Select
              options={[...Array(12).keys()].map((i) => {
                return { value: (i + 1).toString(), label: (i + 1).toString() }
              })}
              style={{ width: 70 }}
            />
          </Form.Item>
        </Input.Group>
      </Form.Item>
      <Form.Item name="customer" label="Customer Name">
        <Input style={{ width: 200 }} />
      </Form.Item>
      <Form.Item
        name="cluster_id"
        label="Cluster ID"
        rules={[{ required: true }]}
        required
      >
        <Input onChange={updateClusterInfo} style={{ width: 200 }} />
      </Form.Item>
      <Form.Item
        name="biz_region"
        label="Biz Region"
        rules={[{ required: true }]}
        shouldUpdate={(prevValues: any, currentValues: any) =>
          prevValues.biz_region !== currentValues.biz_region
        }
      >
        <Input disabled style={{ width: 200 }} />
      </Form.Item>
      <Form.Item
        name="tenant_id"
        label="Tenant ID"
        rules={[{ required: true }]}
        shouldUpdate={(prevValues: any, currentValues: any) =>
          prevValues.tenant_id !== currentValues.tenant_id
        }
      >
        <Input disabled style={{ width: 200 }} />
      </Form.Item>
      <Form.Item
        name="cluster_type"
        label="Cluster Type"
        rules={[{ required: true }]}
      >
        <Select
          disabled
          options={[
            {
              value: EntityRemediationTicketClusterType.dedicated_multi_tidb,
              label: 'Multiple TiDB Nodes Dedicated Tier'
            },
            {
              value: EntityRemediationTicketClusterType.dedicated_single_tidb,
              label: 'Single TiDB Node Dedicated Tier'
            },
            {
              value: EntityRemediationTicketClusterType.serverless,
              label: 'Serverless Tier'
            }
          ]}
          style={{ width: 200 }}
        />
      </Form.Item>
    </>
  )
}

export default function RemediationTickets() {
  // list helper functions
  const renderAssociatedTicketCell = useCallback(
    (_: any, record: EntityRemediationTicket) =>
      record.associated_incident_id && (
        <Link to={`/incidents/${record.associated_incident_id}`}>
          Incident #{record.associated_incident_id}
        </Link>
      ),
    []
  )

  const renderActionCell = useCallback(
    (_: any, record: EntityRemediationTicket) => (
      <Space>
        <Link to={`/remediation_tickets/${record.id}`}>Details</Link>
        {record.report_link && record.report_link.length > 0 ? (
          <>
            <br />
            <Typography.Link href={record.report_link} target="_blank">
              Incident Report
            </Typography.Link>
          </>
        ) : (
          <></>
        )}
      </Space>
    ),
    []
  )

  const renderPhaseCell = useCallback(
    (_: any, record: EntityRemediationTicket) =>
      getPhaseLabel(record.phase) || record.phase,
    []
  )

  const columns = useMemo(() => {
    return [
      {
        title: 'ID',
        dataIndex: 'id'
      },
      {
        title: 'Phase',
        dataIndex: 'phase',
        render: renderPhaseCell
      },
      {
        title: 'Associated Incident',
        dataIndex: 'associated_incident_id',
        render: renderAssociatedTicketCell
      },
      {
        title: 'Cluster ID',
        dataIndex: 'cluster'
      },
      {
        title: 'Action',
        dataIndex: 'action',
        render: renderActionCell
      }
    ]
  }, [renderPhaseCell, renderActionCell, renderAssociatedTicketCell])

  // page states
  const [modalOpen, setModalOpen] = useState<boolean>(false)
  const [listRequestError, setListRequestError] = useState<string>()
  const [incidents, setIncidents] = useState<EntityIncident[]>([])
  const [incidentOptionsLoading, setIncidentOptionsLoading] =
    useState<boolean>(false)

  // params from url query
  const params = new URLSearchParams(window.location.search)
  const create = params.get('create')
  const incidentId = Number(params.get('incident_id'))
  const incidentName =
    params.get('incident_name') === null
      ? undefined
      : params.get('incident_name')
  const lockIncident = create === 'true' && !!incidentId

  // states
  const getData = async (params?: Partial<PageInfo>) => {
    const response = await remediationTicketControllerListTickets({})

    console.log('[RemediationTickets] list response', {
      status: response.status,
      data: response.data,
      params
    })

    if (
      !response.data ||
      !Array.isArray(response.data.items) ||
      typeof response.data.total !== 'number'
    ) {
      console.error(
        '[RemediationTickets] unexpected list response payload',
        response
      )
    }

    setListRequestError(undefined)
    return response
  }
  const { dataSource, loading, reload, onTableChange } = useTable<
    ListData<EntityRemediationTicket>
  >(getData, [], {
    pagination: true,
    onRequestError: (error) => {
      const axiosError = error as AxiosError<any>
      const responseData = axiosError.response?.data
      const errorMessage =
        responseData?.errmsg ||
        responseData?.message ||
        axiosError.message ||
        'Unknown request error'

      console.error('[RemediationTickets] list request failed', {
        message: errorMessage,
        status: axiosError.response?.status,
        data: responseData
      })

      setListRequestError(errorMessage)
      message.error(`Failed to load remediation tickets: ${errorMessage}`)
    }
  })

  const sortedDataSource = useMemo(
    () =>
      [...(dataSource || [])].sort(
        (a, b) => Number(b.id || 0) - Number(a.id || 0)
      ),
    [dataSource]
  )

  // effetcs
  useEffect(() => {
    setModalOpen(create === 'true')
  }, [create])

  useEffect(() => {
    if (!modalOpen) {
      return
    }

    async function loadIncidents() {
      try {
        setIncidentOptionsLoading(true)
        const resp = await listIncidents({})
        setIncidents(resp.data.items || [])
      } catch (error) {
        message.error('Failed to load incidents')
      } finally {
        setIncidentOptionsLoading(false)
      }
    }

    loadIncidents()
  }, [modalOpen])

  // submitter functions
  const handleCreate = async (formFields: CreateFormFields) => {
    const req = {
      biz_region: formFields.biz_region! as TenantTenantRegion,
      cluster_id: formFields.cluster_id!,
      cluster_type: formFields.cluster_type!,
      customer: formFields.customer!,
      incident_id: Number(formFields.incident_id!),
      tenant_id: formFields.tenant_id!,
      month: formFields.year_month!.year + '/' + formFields.year_month!.month
    }

    await remediationTicketControllerCreateTicket(req)
    setModalOpen(false)
    reload()
  }

  const incidentOptions = useMemo(() => {
    if (!incidentId || !incidentName) {
      return incidents
    }
    if (incidents.some((incident) => incident.id === incidentId)) {
      return incidents
    }
    return [
      {
        id: incidentId,
        name: incidentName
      },
      ...incidents
    ]
  }, [incidentId, incidentName, incidents])

  // main logic
  return (
    <>
      <ListToolBar
        title="Customer Remediation Tickets"
        reload={reload}
        actions={[
          <Button
            type="primary"
            icon={<PlusOutlined />}
            onClick={() => setModalOpen(true)}
          >
            Create Remediation
          </Button>
        ]}
      />
      {listRequestError ? (
        <Alert
          showIcon
          type="error"
          style={{ marginBottom: 16 }}
          message="Failed to load remediation tickets"
          description={listRequestError}
        />
      ) : null}
      <Table
        columns={columns}
        rowKey="id"
        dataSource={sortedDataSource}
        loading={loading}
        //pagination={paginationProps}
        onChange={onTableChange}
        size="small"
      />
      <ModalForm<CreateFormFields>
        initValues={{
          incident_id: incidentId,
          incident_name: incidentName!
        }}
        visible={!!modalOpen}
        name="remediation ticket"
        title="Create a remediation ticket"
        getFields={(formInstance) =>
          renderCreateTicketFormFields(
            formInstance!,
            incidentOptions,
            incidentOptionsLoading,
            lockIncident
          )
        }
        onSubmit={handleCreate}
        onCancel={() => {
          setModalOpen(false)
        }}
      />
    </>
  )
}
