import { UploadOutlined } from '@ant-design/icons'
import {
  Button,
  Col,
  Row,
  Tabs,
  Input,
  Form,
  message,
  Select,
  Upload,
  Radio,
  DatePicker,
  Tooltip
} from 'antd'
import { RcFile } from 'antd/lib/upload'
import { EditorState, convertToRaw, ContentState } from 'draft-js'
import draftToHtml from 'draftjs-to-html'
import htmlToDraft from 'html-to-draftjs'
import moment, { Moment, utc } from 'moment'
import Papa from 'papaparse'
import { useState } from 'react'
import { Editor } from 'react-draft-wysiwyg'
import { useHistory, useParams } from 'react-router-dom'
import useProfileContext from 'useProfileContext'

import { listTenants } from 'apiClient/services/account'
import {
  createNotificationWorkflow,
  updateNotificationWorkflow,
  useBroadcastTriggerAuth,
  useGetWorkflowDetail
} from 'apiClient/services/notification'
import {
  FormsTrigger,
  FormsWorkflow
} from 'apiClient/services/notification/interface'
import DebounceSelect from 'components/DebounceSelect/DebounceSelect'

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

const enum TabKeyEnum {
  Edit = 'edit',
  Schedule = 'schedule'
}

export type FormType = FormsWorkflow & FormsTrigger

