import { useState, useContext, useEffect, useRef, useCallback } from 'react'
import PropTypes from 'prop-types'
import { Flex, Button, Input, Select } from 'antd'
import PlusIcon from '../../Icons/PlusIcon.jsx'
import MinusIcon from '../../Icons/MinusIcon.jsx'
import InfoCircleIcon from '../../Icons/InfoCircleIcon.jsx'
import ObjectProperty from '../common/ObjectProperty.jsx'
import { ApiServerContext } from '../context/ApiServerContext.jsx'

const noop = () => {}

const TemplatePreview = ({
  objectData,
  documentTemplate,
  loading,
  isEditing,
  onTestObjectOpen = noop,
  onPreviewMessage = noop,
  showTestObject = false,
  showPreviewSwitch = true
}) => {
  const iframeRef = useRef(null)
  const previewRequestIdRef = useRef(0)
  const { fetchTemplatePreview, fetchTemplatePDF } =
    useContext(ApiServerContext)
  const [previewContentHTML, setPreviewContentHTML] = useState('')
  const [pdfBlob, setPDFBlob] = useState(null)
  const [reloadLoading, setReloadLoading] = useState(false)
  const [previewScale, setPreviewScale] = useState(1)
  const [previewType, setPreviewType] = useState('HTML')

  const updatePreviewContentHTML = (html) => {
    if (iframeRef.current) {
      // Save current scroll position
      const scrollY = iframeRef.current.contentWindow.scrollY
      const scrollX = iframeRef.current.contentWindow.scrollX

      // Update srcDoc
      setPreviewContentHTML(html)

      // Restore scroll position after iframe loads new content
      const handleLoad = () => {
        iframeRef.current.contentWindow.scrollTo(scrollX, scrollY)
        iframeRef.current.removeEventListener('load', handleLoad)
      }
      iframeRef.current.addEventListener('load', handleLoad)
    }
  }

  const reloadPreviewPDF = useCallback(
    (content, testObject = {}) => {
      const templateId = documentTemplate?._id
      if (!templateId) {
        return
      }

      const requestId = ++previewRequestIdRef.current
      setReloadLoading(true)
      fetchTemplatePDF(templateId, content, testObject, (result) => {
        if (requestId !== previewRequestIdRef.current) {
          return
        }
        setReloadLoading(false)
        if (result?.error) {
          onPreviewMessage(result.error, true)
        } else {
          const pdfBlob = new Blob([result.pdf], { type: 'application/pdf' })
          const pdfUrl = URL.createObjectURL(pdfBlob)

          setPDFBlob(pdfUrl)
          onPreviewMessage('No issues found.', false)
        }
      })
    },
    [documentTemplate?._id, fetchTemplatePDF, onPreviewMessage]
  )

  const reloadPreview = useCallback(
    (content, testObject = {}, scale = 1) => {
      const templateId = documentTemplate?._id
      if (!templateId) {
        return
      }

      const requestId = ++previewRequestIdRef.current
      setReloadLoading(true)
      fetchTemplatePreview(
        templateId,
        content,
        testObject,
        scale,
        (result) => {
          if (requestId !== previewRequestIdRef.current) {
            return
          }
          setReloadLoading(false)
          if (result?.error) {
            onPreviewMessage(result.error, true)
          } else {
            updatePreviewContentHTML(result.html)
            onPreviewMessage('No issues found.', false)
          }
        }
      )
    },
    [fetchTemplatePreview, onPreviewMessage, documentTemplate?._id]
  )

  const templateContent = documentTemplate?.content
  const templateId = documentTemplate?._id

  // Move useEffect to component level and use state to track objectData changes
  useEffect(() => {
    if (!templateId || !templateContent) {
      return
    }

    const timeoutId = window.setTimeout(() => {
      if (previewType == 'HTML') {
        reloadPreview(templateContent, objectData, previewScale)
      } else {
        reloadPreviewPDF(templateContent, objectData)
      }
    }, 300)

    return () => {
      window.clearTimeout(timeoutId)
    }
  }, [
    objectData,
    templateContent,
    templateId,
    previewScale,
    previewType,
    reloadPreview,
    reloadPreviewPDF
  ])

  return (
    <Flex vertical gap={'middle'} style={{ height: '100%' }}>
      <Flex gap={'small'}>
        {showTestObject == true ? (
          <>
            {documentTemplate?.objectType ? (
              <ObjectProperty
                objectType={documentTemplate?.objectType}
                name={'testObject'}
                isEditing={true}
                objectData={objectData}
                disabled={!isEditing || objectData?.global}
                type={'object'}
              />
            ) : (
              <div style={{ flexGrow: 1 }}>
                <Input disabled={true} />
              </div>
            )}
            <Button
              icon={<InfoCircleIcon />}
              disabled={objectData?.global}
              onClick={() => {
                onTestObjectOpen()
              }}
            />
          </>
        ) : null}

        <Button
          icon={<PlusIcon />}
          onClick={() => {
            setPreviewScale((prev) => prev + 0.05)
          }}
          disabled={loading || reloadLoading || previewType == 'PDF'}
        />
        <Button
          icon={<MinusIcon />}
          onClick={() => {
            setPreviewScale((prev) => prev - 0.05)
          }}
          disabled={loading || reloadLoading || previewType == 'PDF'}
        />
        <Button
          readOnly={true}
          style={{ width: '65px' }}
          disabled={loading || reloadLoading || previewType == 'PDF'}
          onClick={() => {
            setPreviewScale(1)
          }}
        >
          {previewScale.toFixed(2)}x
        </Button>
        {showPreviewSwitch == true ? (
          <Select
            options={[
              { value: 'HTML', label: 'HTML' },
              { value: 'PDF', label: 'PDF' }
            ]}
            loading={loading || reloadLoading}
            disabled={loading || reloadLoading}
            value={previewType}
            onChange={(value) => {
              setPreviewType(value)
            }}
          />
        ) : null}
      </Flex>

      <iframe
        ref={iframeRef}
        srcDoc={previewType == 'HTML' ? previewContentHTML : undefined}
        src={previewType == 'PDF' ? pdfBlob : undefined}
        frameBorder='0'
        style={{
          width: '100%',
          flexGrow: 1,
          border: '1px solid #85858541',
          overflow: 'auto'
        }}
      />
    </Flex>
  )
}

TemplatePreview.propTypes = {
  loading: PropTypes.bool,
  objectData: PropTypes.object,
  documentTemplate: PropTypes.object,
  isEditing: PropTypes.bool,
  style: PropTypes.object,
  showTestObject: PropTypes.bool,
  onTestObjectOpen: PropTypes.func,
  onPreviewMessage: PropTypes.func,
  showPreviewSwitch: PropTypes.bool
}

export default TemplatePreview
