import PropTypes from 'prop-types'
import React, { useState } from 'react'
import axios from 'axios'
import {
  Form,
  Input,
  Button,
  message,
  Select,
  Flex,
  Steps,
  Divider,
  Upload,
  Descriptions
} from 'antd'
import { UploadOutlined } from '@ant-design/icons'
import VendorSelect from '../../common/VendorSelect'

import config from '../../../../config'

const initialNewMaterialForm = {
  name: '',
  vendor: { id: null, name: '' },
  category: '',
  image: null,
  url: '',
  barcode: ''
}

const NewMaterial = ({ onSuccess }) => {
  const [messageApi, contextHolder] = message.useMessage()

  const [newMaterialLoading, setNewMaterialLoading] = useState(false)
  const [currentStep, setCurrentStep] = useState(0)
  const [nextEnabled, setNextEnabled] = useState(false)

  const [newMaterialForm] = Form.useForm()
  const [newMaterialFormValues, setNewMaterialFormValues] = useState(
    initialNewMaterialForm
  )

  const [imageList, setImageList] = useState([])

  const newMaterialFormUpdateValues = Form.useWatch([], newMaterialForm)

  React.useEffect(() => {
    newMaterialForm
      .validateFields({
        validateOnly: true
      })
      .then(() => setNextEnabled(true))
      .catch(() => setNextEnabled(false))
  }, [newMaterialForm, newMaterialFormUpdateValues])

  const summaryItems = [
    {
      key: 'name',
      label: 'Name',
      children: newMaterialFormValues.name
    },
    {
      key: 'vendor',
      label: 'Vendor',
      children: newMaterialFormValues.vendor.name
    },
    {
      key: 'category',
      label: 'Category',
      children: newMaterialFormValues.category
    },
    {
      key: 'image',
      label: 'Image',
      children: newMaterialFormValues.image && (
        <img
          src={newMaterialFormValues.image}
          style={{ width: 128 }}
          alt='Material'
        />
      )
    },
    {
      key: 'url',
      label: 'URL',
      children: newMaterialFormValues.url
    },
    {
      key: 'barcode',
      label: 'Barcode',
      children: newMaterialFormValues.barcode
    }
  ]

  const handleNewMaterial = async () => {
    setNewMaterialLoading(true)
    try {
      await axios.post(
        `${config.backendUrl}/materials`,
        newMaterialFormValues,
        {
          withCredentials: true
        }
      )
      messageApi.success('New material created successfully.')
      onSuccess()
    } catch (error) {
      messageApi.error('Error creating new material: ' + error.message)
    } finally {
      setNewMaterialLoading(false)
    }
  }

  const getBase64 = (file) => {
    return new Promise((resolve, reject) => {
      const reader = new FileReader()
      reader.readAsDataURL(file)
      reader.onload = () => resolve(reader.result)
      reader.onerror = (error) => reject(error)
    })
  }

  const handleImageUpload = async ({ file, fileList }) => {
    if (fileList.length === 0) {
      setImageList(fileList)
      newMaterialForm.setFieldsValue({ image: '' })
      return
    }
    const base64 = await getBase64(file)
    setNewMaterialFormValues((prevValues) => ({
      ...prevValues,
      image: base64
    }))
    fileList[0].name = 'Material Image'
    setImageList(fileList)
    newMaterialForm.setFieldsValue({ image: base64 })
  }

  const steps = [
    {
      title: 'Details',
      key: 'details',
      content: (
        <>
          <Form.Item
            label='Name'
            name='name'
            rules={[
              {
                required: true,
                message: 'Please enter a name.'
              }
            ]}
          >
            <Input />
          </Form.Item>
          <Form.Item
            label='Vendor'
            name='vendor'
            rules={[
              {
                required: true,
                message: 'Please select a vendor.'
              }
            ]}
          >
            <VendorSelect />
          </Form.Item>
          <Form.Item
            label='Category'
            name='category'
            rules={[{ required: true, message: 'Please select a category' }]}
          >
            <Select>
              <Select.Option value='Raw Material'>Raw Material</Select.Option>
              <Select.Option value='Component'>Component</Select.Option>
              <Select.Option value='Consumable'>Consumable</Select.Option>
              <Select.Option value='Tool'>Tool</Select.Option>
              <Select.Option value='Packaging'>Packaging</Select.Option>
            </Select>
          </Form.Item>
        </>
      )
    },
    {
      title: 'Additional Info',
      key: 'additional',
      content: (
        <>
          <Form.Item label='Image' name='image'>
            <Upload
              listType='picture'
              maxCount={1}
              fileList={imageList}
              onChange={handleImageUpload}
              beforeUpload={() => false}
            >
              <Button icon={<UploadOutlined />}>Upload Image</Button>
            </Upload>
          </Form.Item>
          <Form.Item label='URL' name='url'>
            <Input />
          </Form.Item>
          <Form.Item label='Barcode' name='barcode'>
            <Input />
          </Form.Item>
        </>
      )
    },
    {
      title: 'Summary',
      key: 'summary',
      content: (
        <>
          <Descriptions
            title='Material Details'
            bordered
            column={1}
            items={summaryItems}
          />
        </>
      )
    }
  ]

  return (
    <>
      {contextHolder}
      <Form
        form={newMaterialForm}
        layout='vertical'
        onValuesChange={(changedValues) => {
          setNewMaterialFormValues((prevValues) => ({
            ...prevValues,
            ...changedValues
          }))
        }}
      >
        <Steps
          current={currentStep}
          items={steps.map((item) => ({ title: item.title }))}
          style={{ marginBottom: 24 }}
        />
        <div style={{ minHeight: 200 }}>{steps[currentStep].content}</div>
        <Divider />
        <Flex justify='space-between'>
          <Button
            disabled={currentStep === 0}
            onClick={() => setCurrentStep((prev) => prev - 1)}
          >
            Previous
          </Button>
          {currentStep < steps.length - 1 ? (
            <Button
              type='primary'
              disabled={!nextEnabled}
              onClick={() => setCurrentStep((prev) => prev + 1)}
            >
              Next
            </Button>
          ) : (
            <Button
              type='primary'
              loading={newMaterialLoading}
              onClick={handleNewMaterial}
            >
              Create Material
            </Button>
          )}
        </Flex>
      </Form>
    </>
  )
}

NewMaterial.propTypes = {
  onSuccess: PropTypes.func.isRequired
}

export default NewMaterial
