import { useContext, useEffect, useState } from 'react'
import { Divider, Flex, Layout, Typography, Button, Badge, Modal } from 'antd'
import { LoadingOutlined } from '@ant-design/icons'
import { useLocation } from 'react-router-dom'
import ControlPrinter from './ControlPrinter.jsx'
import SlicerUploadFlow from './SlicerUploadFlow.jsx'
import PrinterIcon from '../../../Icons/PrinterIcon.jsx'
import ObjectForm from '../../common/ObjectForm.jsx'
import FileIcon from '../../../Icons/FileIcon.jsx'
import ObjectProperty from '../../common/ObjectProperty.jsx'
import { getModelProperty } from '../../../../database/ObjectModels.js'
import { ApiServerContext } from '../../context/ApiServerContext.jsx'
import { useThemeContext } from '../../context/ThemeContext.jsx'

const { Content } = Layout
const { Title } = Typography

const SlicerIntegration = () => {
  const location = useLocation()
  const printerId = new URLSearchParams(location.search).get('printerId')
  const { updateObject } = useContext(ApiServerContext)

  const [pendingSlicerUploads, setPendingSlicerUploads] = useState([])
  const [currentPendingSlicerUpload, setCurrentPendingSlicerUpload] =
    useState(null)

  const { setPrimaryColorOverride } = useThemeContext()

  useEffect(() => {
    setPrimaryColorOverride('#00baa8')
  }, [setPrimaryColorOverride])

  const [objectFormState, setEditFormState] = useState({
    isEditing: false,
    editLoading: false,
    formValid: false,
    activities: [],
    loading: false,
    objectData: {
      pendingSlicerUploads: []
    }
  })
  const [showSlicerUploadFlow, setShowSlicerUploadFlow] = useState(false)

  useEffect(() => {
    setPendingSlicerUploads(
      objectFormState.objectData?.pendingSlicerUploads || []
    )
  }, [objectFormState.objectData?.pendingSlicerUploads])

  useEffect(() => {
    const nextUpload = pendingSlicerUploads.find(
      (upload) => upload.new === true
    )

    if (nextUpload) {
      setCurrentPendingSlicerUpload(nextUpload)
      setShowSlicerUploadFlow(true)
    } else {
      setCurrentPendingSlicerUpload(null)
      setShowSlicerUploadFlow(false)
    }
  }, [pendingSlicerUploads])

  const showPendingSlicerUpload = () => {
    const upload =
      pendingSlicerUploads.find(
        (pendingUpload) => pendingUpload.new === true
      ) || pendingSlicerUploads[0]

    if (upload) {
      setCurrentPendingSlicerUpload(upload)
      setShowSlicerUploadFlow(true)
    }
  }

  const handleGCodeFileCreated = async (gcodeFile) => {
    const updatedUploads = pendingSlicerUploads.map((upload) =>
      upload._id === currentPendingSlicerUpload?._id
        ? { ...upload, gcodeFile: gcodeFile }
        : upload
    )

    setPendingSlicerUploads(updatedUploads)
    setCurrentPendingSlicerUpload((previous) => ({
      ...previous,
      gcodeFile
    }))
    await updateObject(printerId, 'printer', {
      ...objectFormState.objectData,
      pendingSlicerUploads: updatedUploads
    })
  }

  const handleJobCreated = async (job) => {
    const updatedUploads = pendingSlicerUploads.map((upload) =>
      upload._id === currentPendingSlicerUpload?._id
        ? { ...upload, job }
        : upload
    )

    setPendingSlicerUploads(updatedUploads)
    setCurrentPendingSlicerUpload((previous) => ({
      ...previous,
      job
    }))
    await updateObject(printerId, 'printer', {
      ...objectFormState.objectData,
      pendingSlicerUploads: updatedUploads
    })
  }

  const handleSlicerUploadComplete = async () => {
    const updatedUploads = pendingSlicerUploads.filter(
      (upload) => upload._id !== currentPendingSlicerUpload?._id
    )

    setPendingSlicerUploads(updatedUploads)
    await updateObject(printerId, 'printer', {
      ...objectFormState.objectData,
      pendingSlicerUploads: updatedUploads
    })
  }

  const handleSlicerUploadFlowClosed = async () => {
    const updatedUploads = pendingSlicerUploads.map((upload) =>
      upload._id === currentPendingSlicerUpload?._id
        ? { ...upload, new: false }
        : upload
    )

    setPendingSlicerUploads(updatedUploads)
    await updateObject(printerId, 'printer', {
      ...objectFormState.objectData,
      pendingSlicerUploads: updatedUploads
    })
  }

  const slicerUploadsButton = () => {
    if (pendingSlicerUploads.length > 0) {
      return (
        <Badge
          count={pendingSlicerUploads.length}
          style={{ marginTop: '8px' }}
          size='small'
        >
          <Button
            type='text'
            icon={<FileIcon />}
            onClick={showPendingSlicerUpload}
          />
        </Badge>
      )
    }
    return null
  }

  return (
    <Layout style={{ height: 'var(--unit-100vh)' }}>
      <Layout style={{ padding: '24px' }}>
        <Content>
          <Flex vertical style={{ height: '100%' }} gap='20px'>
            <ObjectForm
              id={printerId}
              type='printer'
              onStateChange={(state) =>
                setEditFormState((previousState) => ({
                  ...previousState,
                  ...state
                }))
              }
            >
              {({ loading, objectData }) => (
                <Flex justify='space-between' align='center'>
                  <Flex align='center' gap='middle'>
                    {loading ? (
                      <LoadingOutlined spin style={{ fontSize: '26px' }} />
                    ) : (
                      <PrinterIcon style={{ fontSize: '26px' }} />
                    )}
                    <Title level={3} style={{ margin: 0 }}>
                      {loading
                        ? 'Loading...'
                        : objectData?.name || 'Slicer Integration'}
                    </Title>
                    {!loading && (
                      <div
                        style={{
                          maxWidth: '400px',
                          width: '400px',
                          minWidth: '100px'
                        }}
                      >
                        <ObjectProperty
                          objectData={objectData}
                          {...getModelProperty('printer', 'state')}
                        />
                      </div>
                    )}
                  </Flex>
                  {slicerUploadsButton()}
                </Flex>
              )}
            </ObjectForm>
            <Divider style={{ margin: '0' }} />
            <ControlPrinter slicerIntegration={true} />
          </Flex>
        </Content>
        <Modal
          open={showSlicerUploadFlow}
          onCancel={() => setShowSlicerUploadFlow(false)}
          afterClose={handleSlicerUploadFlowClosed}
          footer={null}
          width={740}
          destroyOnHidden={true}
        >
          {currentPendingSlicerUpload && (
            <SlicerUploadFlow
              key={currentPendingSlicerUpload._id}
              currentPendingSlicerUpload={currentPendingSlicerUpload}
              printer={objectFormState.objectData}
              onGCodeFileCreated={handleGCodeFileCreated}
              onJobCreated={handleJobCreated}
              onComplete={handleSlicerUploadComplete}
            />
          )}
        </Modal>
      </Layout>
    </Layout>
  )
}

export default SlicerIntegration
