import {
  DeleteOutlined,
  EditOutlined,
  FileTextOutlined,
  DollarOutlined,
  PlusOutlined,
  SyncOutlined
} from '@ant-design/icons'
import {
  Alert,
  Button,
  Checkbox,
  Divider,
  Form,
  Input,
  List,
  Modal,
  Select,
  Skeleton,
  Space,
  Tag,
  Tooltip,
  Typography
} from 'antd'
import TextArea from 'antd/lib/input/TextArea'
import dayjs, { Dayjs } from 'dayjs'
import utc from 'dayjs/plugin/utc'
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'

import {
  createIncidentPostMortemToDoAction,
  deleteIncidentPostMortemToDoAction,
  remediationTicketControllerCreateTicket,
  syncIncidentPostMortemToDoActionStatus,
  updateIncident,
  updateIncidentPostMortemToDoAction,
  useListIncidentPostMortemToDoActions
} from 'apiClient/services/devops'
import {
  EntityIncident,
  EntityIncidentPostMortemToDoAction,
  IncidentCreateIncidentPostMortemToDoActionReq,
  IncidentUpdateIncidentPostMortemToDoActionReq,
  IncidentUpdateIncidentReq
} from 'apiClient/services/devops/interface'
import DatePicker from 'components/DatePicker'
import ModalForm from 'components/ModalForm'
import { UserSearchInput } from 'components/ResourceSearchInput/DevOps/UserSearchInput'

import { todoActionStatusColor } from '../Util'

dayjs.extend(utc)

const POSTMORTEM_IMPORT_STATUS_IMPORTING = 'importing'
const POSTMORTEM_IMPORT_POLL_INTERVAL_MS = 30000
const JIRA_BROWSE_BASE_URL = 'https://tidb.atlassian.net/browse'
const JIRA_ISSUE_KEY_PATTERN = /\b[A-Z][A-Z0-9]+-\d+\b/
const TODO_ACTION_PRIMARY_COLUMN_WIDTH = 360
const TODO_ACTION_FIELD_COLUMN_WIDTHS: { [key: string]: number } = {
  assignees: 160,
  status: 120,
  deadline: 140,
  priority: 100,
  tcocp_created_at: 180
}

type ToDoActionFormValues = Omit<
  IncidentCreateIncidentPostMortemToDoActionReq,
  'deadline'
> & {
  deadline?: string | Dayjs | null
}

const todoActionStatusLabel: { [key: string]: string } = {
  open: 'Open',
  ongoing: 'In Progress',
  in_progress: 'In Progress',
  done: 'Done',
  noneed: 'No Need'
}

const renderBadgesForStatus = (s: string) => {
  const color = todoActionStatusColor[s] || 'default'
  return <Tag color={color}>{todoActionStatusLabel[s] || s}</Tag>
}

const todoActionPriorityColor: { [key: string]: string } = {
  P0: 'red',
  P1: 'orange',
  P2: 'blue',
  P3: 'default'
}

const todoActionPriorityOrder: { [key: string]: number } = {
  P0: 0,
  P1: 1,
  P2: 2,
  P3: 3
}

const getTodoActionPriorityRank = (
  action: EntityIncidentPostMortemToDoAction
) => {
  const priority = action.priority?.trim().toUpperCase()
  return priority
    ? todoActionPriorityOrder[priority] ?? Number.MAX_SAFE_INTEGER
    : Number.MAX_SAFE_INTEGER
}

const renderPriority = (priority?: string) => {
  if (!priority) return ''
  const value = priority.trim()
  const color = todoActionPriorityColor[value.toUpperCase()] || 'default'
  return <Tag color={color}>{value}</Tag>
}

const normalizeToDoActionPayload = (
  payload: ToDoActionFormValues
): IncidentCreateIncidentPostMortemToDoActionReq => {
  const deadline = payload.deadline
    ? dayjs(payload.deadline).startOf('day').toISOString()
    : undefined

  return {
    ...payload,
    deadline
  }
}

