import { useEffect, useState } from 'react'
import { Link, useParams } from 'react-router'
import {
  listPublicPublications, listPublicPosts,
  listSubscriptions, subscribe, unsubscribe,
  type Post, type Publication,
} from '~/lib/api-client'
import { useAuth } from '~/lib/auth-context'
import ProfileHeader from '~/components/ProfileHeader'
import PostList from '~/components/PostList'
import CenteredMessage from '~/components/CenteredMessage'
import PageLayout from '~/components/PageLayout'
import Spinner from '~/components/Spinner'
import { ArrowLongLeftIcon, RssIcon } from '@heroicons/react/24/outline'
import type { AppBskyActorDefs } from '@atproto/api'
import type { Route } from './+types/pub'
import { SITE_NAME } from '~/lib/site-config'

export function meta({ params }: Route.MetaArgs) {
  return [{ title: `${params.userId} — ${SITE_NAME}` }]
}

export default function Pub() {
  const { userId: id, rkey } = useParams<{ userId: string; rkey: string }>()
  const { session } = useAuth()
  const [profile, setProfile] = useState<AppBskyActorDefs.ProfileViewDetailed | null>(null)
  const [publication, setPublication] = useState<Publication | null>(null)
  const [posts, setPosts] = useState<Post[] | null>(null)
  const [error, setError] = useState<string | null>(null)
  const [postsError, setPostsError] = useState<string | null>(null)
  const [subscriptionRkey, setSubscriptionRkey] = useState<string | null | undefined>(undefined)
  const [loading, setLoading] = useState(false)
  const [copied, setCopied] = useState(false)

  useEffect(() => {
    if (!id || !rkey) return
    setProfile(null)
    setPublication(null)
    setPosts(null)
    setError(null)
    setPostsError(null)
    setSubscriptionRkey(undefined)

    let cancelled = false

    async function load() {
      const actor = id!.startsWith('@') ? id!.slice(1) : id!

      try {
        const res = await fetch(
          `https://api.bsky.app/xrpc/app.bsky.actor.getProfile?actor=${encodeURIComponent(actor)}`,
        )
        if (!res.ok) throw new Error(res.status === 400 ? 'Profile not found' : `Failed to load profile (${res.status})`)
        const profileData = (await res.json()) as AppBskyActorDefs.ProfileViewDetailed
        if (cancelled) return
        setProfile(profileData)

        const { did } = profileData
        const pubAtUri = `at://${did}/site.standard.publication/${rkey}`

        let pubLink = document.head.querySelector<HTMLLinkElement>('link[rel="site.standard.publication"]')
        if (!pubLink) {
          pubLink = document.createElement('link')
          pubLink.rel = 'site.standard.publication'
          document.head.appendChild(pubLink)
        }
        pubLink.href = pubAtUri

        const fetchPub = async () => {
          try {
            const pubs = await listPublicPublications(did)
            const pub = pubs.find((p) => p.atUri === pubAtUri) ?? null
            if (!cancelled) setPublication(pub)
          } catch {
            if (!cancelled) setError('Failed to load publication')
          }
        }

        const fetchPosts = async () => {
          try {
            const all = await listPublicPosts(did)
            if (!cancelled) setPosts(all.filter((p) => p.site === pubAtUri))
          } catch {
            if (!cancelled) setPostsError('Failed to load posts')
          }
        }

        const fetchSub = session && session.sub !== did
          ? listSubscriptions(session)
              .then((subs) => {
                if (cancelled) return
                const found = subs.find((s) => s.publicationAtUri === pubAtUri)
                setSubscriptionRkey(found?.rkey ?? null)
              })
              .catch(() => { if (!cancelled) setSubscriptionRkey(null) })
          : Promise.resolve()

        await Promise.all([fetchPub(), fetchPosts(), fetchSub])
      } catch (err) {
        if (!cancelled) setError(err instanceof Error ? err.message : 'Failed to load publication')
      }
    }

    load()
    return () => {
      cancelled = true
      document.head.querySelector('link[rel="site.standard.publication"]')?.remove()
    }
  }, [id, rkey, session])

  async function handleSubscribe(pub: Publication) {
    if (!session) return
    setLoading(true)
    try {
      const key = await subscribe(session, pub.atUri)
      setSubscriptionRkey(key)
    } catch {
      // non-fatal
    } finally {
      setLoading(false)
    }
  }

  async function handleUnsubscribe(pub: Publication) {
    if (!session || !subscriptionRkey) return
    setLoading(true)
    try {
      await unsubscribe(session, subscriptionRkey)
      setSubscriptionRkey(null)
    } catch {
      // non-fatal
    } finally {
      setLoading(false)
    }
  }

  if (error) {
    return <CenteredMessage message={error} error action={{ label: 'Back to profile', to: `/${id}` }} />
  }

  if (!profile || publication === null) {
    return (
      <div className="flex-1 flex items-center justify-center">
        <Spinner />
      </div>
    )
  }

  if (!publication) {
    return <CenteredMessage message="Publication not found." error action={{ label: 'Back to profile', to: `/${id}` }} />
  }

  const showSubscribeButton = !!session && session.sub !== profile.did
  const isSubscribed = !!subscriptionRkey
  const isSameOrigin = new URL(publication.url).origin === window.location.origin

  async function handleCopyFeed() {
    const feedUrl = `${publication!.url.replace(/\/$/, '')}/feed.xml`
    try {
      await navigator.clipboard.writeText(feedUrl)
      setCopied(true)
      setTimeout(() => setCopied(false), 2500)
    } catch { /* ignore */ }
  }

  return (
    <PageLayout>
      <div className="w-full max-w-2xl mx-auto px-4 py-8 space-y-8">
        <Link to={`/${profile.handle}`}>
          <ArrowLongLeftIcon className="size-8 text-stone-400 hover:text-stone-700 dark:hover:text-stone-200 transition-colors" />
        </Link>

        <ProfileHeader profile={profile} linkTo={`/${profile.handle}`} />

        <div className="space-y-2">
          <div className="flex items-start justify-between gap-4">
            <div className="min-w-0">
              <h1 className="font-display text-2xl font-semibold text-stone-900 dark:text-white">{publication.name}</h1>
              <p className="text-sm text-stone-400 dark:text-stone-500 mt-1">{new URL(publication.url).host}</p>
              {publication.description && (
                <p className="text-stone-600 dark:text-stone-300 mt-2">{publication.description}</p>
              )}
              {copied && (
                <p className="text-xs text-green-600 dark:text-green-400 mt-1">
                  Feed URL copied — paste into your RSS reader
                </p>
              )}
            </div>
            <div className="shrink-0 flex items-center gap-2">
              {isSameOrigin && (
                <button
                  onClick={handleCopyFeed}
                  title="Copy Atom feed URL"
                  className="p-1.5 rounded-md text-stone-400 dark:text-stone-500 hover:text-orange-500 dark:hover:text-orange-400 hover:bg-stone-100 dark:hover:bg-stone-800 transition-colors"
                >
                  <RssIcon className="h-4 w-4" />
                </button>
              )}
              {showSubscribeButton && (
                <button
                  onClick={() => isSubscribed ? handleUnsubscribe(publication) : handleSubscribe(publication)}
                  disabled={loading || subscriptionRkey === undefined}
                  className={`text-sm px-4 py-1.5 rounded-full transition-colors disabled:opacity-50 ${
                    isSubscribed
                      ? 'border border-stone-300 dark:border-stone-600 text-stone-600 dark:text-stone-300 hover:border-stone-400 dark:hover:border-stone-500 hover:bg-stone-50 dark:hover:bg-stone-800/50'
                      : 'bg-stone-900 dark:bg-stone-100 text-stone-50 dark:text-stone-900 hover:bg-stone-700 dark:hover:bg-stone-200'
                  }`}
                >
                  {loading ? (isSubscribed ? 'Unsubscribing…' : 'Subscribing…') : (isSubscribed ? 'Subscribed' : 'Subscribe')}
                </button>
              )}
            </div>
          </div>
        </div>

        <PostList posts={posts} handle={profile.handle ?? id!} error={postsError} />
      </div>
    </PageLayout>
  )
}
