import React, { useState, useEffect } from 'react'
import { useLocation } from 'react-router-dom'
import axios from 'axios'
import {
  Descriptions,
  Spin,
  Space,
  Button,
  message,
  Badge,
  Form,
  Typography,
  Flex,
  Input,
  Card,
  Collapse,
  Dropdown,
  Popover,
  Checkbox
} from 'antd'
import { LoadingOutlined, CaretLeftOutlined } from '@ant-design/icons'
import IdText from '../../common/IdText.jsx'
import { capitalizeFirstLetter } from '../../utils/Utils.js'
import FilamentSelect from '../../common/FilamentSelect'
import useCollapseState from '../../hooks/useCollapseState'
import FilamentIcon from '../../../Icons/FilamentIcon'
import TimeDisplay from '../../common/TimeDisplay.jsx'
import ReloadIcon from '../../../Icons/ReloadIcon'
import EditIcon from '../../../Icons/EditIcon.jsx'
import XMarkIcon from '../../../Icons/XMarkIcon.jsx'
import CheckIcon from '../../../Icons/CheckIcon.jsx'

import config from '../../../../config.js'
import AuditLogTable from '../../common/AuditLogTable.jsx'
import DashboardNotes from '../../common/DashboardNotes.jsx'
import BinIcon from '../../../Icons/BinIcon.jsx'
import InfoCircleIcon from '../../../Icons/InfoCircleIcon.jsx'
import GCodeFileIcon from '../../../Icons/GCodeFileIcon.jsx'
import NoteIcon from '../../../Icons/NoteIcon.jsx'
import AuditLogIcon from '../../../Icons/AuditLogIcon.jsx'

const { Title, Text } = Typography

