import { useEffect, useRef, useState } from 'react'
import Taro from '@tarojs/taro'
import { ScrollView, Text, View } from '@tarojs/components'
import { PublishChip, PublishIcon } from '@/features/publish/components/PublishPrimitives'
import PublishComposer from '@/features/publish/components/PublishComposer'
import MediaGrid from '@/features/publish/components/MediaGrid'
import PublishOptions from '@/features/publish/components/PublishOptions'
import PetPickerSheet from '@/features/publish/components/PetPickerSheet'
import ComposerToolbar from '@/features/publish/components/ComposerToolbar'
import VisibilitySheet from '@/features/publish/components/VisibilitySheet'
import SuccessModal from '@/features/publish/components/SuccessModal'
import { createPost, getDraft, isUploadPostMediaError, saveDraft, uploadPostMedia } from '@/services/publish.service'
import { getPetList } from '@/services/profile.service'
import { mockPets, mockProfile } from '@/services/mock'
import { ensureProfileReady, useSession } from '@/store/session.store'
import { requestTab } from '@/store/homeTab'
import { useUploadMedia } from '@/hooks/useUploadMedia'
import { useSystemLayout } from '@/hooks/useSystemLayout'
import { isValidPostContent } from '@/utils/validators'
import type { Pet, PublishDraft, Visibility } from '@/types/domain'
import './index.scss'

const defaultTopics = ['滨江公园', '金毛日常', '遛弯', '周末聚会', '猫咪', '新手养宠']

function hasDraftContent(draft: PublishDraft | null | undefined): draft is PublishDraft {
  return Boolean(
    draft &&
    (
      draft.content?.trim() ||
      draft.media?.length ||
      draft.topics?.length ||
      draft.petId ||
      draft.locationText
    )
  )
}