export default function NotificationDetail() {
  const [activeTab, setActiveTab] = useState(TabKeyEnum.Edit)

  const [saveLoading, setSaveLoading] = useState<boolean>(false)

  const [orgType, setOrgType] = useState<'target' | 'all'>('target')

  const [isSendNow, setIsSendNow] = useState(false)

  const [formValues, setFormValues] = useState<FormType>()

  const [editorState, setEditorState] = useState<EditorState>()

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

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

  const history = useHistory()

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

  useGetWorkflowDetail(params.workflow_id, {
    query: {
      enabled: !!params.workflow_id,
      refetchOnWindowFocus: false,
      refetchInterval: false,
      refetchIntervalInBackground: false,
      onSuccess: (data) => {
        const contentBlock = htmlToDraft(data.data.in_app_content ?? '')
        const contentState = ContentState.createFromBlockArray(
          contentBlock.contentBlocks
        )
        const editorState = EditorState.createWithContent(contentState)
        setEditorState(editorState)
        form.setFieldsValue(data.data)
        setFormValues(data.data)
      }
    }
  })

  const { data: authData, isLoading } = useBroadcastTriggerAuth(
    userEmail || '',
    {
      query: {
        enabled: !!params.workflow_id,
        refetchOnWindowFocus: false,
        refetchInterval: false,
        refetchIntervalInBackground: false
      }
    }
  )

  const handleUpload = (file: RcFile) => {
    Papa.parse(file, {
      complete: (results) => {
        form.setFieldsValue({
          target_id_list: results.data.map((v: [string]) => v[0])
        })
      },
      skipEmptyLines: true
    })
  }

  const onSwitchTab = async (key: string) => {
    if (key === TabKeyEnum.Schedule) {
      try {
        await form.validateFields()
        setActiveTab(key)
      } catch (err) {
        console.warn('Validate failed:', err)
      }
    } else if (key === TabKeyEnum.Edit) {
      setActiveTab(key)
    }
  }

  const onSave = async (values: FormType) => {
    setSaveLoading(true)
    const workerFlowId = form.getFieldValue('worker_flow_id')
    values.operator = userEmail
    values.schedule_time = transfor2Utc(moment(values.schedule_time)).toString()
    values.in_app_content =
      draftToHtml(
        convertToRaw(editorState?.getCurrentContent() as ContentState)
      ) || ''
    try {
      if (workerFlowId) {
        await updateNotificationWorkflow(values)
      } else {
        const resp = await createNotificationWorkflow(values)
        message.success('Successfully save template')
        history.push(`/notification/${resp.data.worker_flow_id}`)
      }
    } catch (e) {
      console.error(e)
      message.error('Failed to save template ')
    } finally {
      setSaveLoading(false)
    }
  }

  const topButton = (
    <div
      style={{
        display: 'flex',
        justifyContent: 'space-between',
        alignItems: 'center',
        marginBottom: '20px',
        gap: '12px'
      }}
    >
      <Button
        type="primary"
        htmlType="submit"
        loading={saveLoading}
        disabled={activeTab === TabKeyEnum.Schedule}
      >
        Save
      </Button>
      <div style={{ display: 'flex', alignItems: 'center' }}>
        <div>Notification ID:</div>
        <Form.Item
          name="worker_flow_id"
          style={{ display: 'none' }}
        ></Form.Item>
        <Tooltip title={form.getFieldValue('trigger_id')}>
          <Form.Item name="trigger_id" style={{ margin: '0 0 0 12px' }}>
            <Input disabled />
          </Form.Item>
        </Tooltip>
        <div style={{ marginLeft: '24px' }}>Notification Subject:</div>
        <Form.Item
          name="worker_flow_name"
          style={{ margin: '0 0 0 12px' }}
          rules={[
            {
              required: activeTab === TabKeyEnum.Edit,
              message: 'Notification name is required'
            },
            {
              max: 65,
              message: 'The maximum length of the subject is 65'
            }
          ]}
        >
          <Input placeholder="Maximum length is 65" />
        </Form.Item>
      </div>
      {activeTab === TabKeyEnum.Edit ? (
        <NotificationTest
          triggerId={formValues?.trigger_id || ''}
          editorState={editorState}
          trigger={
            <Button
              style={{ marginRight: '16px' }}
              disabled={!formValues?.trigger_id}
            >
              Send test notification
            </Button>
          }
        />
      ) : (
        <NotificationSchedule
          form={form}
          editorState={editorState}
          orgType={orgType}
          trigger={
            <Button type="primary">
              Review and {isSendNow ? 'Send' : 'Schedule'}
            </Button>
          }
          onSave={onSave}
        />
      )}
    </div>
  )

  const editPanel = (
    <Form.Item
      name="in_app_content"
      rules={[
        {
          required: true,
          message: 'Template is required'
        }
      ]}
    >
      <Editor
        editorState={editorState}
        toolbar={{
          options: ['list', 'link', 'remove'],
          link: {
            defaultTargetOption: '_blank',
            linkCallback: (a: {}) => a
          }
        }}
        editorStyle={{ minHeight: 300 }}
        onEditorStateChange={setEditorState}
      />
    </Form.Item>
  )

  const subjectAndType = (
    <Row style={{ width: '100%' }} gutter={16}>
      <Col span={12}>
        <Form.Item
          name="subject"
          label="Notification Abstract"
          rules={[
            {
              required: true,
              message: 'Notification Abstract is required'
            },
            {
              max: 150,
              message: 'The maximum length of the Abstract is 150'
            }
          ]}
        >
          <Input placeholder="Maximum length is 150" />
        </Form.Item>
      </Col>
      <Col span={12}>
        <Form.Item
          name="notification_group"
          label="Type"
          rules={[
            {
              required: true,
              message: 'Type is required'
            }
          ]}
        >
          <Select options={messageType} />
        </Form.Item>
      </Col>
    </Row>
  )

  const recipients = (
    <Col span={8} offset={4}>
      <h3>Recipients</h3>
      <Form.Item
        rules={[
          {
            required: activeTab === TabKeyEnum.Schedule && orgType === 'target',
            message: 'Target Organizations is required'
          }
        ]}
        label={
          <Radio.Group
            onChange={(e) => {
              setOrgType(e.target.value)
              form.validateFields()
            }}
            value={orgType}
          >
            <Radio value="target">Target Organizations</Radio>
            {authData?.data && <Radio value="all">All Organizations</Radio>}
          </Radio.Group>
        }
        name="target_id_list"
      >
        {orgType === 'target' && (
          <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>
      {orgType === 'target' && (
        <Form.Item label="Upload Organization id">
          <Upload
            name={'file'}
            accept="application/csv"
            multiple={false}
            fileList={[]}
            beforeUpload={handleUpload}
          >
            <Button icon={<UploadOutlined />}>Click to upload</Button>
          </Upload>
        </Form.Item>
      )}
      <Form.Item
        label="Organization Roles"
        name="roles"
        rules={[
          {
            required: activeTab === TabKeyEnum.Schedule && orgType === 'target',
            message: 'Organization Roles is required'
          }
        ]}
      >
        <Select options={orgRole} mode="multiple" />
      </Form.Item>
      <Form.Item label="Variables" name="payload">
        <JsonVariableInput />
      </Form.Item>
    </Col>
  )

  const sendingOptions = (
    <Col span={8} offset={4}>
      <h3>Sending options</h3>
      <Form.Item name="is_send_now" label="Type">
        <Radio.Group onChange={(e) => setIsSendNow(e.target.value)}>
          <Radio value={true}>Send now</Radio>
          <Radio value={false}>Schedule for later</Radio>
        </Radio.Group>
      </Form.Item>
      <Form.Item
        name="schedule_time"
        label="Time(UTC Time)"
        rules={[
          {
            validator: (rule, value: Moment) => {
              if (isSendNow || activeTab === TabKeyEnum.Edit)
                return Promise.resolve()
              if (!value) {
                return Promise.reject(new Error('Time is required'))
              }
              const limit = moment().add(1, 'hour').utc()

              const utcDate = transfor2Utc(value)

              if (limit.isAfter(utcDate)) {
                return Promise.reject(
                  new Error('Time must be at least 1 hour after now')
                )
              }
              return Promise.resolve()
            }
          }
        ]}
      >
        <DatePicker showTime />
      </Form.Item>
    </Col>
  )

  return (
    <Form
      form={form}
      onFinish={onSave}
      layout="vertical"
      onValuesChange={(_, values: FormType) => {
        setFormValues(values)
        form.validateFields()
      }}
    >
      <Tabs centered activeKey={activeTab} onChange={onSwitchTab}>
        <Tabs.TabPane tab="Edit" key={TabKeyEnum.Edit}>
          {topButton}
          {subjectAndType}
          {editPanel}
        </Tabs.TabPane>
        <Tabs.TabPane tab="Send or Schedule" key={TabKeyEnum.Schedule}>
          {topButton}
          <Row>
            {recipients}
            {sendingOptions}
          </Row>
        </Tabs.TabPane>
      </Tabs>
    </Form>
  )
}

const transfor2Utc = (date: Moment) => {
  const hours = date.hours()
  const minutes = date.minutes()
  const seconds = date.seconds()
  const utcDate = moment.utc().set({ hours, minutes, seconds })
  return utcDate
}
