import { PlusOutlined, MinusCircleOutlined } from '@ant-design/icons'
import {
  Button,
  Table,
  Space,
  Tag,
  Form,
  Input,
  Select,
  Typography,
  Checkbox,
  Badge,
  FormInstance,
  TableProps
} from 'antd'
import TextArea from 'antd/lib/input/TextArea'
import { useCallback, useMemo, useState } from 'react'
import { Link } from 'react-router-dom'
import useProfileContext from 'useProfileContext'

import {
  createIncident,
  listIncidents,
  useGetIncidentComponentOptions
} from 'apiClient/services/devops'
import {
  EntityIncident,
  IncidentCreateIncidentReq,
  ListIncidentsParams
} from 'apiClient/services/devops/interface'
import ModalForm from 'components/ModalForm'
import { UserSearchInput } from 'components/ResourceSearchInput/DevOps/UserSearchInput'
import { WorkspaceSearchInput } from 'components/ResourceSearchInput/TicketManager/WorkspaceSearchInput'
import { useTable, ListToolBar } from 'components/Table'
import { capitalize } from 'utils/string'

import {
  AntdIncidentCreateAdaptor,
  fallbackIncidentComponents,
  formJiraLinksToRequestValues,
  regionColors,
  statusColors,
  statusText,
  tierColors,
  calculateTTR
} from './Util'

const renderRegionCell = (_: any, record: EntityIncident) => {
  var regions = record.biz_regions?.split(' ')
  if (regions) {
    return regions
      .filter((e) => !!e)
      .map((region) => (
        <Tag color={regionColors[region] ? regionColors[region] : 'purple'}>
          {region === 'jp' ? 'Japan' : region.toUpperCase()}
        </Tag>
      ))
  } else {
    return <></>
  }
}

const renderComponentCell = (_: any, record: EntityIncident) => {
  var components = record.components?.split(' ')
  if (components) {
    return components.map((component) =>
      component ? <Tag color="blue">{component}</Tag> : <></>
    )
  } else {
    return <></>
  }
}

const renderStatusCell = (_: any, record: EntityIncident) => {
  const status = record.status
  if (status) {
    return (
      <Badge
        color={statusColors[status] ? statusColors[status] : 'grey'}
        text={statusText[status] ? statusText[status] : 'Unknown'}
      />
    )
  } else {
    return <></>
  }
}

const renderTierCell = (_: any, record: EntityIncident) => {
  var tier = record.tier?.split(' ')
  if (tier) {
    return tier.map((t) => (
      <Tag color={tierColors[t] ? tierColors[t] : 'default'}>
        {capitalize(t)}
      </Tag>
    ))
  } else {
    return <></>
  }
}

const renderTTRCell = (_: any, record: EntityIncident) => {
  if (!record.incident_start_time || !record.incident_resolve_time) return ''
  return calculateTTR(record.incident_start_time!, record.incident_resolve_time)
}

const renderActionCell = (_: any, record: EntityIncident) => (
  <Space>
    <Link to={`/incidents/${record.id}`}>Details</Link>
    {record.feishu_url && record.feishu_url.length > 0 ? (
      <>
        <br />
        <Typography.Link href={record.feishu_url} target="_blank">
          {record.feishu_url.indexOf('/chat/') > -1
            ? 'Chat Link'
            : 'Postmortem Doc'}
        </Typography.Link>
      </>
    ) : (
      <></>
    )}
  </Space>
)

type IncidentListFilters = Pick<
  ListIncidentsParams,
  'tier' | 'components' | 'biz_regions'
> & {
  status?: string
}