export default function PublishPage() {
  const { statusBarHeight, menuRight } = useSystemLayout()
  const { user } = useSession()
  const [content, setContent] = useState('')
  const [topics, setTopics] = useState<string[]>(defaultTopics)
  const [selectedTopics, setSelectedTopics] = useState<string[]>([])
  const [pets, setPets] = useState<Pet[]>(mockPets)
  const [selectedPetId, setSelectedPetId] = useState('')
  const [petSheet, setPetSheet] = useState(false)
  const [visibility, setVisibility] = useState<Visibility>('public')
  const [location, setLocation] = useState('')
  const [locationGeo, setLocationGeo] = useState<{ latitude: number; longitude: number } | null>(null)
  const [saveDraftEnabled, setSaveDraftEnabled] = useState(false)
  const [visSheet, setVisSheet] = useState(false)
  const [success, setSuccess] = useState(false)
  const [submitting, setSubmitting] = useState(false)
  const { media, replaceMedia, addImages, removeMedia } = useUploadMedia([])
  const draftRestoredRef = useRef(false)
  const draftPetSelectionExplicitRef = useRef(false)

  const selectedPet = pets.find(p => p._id === selectedPetId)

  const restoreDraft = (draft: PublishDraft) => {
    const draftTopics = Array.isArray(draft.topics) ? draft.topics : []
    setContent(draft.content || '')
    setSelectedTopics(draftTopics)
    setTopics(current => {
      const merged = [...current]
      draftTopics.forEach(topic => {
        if (topic && !merged.includes(topic)) merged.push(topic)
      })
      return merged
    })
    replaceMedia(Array.isArray(draft.media) ? draft.media : [])
    draftPetSelectionExplicitRef.current = Boolean(draft.petSelectionExplicit || draft.petId === null || draft.petId)
    if (typeof draft.petId === 'string') {
      setSelectedPetId(draft.petId)
    } else if (draft.petSelectionExplicit || draft.petId === null) {
      setSelectedPetId('')
    }
    setLocation(draft.locationText || '')
    setLocationGeo(
      typeof draft.latitude === 'number' && typeof draft.longitude === 'number'
        ? { latitude: draft.latitude, longitude: draft.longitude }
        : null
    )
    setVisibility(draft.visibility || 'public')
    setSaveDraftEnabled(Boolean(draft.saveDraft))
  }

  useEffect(() => {
    getPetList().then(list => {
      setPets(list)
      // Default to the first pet for convenience; user can change or clear it.
      if (list[0]?._id) {
        setSelectedPetId(prev => prev || (draftRestoredRef.current && draftPetSelectionExplicitRef.current ? '' : list[0]._id))
      }
    })
  }, [])

  useEffect(() => {
    let cancelled = false
    getDraft()
      .then(res => {
        const draft = res.draft
        if (cancelled || !hasDraftContent(draft)) return

        draftRestoredRef.current = true
        restoreDraft(draft)
      })
      .catch(() => undefined)

    return () => {
      cancelled = true
    }
  }, [])

  const toggleTopic = (topic: string) => {
    setSelectedTopics(current => (current.includes(topic) ? current.filter(item => item !== topic) : [...current, topic]))
  }

  const addCustomTopic = () => {
    Taro.showModal({
      title: '自定义话题',
      editable: true,
      placeholderText: '如 周末出游',
      success: (res: any) => {
        if (!res.confirm) return
        const t = (res.content || '').trim().replace(/^#/, '').slice(0, 12)
        if (!t) return
        setTopics(cur => (cur.includes(t) ? cur : [...cur, t]))
        setSelectedTopics(cur => (cur.includes(t) ? cur : [...cur, t]))
      }
    } as any)
  }

  const pickLocation = async () => {
    if (location) {
      // Already set — let the user clear it or re-pick.
      const res = await Taro.showActionSheet({ itemList: ['重新选择位置', '清除位置'] }).catch(() => null)
      if (!res) return
      if (res.tapIndex === 1) {
        setLocation('')
        setLocationGeo(null)
        return
      }
    }
    try {
      const res = await Taro.chooseLocation({})
      if (res && (res.name || res.address)) {
        setLocation(res.name || res.address)
        setLocationGeo({ latitude: res.latitude, longitude: res.longitude })
      }
    } catch (e: any) {
      const msg = String(e?.errMsg || '')
      if (msg.includes('cancel')) return // user cancelled the map — stay silent
      if (msg.includes('auth') || msg.includes('deny')) {
        Taro.showModal({
          title: '需要位置权限',
          content: '请在右上角「···」→ 设置中打开位置权限后重试',
          showCancel: false
        })
        return
      }
      Taro.showToast({ title: '无法打开地图选点', icon: 'none' })
    }
  }

  const textLength = content.trim().length
  const hasContent = textLength > 0 || media.length > 0
  const canSubmit = hasContent && (media.length > 0 || isValidPostContent(content)) && textLength <= 2000

  const buildDraft = (uploadedMedia: typeof media, shouldSaveDraft: boolean): PublishDraft => ({
    content,
    topics: selectedTopics,
    media: uploadedMedia,
    petId: selectedPetId || null,
    petSelectionExplicit: true,
    locationText: location,
    latitude: locationGeo?.latitude,
    longitude: locationGeo?.longitude,
    visibility,
    saveDraft: shouldSaveDraft
  })

  const showUploadFailure = async (error: unknown) => {
    if (!isUploadPostMediaError(error)) return false

    const failedIndexes = error.failedItems
      .map(item => media.findIndex(current => current.id === item.id) + 1)
      .filter(index => index > 0)

    await Taro.showModal({
      title: '图片上传失败',
      content: failedIndexes.length
        ? `第 ${failedIndexes.join('、')} 张图片上传失败，请重试或重新选择后再发布。`
        : '有图片上传失败，请重试或重新选择后再发布。',
      showCancel: false,
      confirmText: '知道了'
    })
    return true
  }

  const saveCurrentDraftAndLeave = async () => {
    if (submitting) return
    if (!(await ensureProfileReady())) return
    setSubmitting(true)
    try {
      const uploadedMedia = await uploadPostMedia(media)
      await saveDraft(buildDraft(uploadedMedia, true))
      Taro.showToast({ title: '已存草稿', icon: 'success' })
      setTimeout(() => Taro.navigateBack(), 600)
    } catch (error) {
      if (await showUploadFailure(error)) return
      Taro.showToast({ title: '保存失败，请重试', icon: 'none' })
    } finally {
      setSubmitting(false)
    }
  }

  const handleClose = async () => {
    if (submitting) return
    if (!hasContent) {
      Taro.navigateBack()
      return
    }

    const res = await Taro.showModal({
      title: '保存草稿？',
      content: '当前内容尚未发布，是否保存为草稿后离开？',
      cancelText: '不保存',
      confirmText: '保存'
    })

    if (res.confirm) {
      await saveCurrentDraftAndLeave()
      return
    }

    Taro.navigateBack()
  }

  const submit = async () => {
    if (submitting) return
    if (!(await ensureProfileReady())) return
    if (!hasContent) {
      Taro.showToast({ title: '写点什么或加张图片吧', icon: 'none' })
      return
    }
    if (!canSubmit) {
      Taro.showToast({ title: '正文最多 2000 字', icon: 'none' })
      return
    }
    setSubmitting(true)
    try {
      const uploadedMedia = await uploadPostMedia(media)
      const draft = buildDraft(uploadedMedia, saveDraftEnabled)

      // Draft mode saves only — it does not publish to the plaza.
      if (saveDraftEnabled) {
        await saveDraft(draft)
        Taro.showToast({ title: '已存草稿', icon: 'success' })
        setTimeout(() => Taro.navigateBack(), 600)
        return
      }

      await createPost(draft)
      setSuccess(true)
    } catch (error) {
      if (await showUploadFailure(error)) return
      Taro.showToast({ title: saveDraftEnabled ? '保存失败，请重试' : '发布失败，请重试', icon: 'none' })
    } finally {
      setSubmitting(false)
    }
  }

  return (
    <View className='publish-page'>
      <View className='publish-nav' style={{ paddingTop: `${statusBarHeight}px`, paddingRight: `${menuRight}px` }}>
        <View className='publish-nav__row'>
          <View className='publish-nav__leading'>
            <View className='publish-page__close' onClick={handleClose}>
              <PublishIcon name='close' size={22} />
            </View>
          </View>
          <Text className='publish-nav__title'>发布动态</Text>
        </View>
      </View>
      <ScrollView scrollY className='publish-page__scroll' enhanced showScrollbar={false}>
        <PublishComposer user={user || mockProfile} value={content} onChange={setContent} />
        <MediaGrid media={media} onAdd={addImages} onRemove={removeMedia} />

        <View className='publish-page__label-row'>
          <Text className='publish-page__label'>话题</Text>
          <Text className='publish-page__custom' onClick={addCustomTopic}>+ 自定义</Text>
        </View>
        <View className='publish-page__topics'>
          {topics.map(topic => (
            <PublishChip
              key={topic}
              active={selectedTopics.includes(topic)}
              prefix={selectedTopics.includes(topic) ? '×' : '+'}
              onClick={() => toggleTopic(topic)}
            >
              #{topic}
            </PublishChip>
          ))}
        </View>

        <PublishOptions
          pet={selectedPet}
          visibility={visibility}
          saveDraft={saveDraftEnabled}
          location={location}
          onPetClick={() => setPetSheet(true)}
          onLocationClick={pickLocation}
          onVisibilityClick={() => setVisSheet(true)}
          onDraftChange={setSaveDraftEnabled}
        />

        <View className='publish-page__notice'>
          <PublishIcon name='info' size={14} />
          <Text>分享到广场需遵守汪圈社区公约。请勿发布违规内容,文明养宠。</Text>
        </View>
      </ScrollView>

      <ComposerToolbar
        count={content.length}
        disabled={!canSubmit || submitting}
        label={saveDraftEnabled ? '存草稿' : '发布'}
        onToolClick={tool => {
          if (tool === 'image') addImages()
          if (tool === 'location') pickLocation()
          if (tool === 'topic') addCustomTopic()
        }}
        onSubmit={submit}
      />
      <PetPickerSheet
        visible={petSheet}
        pets={pets}
        selectedId={selectedPetId}
        onSelect={id => {
          setSelectedPetId(id)
          setPetSheet(false)
        }}
        onClose={() => setPetSheet(false)}
      />
      <VisibilitySheet visible={visSheet} value={visibility} onChange={setVisibility} onClose={() => setVisSheet(false)} />
      <SuccessModal
        visible={success}
        onStay={() => setSuccess(false)}
        onGoPlaza={() => { requestTab('plaza'); Taro.navigateBack() }}
      />
    </View>
  )
}