const GCodeFileInfo = () => {
  const [gcodeFileData, setGCodeFileData] = useState(null)
  const [editLoading, setLoading] = useState(false)
  const [error, setError] = useState(null)
  const location = useLocation()
  const [messageApi, contextHolder] = message.useMessage()
  const gcodeFileId = new URLSearchParams(location.search).get('gcodeFileId')
  const [isEditing, setIsEditing] = useState(false)
  const [form] = Form.useForm()
  const [fetchLoading, setFetchLoading] = useState(true)
  const [collapseState, updateCollapseState] = useCollapseState(
    'GCodeFileInfo',
    {
      info: true,
      preview: true
    }
  )

  useEffect(() => {
    if (gcodeFileId) {
      fetchGCodeFileDetails()
    }
  }, [gcodeFileId])

  useEffect(() => {
    if (gcodeFileData) {
      form.setFieldsValue({
        name: gcodeFileData.name || '',
        filament: gcodeFileData.filament || { id: null, name: '' }
      })
    }
  }, [gcodeFileData, form])

  const fetchGCodeFileDetails = async () => {
    try {
      setFetchLoading(true)
      const response = await axios.get(
        `${config.backendUrl}/gcodefiles/${gcodeFileId}`,
        {
          headers: {
            Accept: 'application/json'
          },
          withCredentials: true
        }
      )
      setGCodeFileData(response.data)
      setError(null)
    } catch (err) {
      setError('Failed to fetch GCodeFile details')
      messageApi.error('Failed to fetch GCodeFile details')
    } finally {
      setFetchLoading(false)
    }
  }

  const startEditing = () => {
    setIsEditing(true)
    updateCollapseState('info', true)
  }

  const cancelEditing = () => {
    form.setFieldsValue({
      name: gcodeFileData?.name || '',
      filament: gcodeFileData?.filament || { id: null, name: '' }
    })
    setIsEditing(false)
  }

  const updateGCodeFileInfo = async () => {
    try {
      const values = await form.validateFields()
      setLoading(true)

      await axios.put(
        `${config.backendUrl}/gcodefiles/${gcodeFileId}`,
        values,
        {
          headers: {
            'Content-Type': 'application/json'
          },
          withCredentials: true
        }
      )

      setGCodeFileData({ ...gcodeFileData, ...values })
      setIsEditing(false)
      messageApi.success('GCode File information updated successfully')
    } catch (err) {
      if (err.errorFields) {
        return
      }
      console.error('Failed to update gcode file information:', err)
      messageApi.error('Failed to update gcode file information')
    } finally {
      fetchGCodeFileDetails()
      setLoading(false)
    }
  }

  const actionItems = {
    items: [
      {
        label: 'Edit GCode File',
        key: 'edit',
        icon: <EditIcon />
      },
      {
        label: 'Delete GCode File',
        key: 'delete',
        icon: <BinIcon />,
        danger: true
      },
      { type: 'divider' },
      {
        label: 'Reload GCode File',
        key: 'reload',
        icon: <ReloadIcon />
      }
    ],
    onClick: ({ key }) => {
      if (key === 'reload') {
        fetchGCodeFileDetails()
      }
    }
  }

  const getViewDropdownItems = () => {
    const sections = [
      { key: 'info', label: 'GCode File Information' },
      { key: 'preview', label: 'GCode File Preview' },
      { key: 'notes', label: 'Notes' },
      { key: 'auditLogs', label: 'Audit Logs' }
    ]

    return (
      <Flex vertical>
        <Flex vertical gap='middle' style={{ margin: '4px 8px' }}>
          {sections.map((section) => (
            <Checkbox
              checked={collapseState[section.key]}
              key={section.key}
              onChange={(e) => {
                updateCollapseState(section.key, e.target.checked)
              }}
            >
              {section.label}
            </Checkbox>
          ))}
        </Flex>
      </Flex>
    )
  }

  return (
    <>
      {contextHolder}
      <Flex
        gap='large'
        vertical='true'
        style={{ height: '100%', minHeight: 0 }}
      >
        <Flex justify={'space-between'}>
          <Space size='small'>
            <Dropdown menu={actionItems}>
              <Button>Actions</Button>
            </Dropdown>
            <Popover
              content={getViewDropdownItems()}
              placement='bottomLeft'
              arrow={false}
            >
              <Button>View</Button>
            </Popover>
          </Space>
          <Space>
            {isEditing ? (
              <>
                <Button
                  icon={<CheckIcon />}
                  type='primary'
                  onClick={updateGCodeFileInfo}
                  loading={editLoading}
                  disabled={editLoading}
                />
                <Button
                  icon={<XMarkIcon />}
                  onClick={cancelEditing}
                  disabled={editLoading}
                />
              </>
            ) : (
              <Button icon={<EditIcon />} onClick={startEditing} />
            )}
          </Space>
        </Flex>

        {error ? (
          <Space
            direction='vertical'
            style={{ width: '100%', textAlign: 'center' }}
          >
            <p>{error || 'Print job not found'}</p>
            <Button icon={<ReloadIcon />} onClick={fetchGCodeFileDetails}>
              Retry
            </Button>
          </Space>
        ) : (
          <div style={{ height: '100%', overflow: 'auto' }}>
            <Flex vertical gap={'large'}>
              <Collapse
                ghost
                expandIconPosition='end'
                activeKey={collapseState.info ? ['info'] : []}
                onChange={(keys) =>
                  updateCollapseState('info', keys.length > 0)
                }
                expandIcon={({ isActive }) => (
                  <CaretLeftOutlined rotate={isActive ? -90 : 0} />
                )}
                className='no-h-padding-collapse no-t-padding-collapse'
              >
                <Collapse.Panel
                  header={
                    <Flex align='center' gap={'middle'}>
                      <InfoCircleIcon />
                      <Title level={5} style={{ margin: 0 }}>
                        GCode File Information
                      </Title>
                    </Flex>
                  }
                  key='info'
                >
                  <Form form={form} layout='vertical'>
                    <Spin
                      spinning={fetchLoading}
                      indicator={<LoadingOutlined />}
                    >
                      <Descriptions
                        bordered
                        column={{
                          xs: 1,
                          sm: 1,
                          md: 1,
                          lg: 2,
                          xl: 2,
                          xxl: 2
                        }}
                      >
                        <Descriptions.Item label='ID' span={1}>
                          {gcodeFileData?._id ? (
                            <IdText
                              id={gcodeFileData._id}
                              type='gcodefile'
                            ></IdText>
                          ) : (
                            <Text>n/a</Text>
                          )}
                        </Descriptions.Item>
                        <Descriptions.Item label='Created At'>
                          {gcodeFileData?.createdAt ? (
                            <TimeDisplay
                              dateTime={gcodeFileData.createdAt}
                              showSince={true}
                            />
                          ) : (
                            <Text>n/a</Text>
                          )}
                        </Descriptions.Item>

                        <Descriptions.Item label='Name'>
                          {isEditing ? (
                            <Form.Item
                              name='name'
                              rules={[
                                {
                                  required: true,
                                  message: 'Please enter a vendor name'
                                },
                                {
                                  max: 100,
                                  message: 'Name cannot exceed 100 characters'
                                }
                              ]}
                              style={{ margin: 0 }}
                            >
                              <Input />
                            </Form.Item>
                          ) : gcodeFileData?.name ? (
                            <Text>{gcodeFileData.name}</Text>
                          ) : (
                            <Text>n/a</Text>
                          )}
                        </Descriptions.Item>

                        <Descriptions.Item label='Updated At'>
                          {gcodeFileData?.updatedAt ? (
                            <TimeDisplay
                              dateTime={gcodeFileData.updatedAt}
                              showSince={true}
                            />
                          ) : (
                            <Text>n/a</Text>
                          )}
                        </Descriptions.Item>
                        <Descriptions.Item label='Filament Name'>
                          {isEditing ? (
                            <Form.Item
                              name='filament'
                              rules={[
                                {
                                  required: true,
                                  message: 'Please enter a filament'
                                }
                              ]}
                              style={{ margin: 0 }}
                            >
                              <FilamentSelect />
                            </Form.Item>
                          ) : gcodeFileData?.filament ? (
                            <Space>
                              <FilamentIcon />
                              <Badge
                                color={gcodeFileData.filament.color}
                                text={gcodeFileData.filament.name}
                              />
                            </Space>
                          ) : (
                            <Text>n/a</Text>
                          )}
                        </Descriptions.Item>
                        <Descriptions.Item label='Filament ID'>
                          {gcodeFileData?.filament ? (
                            <IdText
                              id={gcodeFileData.filament.id}
                              type={'filament'}
                              showHyperlink={true}
                            />
                          ) : (
                            <Text>n/a</Text>
                          )}
                        </Descriptions.Item>
                        <Descriptions.Item label='Est Print Time'>
                          {gcodeFileData?.gcodeFileInfo
                            ?.estimatedPrintingTimeNormalMode ? (
                            <Text>
                              {
                                gcodeFileData.gcodeFileInfo
                                  .estimatedPrintingTimeNormalMode
                              }
                            </Text>
                          ) : (
                            <Text>n/a</Text>
                          )}
                        </Descriptions.Item>
                        <Descriptions.Item label='Cost'>
                          {gcodeFileData?.cost ? (
                            <Text>{'£' + gcodeFileData.cost.toFixed(2)}</Text>
                          ) : (
                            <Text>n/a</Text>
                          )}
                        </Descriptions.Item>
                        <Descriptions.Item label='Infill Density'>
                          {gcodeFileData?.gcodeFileInfo?.sparseInfillDensity ? (
                            <Text>
                              {gcodeFileData.gcodeFileInfo.sparseInfillDensity}
                            </Text>
                          ) : (
                            <Text>n/a</Text>
                          )}
                        </Descriptions.Item>
                        <Descriptions.Item label='Infill Pattern'>
                          {gcodeFileData?.gcodeFileInfo?.sparseInfillPattern ? (
                            <Text>
                              {capitalizeFirstLetter(
                                gcodeFileData.gcodeFileInfo.sparseInfillPattern
                              )}
                            </Text>
                          ) : (
                            <Text>n/a</Text>
                          )}
                        </Descriptions.Item>
                        <Descriptions.Item label='Filament Used (mm)'>
                          {gcodeFileData?.gcodeFileInfo?.filamentUsedMm ? (
                            <Text>
                              {gcodeFileData.gcodeFileInfo.filamentUsedMm}mm
                            </Text>
                          ) : (
                            <Text>n/a</Text>
                          )}
                        </Descriptions.Item>
                        <Descriptions.Item label='Filament Used (g)'>
                          {gcodeFileData?.gcodeFileInfo?.filamentUsedG ? (
                            <Text>
                              {gcodeFileData.gcodeFileInfo.filamentUsedG}g
                            </Text>
                          ) : (
                            <Text>n/a</Text>
                          )}
                        </Descriptions.Item>
                        <Descriptions.Item label='Hotend Temperature'>
                          {gcodeFileData?.gcodeFileInfo?.nozzleTemperature ? (
                            <Text>
                              {gcodeFileData.gcodeFileInfo.nozzleTemperature}°
                            </Text>
                          ) : (
                            <Text>n/a</Text>
                          )}
                        </Descriptions.Item>
                        <Descriptions.Item label='Bed Temperature'>
                          {gcodeFileData?.gcodeFileInfo?.hotPlateTemp ? (
                            <Text>
                              {gcodeFileData.gcodeFileInfo.hotPlateTemp}°
                            </Text>
                          ) : (
                            <Text>n/a</Text>
                          )}
                        </Descriptions.Item>
                        <Descriptions.Item label='Filament Profile'>
                          {gcodeFileData?.gcodeFileInfo?.filamentSettingsId ? (
                            <Text>
                              {gcodeFileData.gcodeFileInfo.filamentSettingsId.replaceAll(
                                '"',
                                ''
                              )}
                            </Text>
                          ) : (
                            <Text>n/a</Text>
                          )}
                        </Descriptions.Item>
                        <Descriptions.Item label='Print Profile'>
                          {gcodeFileData?.gcodeFileInfo?.printSettingsId ? (
                            <Text>
                              {gcodeFileData.gcodeFileInfo.printSettingsId.replaceAll(
                                '"',
                                ''
                              )}
                            </Text>
                          ) : (
                            <Text>n/a</Text>
                          )}
                        </Descriptions.Item>
                      </Descriptions>
                    </Spin>
                  </Form>
                </Collapse.Panel>
              </Collapse>

              <Collapse
                ghost
                expandIconPosition='end'
                activeKey={collapseState.preview ? ['preview'] : []}
                onChange={(keys) =>
                  updateCollapseState('preview', keys.length > 0)
                }
                expandIcon={({ isActive }) => (
                  <CaretLeftOutlined rotate={isActive ? -90 : 0} />
                )}
                className='no-h-padding-collapse'
              >
                <Collapse.Panel
                  header={
                    <Flex align='center' gap={'middle'}>
                      <GCodeFileIcon />
                      <Title level={5} style={{ margin: 0 }}>
                        GCode File Preview
                      </Title>
                    </Flex>
                  }
                  key='preview'
                >
                  <Spin spinning={fetchLoading} indicator={<LoadingOutlined />}>
                    <Card styles={{ body: { padding: '10px' } }}>
                      {gcodeFileData?.gcodeFileInfo?.thumbnail ? (
                        <img
                          src={`data:image/png;base64,${gcodeFileData.gcodeFileInfo.thumbnail.data}`}
                          alt='GCodeFile'
                          style={{ maxWidth: '100%' }}
                        />
                      ) : (
                        <Text>n/a</Text>
                      )}
                    </Card>
                  </Spin>
                </Collapse.Panel>
              </Collapse>

              <Collapse
                ghost
                expandIconPosition='end'
                activeKey={collapseState.notes ? ['notes'] : []}
                onChange={(keys) =>
                  updateCollapseState('notes', keys.length > 0)
                }
                expandIcon={({ isActive }) => (
                  <CaretLeftOutlined rotate={isActive ? -90 : 0} />
                )}
                className='no-h-padding-collapse'
              >
                <Collapse.Panel
                  header={
                    <Flex align='center' gap={'middle'}>
                      <NoteIcon />
                      <Title level={5} style={{ margin: 0 }}>
                        Notes
                      </Title>
                    </Flex>
                  }
                  key='notes'
                >
                  <Card>
                    <DashboardNotes _id={gcodeFileId} />
                  </Card>
                </Collapse.Panel>
              </Collapse>

              <Collapse
                ghost
                expandIconPosition='end'
                activeKey={collapseState.auditLogs ? ['auditLogs'] : []}
                onChange={(keys) =>
                  updateCollapseState('auditLogs', keys.length > 0)
                }
                expandIcon={({ isActive }) => (
                  <CaretLeftOutlined rotate={isActive ? -90 : 0} />
                )}
                className='no-h-padding-collapse'
              >
                <Collapse.Panel
                  header={
                    <Flex align='center' gap={'middle'}>
                      <AuditLogIcon />
                      <Title level={5} style={{ margin: 0 }}>
                        Audit Log
                      </Title>
                    </Flex>
                  }
                  key='auditLogs'
                >
                  <AuditLogTable
                    items={gcodeFileData?.auditLogs || []}
                    loading={fetchLoading}
                    showTargetColumn={false}
                  />
                </Collapse.Panel>
              </Collapse>
            </Flex>
          </div>
        )}
      </Flex>
    </>
  )
}

export default GCodeFileInfo