export default function Incidents() {
  const [open, setOpen] = useState<'edit' | 'create' | null>(null)
  const [incidentFilters, setIncidentFilters] = useState<IncidentListFilters>(
    {}
  )
  const {
    profile: { roles, userEmail }
  } = useProfileContext()
  const currUserEmail = userEmail || 'unknown@pingcap.com'
  const creatable = !!roles?.admin
  const { data: componentOptionsResp } = useGetIncidentComponentOptions({
    query: { refetchOnWindowFocus: false, refetchInterval: false }
  })
  const componentOptions =
    componentOptionsResp?.data.components ?? fallbackIncidentComponents

  const getData = useCallback(
    (params?: Partial<PageInfo>) =>
      listIncidents({
        page: params?.page,
        per_page: params?.pageSize,
        status: incidentFilters.status as ListIncidentsParams['status'],
        tier: incidentFilters.tier,
        components: incidentFilters.components,
        biz_regions: incidentFilters.biz_regions
      }),
    [incidentFilters]
  )

  const {
    dataSource,
    loading,
    reload,
    paginationProps,
    onTableChange,
    resetPageIndex
  } = useTable<ListData<EntityIncident>>(getData, [], {
    pagination: true,
    deps: [incidentFilters]
  })

  const handleTableChange: TableProps<EntityIncident>['onChange'] = (
    pagination,
    filters,
    _sorter,
    extra
  ) => {
    if (extra.action === 'filter') {
      setIncidentFilters({
        status: filters.status?.[0] as string | undefined,
        tier: filters.tier?.[0] as IncidentListFilters['tier'],
        components: filters.components?.length
          ? filters.components.map(String)
          : undefined,
        biz_regions: filters.biz_regions?.length
          ? filters.biz_regions.map(String)
          : undefined
      })
      resetPageIndex()
      return
    }

    onTableChange(pagination, {})
  }

  const renderFormFields = useCallback(
    (form: FormInstance) => {
      return (
        <IncidentModelForm
          form={form}
          isEdit={open === 'edit'}
          componentOptions={componentOptions}
        />
      )
    },
    [componentOptions, open]
  )

  const handleCreate = useCallback(
    async (payload: AntdIncidentCreateAdaptor) => {
      const req: IncidentCreateIncidentReq = {
        name: payload.name,
        status: payload.status,
        tier: payload.tier,
        components: payload.components?.join(' '),
        biz_regions: payload.biz_regions?.join(' '),
        oncallers: payload.oncallers,
        leaders: payload.leaders,
        fbowners: payload.fbowners,
        jira_issue_links: formJiraLinksToRequestValues(payload.jira_issues),
        description: payload.description,
        war_room_id: payload.war_room_id,
        need_generate_feishu: payload.need_generate_feishu
      }

      return createIncident(req).then(() => {
        setOpen(null)
        reload()
      })
    },
    [reload]
  )

  const handleCancel = useCallback(() => {
    setOpen(null)
  }, [])

  const columns = useMemo(() => {
    const dataCols = ['name'].map((s) => ({
      title: capitalize(s).replace('_', ' '),
      dataIndex: s
    }))
    return [
      {
        title: 'ID',
        dataIndex: 'id',
        width: 90,
        render: (_: any, record: EntityIncident) => (
          <Link to={`/incidents/${record.id}`}>{record.id}</Link>
        )
      },
      ...dataCols,
      {
        title: 'Created At',
        dataIndex: 'created_at'
      },
      {
        title: 'Status',
        dataIndex: 'status',
        render: renderStatusCell,
        filters: [
          {
            text: 'Ongoing',
            value: 'ongoing'
          },
          {
            text: 'Post Mortem',
            value: 'post-mortem'
          },
          {
            text: 'Under Improvement',
            value: 'under-improvement'
          },
          {
            text: 'Archived',
            value: 'archived'
          }
        ],
        filterMultiple: false,
        filteredValue: incidentFilters.status ? [incidentFilters.status] : null
      },
      {
        title: 'Incident Tier',
        dataIndex: 'tier',
        render: renderTierCell,
        filters: [
          {
            text: 'T0',
            value: 't0'
          },
          {
            text: 'T1',
            value: 't1'
          },
          {
            text: 'T2',
            value: 't2'
          },
          {
            text: 'T3',
            value: 't3'
          }
        ],
        filterMultiple: false,
        filteredValue: incidentFilters.tier ? [incidentFilters.tier] : null
      },
      {
        title: 'Biz Regions',
        dataIndex: 'biz_regions',
        render: renderRegionCell,
        filters: [
          {
            text: 'Japan',
            value: 'jp'
          },
          {
            text: 'APAC',
            value: 'apac'
          },
          {
            text: 'EMEA',
            value: 'emea'
          },
          {
            text: 'NA',
            value: 'na'
          },
          {
            text: 'ALL-DBAAS',
            value: 'all-dbaas'
          }
        ],
        filteredValue: incidentFilters.biz_regions ?? null
      },
      {
        title: 'Component(s)',
        dataIndex: 'components',
        render: renderComponentCell,
        filters: componentOptions.map((c: string) => {
          return { text: c, value: c }
        }),
        filteredValue: incidentFilters.components ?? null
      },
      {
        title: 'Time To Resolve(minute)',
        dataIndex: 'incident_start_time',
        render: renderTTRCell
      },
      {
        title: 'Action',
        dataIndex: 'action',
        render: renderActionCell
      }
    ]
  }, [componentOptions, incidentFilters])

  const actions = useMemo(
    () => [
      <Button
        disabled={!creatable}
        type="primary"
        name="register"
        icon={<PlusOutlined />}
        onClick={() => {
          setOpen('create')
        }}
      >
        Create
      </Button>
    ],
    // eslint-disable-next-line react-hooks/exhaustive-deps
    [creatable]
  )

  return (
    <>
      <ListToolBar reload={reload} actions={actions} />

      <Table
        columns={columns}
        rowKey="id"
        dataSource={dataSource}
        loading={loading}
        pagination={paginationProps}
        onChange={handleTableChange}
        size="small"
      />
      <ModalForm<AntdIncidentCreateAdaptor>
        initValues={{
          fbowners: [currUserEmail],
          need_generate_feishu: false
        }}
        visible={!!open}
        name="incident"
        title="create a new incident"
        getFields={renderFormFields}
        onSubmit={handleCreate}
        onCancel={handleCancel}
        width={600}
      />
    </>
  )
}

