import { Button, Form, Input, InputNumber, notification } from 'antd'
import TextArea from 'antd/lib/input/TextArea'
import dayjs, { Dayjs } from 'dayjs'
import { useEffect, useState } from 'react'
import { useParams } from 'react-router-dom'

import { FormsUnitCostsInput } from 'apiClient/api/interface'
import { costUnitsDryrun, costUnitsMeasure } from 'apiClient/services/billing'
import DatePicker from 'components/DatePicker'
import { getErrorMessage } from 'utils/error'
import { format } from 'utils/time'

const serverFmt = 'YYYY-MM-DDTHH:mm:ss[Z]'

export const Metering = () => {
  const { org_id } = useParams<{ org_id: string }>()

  const [dryRunning, setDryRunning] = useState(false)
  const [loading, setLoading] = useState(false)

  const [form] = Form.useForm()

  const timeFormat = (value: Dayjs) => {
    return format(
      value.format(serverFmt),
      undefined,
      'YYYY-MM-DD HH:mm:ss Z',
      0
    )
  }

  const onSubmit = async (values: any) => {
    if (loading) {
      return
    }
    try {
      setLoading(true)
      await costUnitsMeasure(org_id, {
        ...packBody(values)
      })
      setLoading(false)
      notification.success({ message: 'Success.' })
      form.resetFields()
      genCostID()
      form.setFieldsValue({ tennant_id: org_id })
    } catch (e) {
      setLoading(false)
      notification.error({ message: getErrorMessage(e) })
    }
  }

  const packBody = (
    values: Omit<FormsUnitCostsInput, 'labels'> & { labels?: string }
  ) => {
    return {
      cost: values.cost,
      cost_id: values.cost_id,
      cost_time_stamp: dayjs(
        dayjs(values.cost_time_stamp).format(serverFmt)
      ).unix(),
      unit: values.unit,
      labels: values.labels ? JSON.parse(values.labels) : undefined
    }
  }

  const genCostID = () => {
    form.setFieldsValue({ cost_id: `org_${org_id}_${new Date().getTime()}` })
  }

  const onDryRun = async () => {
    if (dryRunning) {
      return
    }
    let values = {}

    try {
      values = await form.validateFields()
    } catch (e) {
      console.warn(e)
      return
    }
    try {
      setDryRunning(true)
      await costUnitsDryrun(org_id, {
        ...packBody(values)
      })
      setDryRunning(false)
      notification.success({ message: 'Valid!' })
    } catch (e) {
      setDryRunning(false)
      notification.error({ message: getErrorMessage(e) })
    }
  }

  useEffect(() => {
    genCostID()
  }, [])

  useEffect(() => {
    form.setFieldsValue({ tennant_id: org_id })
  }, [org_id])

  return (
    <div>
      <Form
        form={form}
        labelCol={{ span: 8 }}
        wrapperCol={{ span: 16 }}
        style={{ width: '700px', margin: '0 auto' }}
        onFinish={onSubmit}
      >
        <Form.Item
          name="tennant_id"
          label="Tenant ID"
          style={{ marginBottom: 0 }}
        >
          <Input disabled />
        </Form.Item>
        <Form.Item label="Cost ID" noStyle>
          <Form.Item name="cost_id" noStyle>
            <Input
              style={{
                width: 300,
                marginRight: 8,
                padding: 0,
                height: 0,
                border: 'none'
              }}
              disabled
            />
          </Form.Item>
          {/* <Button onClick={genCostID}>Generate</Button> */}
        </Form.Item>
        <Form.Item
          name="cost_time_stamp"
          label="Cost Timestamp"
          rules={[{ required: true, message: 'Required' }]}
        >
          <DatePicker showTime={{ format: 'HH:mm:ss' }} format={timeFormat} />
        </Form.Item>
        <Form.Item
          name="unit"
          label="Unit"
          rules={[{ required: true, message: 'Required' }]}
        >
          <Input type="string" />
        </Form.Item>
        <Form.Item
          name="cost"
          label="Cost"
          rules={[{ required: true, message: 'Required' }]}
        >
          <InputNumber step={1} min={0} precision={0} style={{ width: 400 }} />
        </Form.Item>
        <Form.Item
          name="labels"
          label="Labels"
          rules={[
            {
              validator: (_, value) => {
                if (!value) {
                  return Promise.resolve()
                }
                try {
                  const parsedValue = JSON.parse(value)
                  const keys = Object.keys(parsedValue)
                  for (let i = 0; i < keys.length; i++) {
                    if (typeof parsedValue[keys[i]] !== 'string') {
                      return Promise.reject(
                        new Error(`The type of ${keys[i]} should be string`)
                      )
                    }
                  }
                  return Promise.resolve()
                } catch (e) {
                  return Promise.reject(new Error('Invalid JSON Input'))
                }
              }
            }
          ]}
        >
          <TextArea rows={4} />
        </Form.Item>
        <Form.Item wrapperCol={{ offset: 8, span: 16 }}>
          <Button onClick={onDryRun} loading={dryRunning} disabled={loading}>
            Dry Run
          </Button>
          <Button
            type="primary"
            htmlType="submit"
            loading={loading}
            disabled={dryRunning}
            style={{ marginLeft: 24 }}
          >
            Measure
          </Button>
        </Form.Item>
      </Form>
    </div>
  )
}
