import { Button, Drawer, Form, Input, Radio, Select, message } from 'antd'
import { EditorState, convertToRaw, ContentState } from 'draft-js'
import draftToHtml from 'draftjs-to-html'
import React, { useState } from 'react'
import { useParams } from 'react-router-dom'
import useProfileContext from 'useProfileContext'

import { listTenants, useGetOrgProjects } from 'apiClient/services/account'
import { useBulkTrigger } from 'apiClient/services/notification'
import { FormsTrigger } from 'apiClient/services/notification/interface'
import DebounceSelect from 'components/DebounceSelect/DebounceSelect'

import { orgRole, projectRole } from './const'
import { JsonVariableInput } from './JsonVariableInput'
import 'react-draft-wysiwyg/dist/react-draft-wysiwyg.css'

export const NotificationTest = ({
  editorState,
  triggerId,
  trigger
}: {
  editorState?: EditorState
  triggerId: string
  trigger: React.ReactElement
}) => {
  const [testDrawerOpen, setTestDrawerOpen] = useState(false)

  const [tenantId, setTenanId] = useState('')

  const [form] = Form.useForm<FormsTrigger>()

  const params = useParams<{ workflow_id: string }>()

  const [scope, setScope] = useState<'ORG' | 'PROJECT'>('ORG')

  const { isLoading, mutateAsync } = useBulkTrigger()

  const {
    profile: { userEmail }
  } = useProfileContext()

  const hideDrawer = () => {
    setTestDrawerOpen(false)
  }

  const handleTargetClick = () => {
    const htmlContent =
      draftToHtml(
        convertToRaw(editorState?.getCurrentContent() as ContentState)
      ) || ''
    const variables: Record<string, string> = {}
    const regex = /\{\{([^\}]+)\}\}/g
    const matches = htmlContent.match(regex)

    if (matches) {
      matches.forEach((match) => {
        const name = match.replace('{{', '').replace('}}', '')
        variables[name] = ''
      })
    }
    form.setFieldsValue({ payload: variables })
    setTestDrawerOpen(true)
  }

  const onSubmit = async (values: FormsTrigger) => {
    values.is_test = true
    values.worker_flow_id = params.workflow_id
    values.trigger_id = triggerId
    values.operator = userEmail
    values.is_send_now = true
    values.scope_type = scope
    values.tenant_id = +(values.tenant_id ?? 0)
    values.target_id_list =
      scope === 'ORG'
        ? values.target_id_list
        : values.target_id_list?.toString().split(',')
    try {
      await mutateAsync({ data: values })
      message.success('Successfully send test email')
    } catch (e) {
      console.error(e)
      message.error('Failed to send test email')
    }
  }

  const { data: projectOptions } = useGetOrgProjects(
    tenantId,
    {
      page: 1,
      page_size: 1000
    },
    {
      query: {
        enabled: !!tenantId,
        refetchInterval: false,
        refetchOnWindowFocus: false,
        select(data) {
          return data.data.items?.map((v) => ({
            value: v.id ?? '',
            label: v.name ?? ''
          }))
        }
      }
    }
  )

  const formFields = (
    <>
      <h3>Recipients</h3>
      <Radio.Group
        onChange={(e) => {
          setScope(e.target.value)
          form.resetFields(['target_id_list', 'roles', 'tenant_id'])
        }}
        value={scope}
      >
        <Radio value="ORG">Organization</Radio>
        <Radio value="PROJECT">Project</Radio>
      </Radio.Group>
      {scope === 'ORG' ? (
        <>
          <Form.Item
            label="Target Organization"
            name="target_id_list"
            rules={[
              {
                required: true,
                message: 'Target Organization is required'
              }
            ]}
          >
            <DebounceSelect
              mode="multiple"
              showSearch
              labelInValue={false}
              placeholder="Search by ID/Name/Email"
              fetchOptions={async (search: string) => {
                const data = await listTenants({
                  search,
                  status: ['active']
                })
                return (data.data.items || [])
                  .filter((v) => v.email?.includes('@pingcap.com'))
                  .map((item) => {
                    return {
                      label: `${item.name} (Org ID: ${item.id})` || '',
                      value: item.id || ''
                    }
                  })
              }}
            />
          </Form.Item>
          <Form.Item
            label="Organization Roles"
            name="roles"
            rules={[
              {
                required: true,
                message: 'Notification name is required'
              }
            ]}
          >
            <Select options={orgRole} mode="multiple" />
          </Form.Item>
        </>
      ) : (
        <>
          <Form.Item
            label="Target Organization"
            name="tenant_id"
            rules={[
              {
                required: true,
                message: 'Target Organization is required'
              }
            ]}
          >
            <DebounceSelect
              showSearch
              labelInValue={false}
              placeholder="Search by ID/Name/Email"
              fetchOptions={async (search: string) => {
                const data = await listTenants({
                  search,
                  status: ['active']
                })
                return (data.data.items || [])
                  .filter((v) => v.email?.includes('@pingcap.com'))
                  .map((item) => {
                    return {
                      label: `${item.name} (Org ID: ${item.id})` || '',
                      value: item.id || ''
                    }
                  })
              }}
            />
          </Form.Item>
          <Form.Item
            label="Target Project"
            name="target_id_list"
            rules={[
              {
                required: true,
                message: 'Project is required'
              }
            ]}
          >
            <Select options={projectOptions} mode="multiple" />
          </Form.Item>
          <Form.Item
            label="Project Roles"
            name="roles"
            rules={[
              {
                required: true,
                message: 'Notification name is required'
              }
            ]}
          >
            <Select options={projectRole} mode="multiple" />
          </Form.Item>
        </>
      )}
      <Form.Item label="Variables" name="payload">
        <JsonVariableInput />
      </Form.Item>
    </>
  )

  return (
    <>
      {React.cloneElement(trigger, {
        onClick: handleTargetClick
      })}
      <Drawer
        title="Send a test"
        width={520}
        closable={false}
        onClose={hideDrawer}
        visible={testDrawerOpen}
      >
        <Form
          form={form}
          layout="vertical"
          onFinish={onSubmit}
          onFieldsChange={(c: any[], all: []) => {
            const change = c[0]
            const name = change.name[0]
            const value = change.value
            if (!change) {
              return
            }
            if (name === 'tenant_id') {
              setTenanId(value)
            }
          }}
        >
          {formFields}
          <Button type="primary" htmlType="submit" loading={isLoading}>
            Send test
          </Button>
        </Form>
      </Drawer>
    </>
  )
}