const IncidentModelForm = ({
  form,
  isEdit,
  componentOptions
}: {
  form: FormInstance
  isEdit?: boolean
  componentOptions: string[]
}) => {
  return (
    <>
      <Form.Item name="name" label="Incident Name">
        <Input />
      </Form.Item>
      <Form.Item name="status" label="Status">
        <Select
          style={{ width: 120 }}
          options={[
            { value: 'ongoing', label: 'Ongoing' },
            { value: 'post-mortem', label: 'Post Mortem' },
            { value: 'under-improvement', label: 'Under Improvement' },
            { value: 'archived', label: 'Archived' }
          ]}
        />
      </Form.Item>
      <Form.Item name="tier" label="Incident Tier">
        <Select
          style={{ width: 120 }}
          options={[
            { value: 't1', label: 'T1' },
            { value: 't2', label: 'T2' },
            { value: 't3', label: 'T3' }
          ]}
        />
      </Form.Item>
      <Form.Item name="biz_regions" label="Biz Regions">
        <Select
          mode="multiple"
          style={{ width: 120 }}
          options={[
            { value: 'jp', label: 'Japan' },
            { value: 'na', label: 'NA' },
            { value: 'apac', label: 'APAC' },
            { value: 'emea', label: 'EMEA' }
          ]}
        />
      </Form.Item>
      <Form.Item name="components" label="Component(s)">
        <Select
          mode="multiple"
          allowClear
          style={{ width: '100%' }}
          placeholder="Please select"
          options={componentOptions.map((c) => {
            return { label: c, value: c }
          })}
        />
      </Form.Item>
      <Form.Item name="oncallers" label="Oncaller(s)">
        <UserSearchInput mode="multiple" />
      </Form.Item>
      <Form.Item name="leaders" label="Team Leader(s)">
        <UserSearchInput mode="multiple" />
      </Form.Item>
      <Form.Item name="fbowners" label="FB Owner" style={{ width: '100%' }}>
        <UserSearchInput mode="multiple" />
      </Form.Item>
      <Form.Item name="war_room_id" label="Link War Room">
        <WorkspaceSearchInput style={{ width: '100%' }} />
      </Form.Item>
      <Form.Item name="description" label="Description">
        <TextArea></TextArea>
      </Form.Item>
      <Form.Item label="Jira Issues">
        <Form.List name="jira_issues">
          {(fields, { add, remove }, { errors }) => (
            <>
              {fields.map((field, index) => (
                <>
                  <Form.Item key={field.key}>
                    <Form.Item
                      {...field}
                      rules={[
                        {
                          required: true,
                          whitespace: true,
                          message: 'Please input a valid Jira URL'
                        }
                      ]}
                      noStyle
                    >
                      <Input style={{ width: 400 }}></Input>
                    </Form.Item>
                    <MinusCircleOutlined onClick={() => remove(field.name)} />
                  </Form.Item>
                </>
              ))}
              <Form.Item>
                <Button
                  type="dashed"
                  onClick={() => add()}
                  style={{ width: 400 }}
                  icon={<PlusOutlined />}
                >
                  Add Jira Issue
                </Button>
                <Form.ErrorList errors={errors} />
              </Form.Item>
            </>
          )}
        </Form.List>
      </Form.Item>
      <Form.Item
        name="need_generate_feishu"
        label="Generate Feishu"
        valuePropName="checked"
      >
        <Checkbox></Checkbox>
      </Form.Item>
    </>
  )
}
