import { GenerativePage, useThemeName } from '@my/ui'
import { getServerAddress } from 'app/utils/getServerAddress'
import { EventSourcePolyfill as EventSource } from 'event-source-polyfill'
import React, { useEffect, useState, useCallback } from 'react'
import { useRouter } from 'solito/router'
import { useParams } from 'solito/navigation'

export const PostPage = () => {
  const params = useParams()
  const router = useRouter()
  const [title, setTitle] = useState<string>('Title')
  const [loading, setLoading] = useState<boolean>(true)
  const [streamId, setStreamId] = useState<string | null>(null)
  const [code, setCode] = useState<string>('')
  const [shouldFetch, setShouldFetch] = useState<boolean>(true)
  const themeName = useThemeName()
  const isDarkMode = themeName.includes('dark')

  const fetchPostData = useCallback(
    async (guideline: string) => {
      const serverAddress = getServerAddress()
      const url = `${serverAddress}/post/${params.title}`

      try {
        const response = await fetch(url, {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({
            generationGuideline: `${guideline}\n${isDarkMode ? 'Use dark mode colors.' : ''}`,
          }),
        })

        if (!response.headers.get('content-type')?.includes('application/json')) {
          throw new Error('Unexpected Content Type')
        }

        const data = await response.json()
        if (data.action === 'render_post_data') {
          const { title: postTitle, generated_code } = data.post_data
          setTitle(postTitle || 'Title')
          setCode(generated_code || '')
          setLoading(false)
        } else if (data.action === 'generating_post_page') {
          setStreamId(data.stream_id)
          setTitle(data.post_title)
        } else {
          console.warn('Unexpected Server Response:', data.action)
          setLoading(false)
        }
      } catch (error) {
        console.error('Error:', error)
        setLoading(false)
      }
    },
    [params?.title, isDarkMode]
  )

  const initializeFetch = useCallback(async () => {
    if (!params?.title || !shouldFetch) return
    setShouldFetch(false)
    setTitle('Loading')
    setLoading(true)

    const guideline = `Post Title: ${params.title}`
    await fetchPostData(guideline)
  }, [params?.title, shouldFetch, fetchPostData])

  const handleGuidelineSubmit = useCallback(
    async (guideline: string) => {
      if (!params?.title) return
      setLoading(true)
      await fetchPostData(guideline)
    },
    [params?.title, fetchPostData]
  )

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

  useEffect(() => {
    if (streamId) {
      const serverAddress = getServerAddress()
      const eventSource = new EventSource(`${serverAddress}/stream/${streamId}`)

      eventSource.onmessage = (event) => {
        const eventData = event.data
        try {
          const data = JSON.parse(eventData)
          if (data.action === 'render_post_page') {
            setCode(data.page_code || '')
            setTitle(data.page_title || '')
            if (data.page_link && data.page_link !== params?.title) {
              router.push(`/post/${data.page_link}`, undefined, { shallow: true })
            }
            setLoading(false)
            eventSource.close()
          }
        } catch (error) {
          console.error('Error processing stream message:', error)
        }
      }

      eventSource.onerror = (error) => {
        console.error('EventSource error:', error)
        eventSource.close()
      }

      return () => {
        if (eventSource.readyState !== EventSource.CLOSED) {
          eventSource.close()
        }
      }
    }
  }, [streamId, params?.title, router])

  return (
    <GenerativePage
      kind="post"
      title={title}
      code={code}
      showLoading={loading}
      showBackButton
      onGuidelineSubmit={handleGuidelineSubmit}
    />
  )
}