const renderLinkedJiraIssue = (linkedJiraIssue?: string) => {
  if (!linkedJiraIssue) return ''
  const trimmed = linkedJiraIssue.trim()
  const key = trimmed.toUpperCase().match(JIRA_ISSUE_KEY_PATTERN)?.[0]
  if (!key) return trimmed
  return (
    <Typography.Link href={`${JIRA_BROWSE_BASE_URL}/${key}`} target="_blank">
      {key}
    </Typography.Link>
  )
}

const renderTruncatedText = (text?: string) => {
  const value = text?.trim() || '-'
  return (
    <Tooltip title={value === '-' ? undefined : value}>
      <Typography.Text
        type={value === '-' ? 'secondary' : undefined}
        style={{
          display: 'block',
          maxWidth: '100%',
          overflow: 'hidden',
          textOverflow: 'ellipsis',
          whiteSpace: 'nowrap'
        }}
      >
        {value}
      </Typography.Text>
    </Tooltip>
  )
}

export default function IncidentPostMortem({
  incidentId,
  incident,
  editable,
  reload
}: {
  incidentId: string
  incident: EntityIncident
  editable: boolean
  reload: () => Promise<void>
}) {
  const defaultToDoAction = {
    title: '',
    description: '',
    deadline: null,
    persons: [],
    status: 'open'
  }

  const { data, refetch } = useListIncidentPostMortemToDoActions(
    Number(incidentId),
    1, // just a placeholder, currently this parameter is not used
    {
      query: {
        refetchOnWindowFocus: false,
        refetchInterval: false
      }
    }
  )
  const todoActions = useMemo(() => {
    if (!data?.data?.items) return []
    return data.data.items
      .map((item, index) => ({ item, index }))
      .sort((a, b) => {
        const priorityDiff =
          getTodoActionPriorityRank(a.item) - getTodoActionPriorityRank(b.item)
        return priorityDiff || a.index - b.index
      })
      .map(({ item }) => item)
  }, [data])
  const [todoActionModalOpen, setTodoActionModalOpen] = useState<boolean>(false)
  const [todoActionModalMode, setToDoActionModalMode] = useState<
    'edit' | 'create'
  >('create')
  const [editingToDoAction, setEditingToDoAction] = useState<
    EntityIncidentPostMortemToDoAction | undefined
  >(undefined)
  const [todoActionLoading, setToDoActionLoading] = useState<boolean>(false)
  const [postmortemImportLoading, setPostmortemImportLoading] =
    useState<boolean>(false)
  const isPostmortemActionImporting =
    postmortemImportLoading ||
    incident.postmortem_todo_action_import_status ===
      POSTMORTEM_IMPORT_STATUS_IMPORTING
  const wasPostmortemActionImporting = useRef<boolean>(false)

  const [form] = Form.useForm()

  useEffect(() => {
    if (!isPostmortemActionImporting) {
      if (wasPostmortemActionImporting.current) {
        wasPostmortemActionImporting.current = false
        void refetch()
      }
      return
    }
    wasPostmortemActionImporting.current = true

    if (postmortemImportLoading) {
      void refetch()
      return
    }

    const timer = window.setInterval(() => {
      void reload()
    }, POSTMORTEM_IMPORT_POLL_INTERVAL_MS)
    return () => window.clearInterval(timer)
  }, [isPostmortemActionImporting, postmortemImportLoading, refetch, reload])

  const genToDoActionItems = useCallback(
    (item: EntityIncidentPostMortemToDoAction, index: number) => {
      const contentItems = [
        {
          key: 'assignees',
          label: 'Assignees',
          content: (
            <Space size="small">
              {item.persons?.map((person) => (
                <span key={person.email || person.lark_user_id}>
                  {person.lark_user_name || person.email}
                </span>
              ))}
            </Space>
          )
        },
        {
          key: 'status',
          label: 'Status',
          content: item.status && renderBadgesForStatus(item.status)
        },
        {
          key: 'deadline',
          label: 'Deadline',
          content: item.deadline
            ? dayjs(item.deadline).format('YYYY-MM-DD')
            : ''
        },
        {
          key: 'priority',
          label: 'Priority',
          content: renderPriority(item.priority)
        },
        {
          key: 'tcocp_created_at',
          label: 'TCOCP Created (UTC)',
          content: item.tcocp_created_at
            ? dayjs.utc(item.tcocp_created_at).format('YYYY-MM-DD HH:mm')
            : ''
        }
      ]
      return (
        <List.Item
          key={index}
          actions={[
            <Tooltip title="Edit" key="edit">
              <Button
                type="text"
                size="small"
                icon={<EditOutlined />}
                onClick={() => {
                  setEditingToDoAction(item)
                  setToDoActionModalMode('edit')
                  setTodoActionModalOpen(true)
                }}
              />
            </Tooltip>,
            <Tooltip title="Delete" key="delete">
              <Button
                danger
                type="text"
                size="small"
                icon={<DeleteOutlined />}
                onClick={() => {
                  Modal.confirm({
                    title: 'Delete this TODO action?',
                    okText: 'Delete',
                    okButtonProps: { danger: true },
                    onOk: async () => {
                      try {
                        setToDoActionLoading(true)
                        await deleteIncidentPostMortemToDoAction(
                          Number(incidentId),
                          1,
                          item.id!
                        )
                        refetch()
                      } catch (e) {
                        console.log('delete failed', e)
                      } finally {
                        setToDoActionLoading(false)
                      }
                    }
                  })
                }}
              />
            </Tooltip>
          ]}
        >
          <div
            style={{
              display: 'flex',
              flex: '1 1 auto',
              minWidth: 0,
              width: '100%'
            }}
          >
            <div
              style={{
                flex: `0 0 ${TODO_ACTION_PRIMARY_COLUMN_WIDTH}px`,
                maxWidth: `${TODO_ACTION_PRIMARY_COLUMN_WIDTH}px`,
                minWidth: `${TODO_ACTION_PRIMARY_COLUMN_WIDTH}px`,
                paddingRight: '16px'
              }}
            >
              <div style={{ marginBottom: 4, whiteSpace: 'nowrap' }}>
                {renderLinkedJiraIssue(item.linked_jira_issue) || '-'}
                {item.feishu_task_id && (
                  <Tag color="blue" style={{ marginLeft: 8 }}>
                    Feishu Task
                  </Tag>
                )}
              </div>
              {renderTruncatedText(item.description || item.title)}
            </div>
            <div style={{ flex: '1 1 auto', minWidth: 0, overflowX: 'auto' }}>
              <div
                style={{
                  display: 'flex',
                  flexDirection: 'row',
                  gap: '16px',
                  minWidth: '760px'
                }}
              >
                {contentItems.map((i) => (
                  <div
                    key={i.key}
                    style={{
                      display: 'flex',
                      flex: `0 0 ${TODO_ACTION_FIELD_COLUMN_WIDTHS[i.key]}px`,
                      flexDirection: 'column',
                      minWidth: `${TODO_ACTION_FIELD_COLUMN_WIDTHS[i.key]}px`
                    }}
                  >
                    <Typography.Text type="secondary">
                      {i.label}
                    </Typography.Text>
                    <div
                      style={{
                        display: 'flex',
                        flexDirection: 'row',
                        minHeight: 24,
                        whiteSpace: 'nowrap'
                      }}
                    >
                      {i.content || '-'}
                    </div>
                  </div>
                ))}
              </div>
            </div>
          </div>
        </List.Item>
      )
    },
    [incidentId, refetch]
  )

  const handleFinish = async () => {
    try {
      const values = await form.validateFields()

      try {
        setPostmortemImportLoading(true)
        const payload: IncidentUpdateIncidentReq = {
          ...(values as IncidentUpdateIncidentReq),
          extract_postmortem_todo_actions: true
        }
        await updateIncident(incident.id || -1, payload)
        await refetch()
        await reload()
      } catch (e) {
        console.error(e)
      } finally {
        setPostmortemImportLoading(false)
      }
    } catch (err) {
      console.warn('Validate failed:', err)
    }
  }

  const TodoActionModalForm = ({ isEdit }: { isEdit: boolean }) => {
    return (
      <>
        <Form.Item
          required
          name="title"
          label="Title"
          rules={[
            { required: true, message: 'Please input todo action title!' }
          ]}
        >
          <Input></Input>
        </Form.Item>
        <Form.Item name="description" label="Description">
          <TextArea></TextArea>
        </Form.Item>
        <Form.Item name="linked_jira_issue" label="Linked Jira Issue">
          <Input></Input>
        </Form.Item>
        <Form.Item
          required
          name="deadline"
          label="Deadline"
          getValueProps={(t) => {
            return { value: t ? dayjs(t).startOf('day') : null }
          }}
          rules={[{ required: true, message: 'Please choose a deadline!' }]}
        >
          <DatePicker></DatePicker>
        </Form.Item>
        <Form.Item
          required
          name="persons"
          label="Executors"
          rules={[
            { required: true, message: 'Please add at least 1 executor!' }
          ]}
        >
          <UserSearchInput mode="multiple" />
        </Form.Item>
        <Form.Item
          required
          name="status"
          label="Status"
          rules={[
            { required: true, message: 'Please select todo action status!' }
          ]}
        >
          <Select
            options={[
              { value: 'open', label: 'Open' },
              { value: 'in_progress', label: 'In Progress' },
              { value: 'done', label: 'Done' },
              { value: 'noneed', label: 'No Need' }
            ]}
          ></Select>
        </Form.Item>
        {!isEdit && (
          <Form.Item
            name="create_feishu_task"
            label="Create Feishu Task"
            valuePropName="checked"
          >
            <Checkbox></Checkbox>
          </Form.Item>
        )}
      </>
    )
  }
  const renderTodoActionFormFields = () => {
    return <TodoActionModalForm isEdit={todoActionModalMode === 'edit'} />
  }

  const handleTodoActionCreate = async (payload: ToDoActionFormValues) => {
    return createIncidentPostMortemToDoAction(
      incident.id!,
      1,
      normalizeToDoActionPayload(payload)
    ).then(() => {
      setTodoActionModalOpen(false)
      refetch()
    })
  }

  const handleTodoActionEdit = async (payload: ToDoActionFormValues) => {
    if (!editingToDoAction) return
    return updateIncidentPostMortemToDoAction(
      incident.id!,
      1,
      editingToDoAction?.id!,
      normalizeToDoActionPayload(payload)
    ).then(() => {
      setTodoActionModalOpen(false)
      refetch()
    })
  }

  const handleTodoActionCancel = () => {
    setTodoActionModalOpen(false)
  }

  if (
    incident.feishu_url &&
    (incident.feishu_url.indexOf('/docx/') !== -1 ||
      incident.feishu_url.indexOf('/wiki/') !== -1)
  ) {
    return (
      <>
        <Typography.Title level={2}>Incident Postmortem</Typography.Title>
        <Typography.Title level={3}>Postmortem Doc</Typography.Title>
        <Typography.Link href={incident.feishu_url} target="_blank">
          <FileTextOutlined /> Post Mortem Doc
        </Typography.Link>
        <Divider />
        <div
          style={{
            display: 'flex',
            flex: 'auto',
            justifyContent: 'space-between'
          }}
        >
          <Typography.Title level={3}>ToDo Actions</Typography.Title>
          <Space>
            <Tooltip title="Sync TODO action fields from TCOCP">
              <Button
                size="small"
                disabled={isPostmortemActionImporting}
                onClick={async () => {
                  try {
                    setToDoActionLoading(true)
                    await syncIncidentPostMortemToDoActionStatus(
                      Number(incidentId),
                      1
                    )
                    refetch()
                  } catch (e) {
                    console.log('sync todo action failed', e)
                  } finally {
                    setToDoActionLoading(false)
                  }
                }}
              >
                <SyncOutlined />
                Sync TCOCP
              </Button>
            </Tooltip>
            <Tooltip title="Apply for remediation">
              <Button
                size="small"
                icon={<DollarOutlined />}
                disabled={!editable}
                onClick={() => {
                  window.open(
                    `/remediation_tickets?create=true&incident_id=${incident.id!}&incident_name=${incident.name!}`
                  )
                }}
              >
                Apply for Remediation
              </Button>
            </Tooltip>
            <Tooltip title="Create new TODO action">
              <Button
                size="small"
                type="primary"
                icon={<PlusOutlined />}
                disabled={!editable || isPostmortemActionImporting}
                onClick={() => {
                  setToDoActionModalMode('create')
                  setEditingToDoAction(undefined)
                  setTodoActionModalOpen(true)
                }}
              >
                New
              </Button>
            </Tooltip>
          </Space>
        </div>
        {isPostmortemActionImporting && (
          <Alert
            type="info"
            showIcon
            message="TODO actions are being created based on the postmortem."
            style={{ marginBottom: 16 }}
          />
        )}
        <List
          itemLayout="horizontal"
          dataSource={todoActions}
          renderItem={genToDoActionItems}
          loading={todoActionLoading || isPostmortemActionImporting}
        ></List>
        {todoActionModalMode === 'create' ? (
          <ModalForm<ToDoActionFormValues>
            visible={todoActionModalOpen}
            name="postmortem TODO action"
            title="Create new TODO action"
            initValues={defaultToDoAction}
            getFields={renderTodoActionFormFields}
            onSubmit={handleTodoActionCreate}
            onCancel={handleTodoActionCancel}
            width={600}
            destoryOnClose
          />
        ) : (
          <ModalForm<ToDoActionFormValues>
            visible={todoActionModalOpen}
            name="postmortem TODO action"
            title="Edit a TODO action"
            initValues={{
              deadline: editingToDoAction?.deadline,
              description: editingToDoAction?.description,
              id: editingToDoAction?.id,
              linked_jira_issue: editingToDoAction?.linked_jira_issue,
              persons: editingToDoAction?.persons
                ?.filter((p) => !!p && p.email)
                .map((p) => p.email!),
              status: editingToDoAction?.status,
              title: editingToDoAction?.title
            }}
            getFields={renderTodoActionFormFields}
            onSubmit={handleTodoActionEdit}
            onCancel={handleTodoActionCancel}
            width={600}
            destoryOnClose
          />
        )}
        <Divider />
        <Typography.Title level={3}>Incident Timeline</Typography.Title>
      </>
    )
  } else if (editable) {
    return (
      <>
        <Form
          initialValues={{ feishu_url: '' }}
          onFinish={handleFinish}
          form={form}
        >
          <Form.Item
            name="feishu_url"
            label="Feishu Postmortem doc url"
            rules={[
              {
                required: true,
                message: 'Please enter a valid feishu doc url'
              },
              {
                pattern: /\/(wiki|docx)\//,
                message: 'Not a valid postmortem doc url'
              }
            ]}
          >
            <Input></Input>
          </Form.Item>
          <Form.Item>
            <Button
              type="primary"
              htmlType="submit"
              loading={isPostmortemActionImporting}
            >
              Create Postmortem from Feishu postmortem doc
            </Button>
          </Form.Item>
        </Form>
      </>
    )
  } else {
    return (
      <>
        Postmortem Not Available
        <Skeleton></Skeleton>
      </>
    )
  }
}
