import { useCallback, useEffect, useState } from 'react'
import type { Review, Article } from '@/types/nostr'
import { getReviewsForArticle } from '@/lib/reviews'
import { getReviewTipsForArticle } from '@/lib/reviewAggregation'
import { ReviewForm } from './ReviewForm'
import { ReviewTipForm } from './ReviewTipForm'
import { t } from '@/lib/i18n'

interface ArticleReviewsProps {
  article: Article
  authorPubkey: string
}

export function ArticleReviews({ article, authorPubkey }: ArticleReviewsProps): React.ReactElement {
  const data = useArticleReviewsData({ articleId: article.id, authorPubkey })
  const reviewForm = useReviewFormState({ reload: data.reload })
  const tipSelection = useReviewTipSelection({ article, reviews: data.reviews, reload: data.reload })

  return (
    <div className="border border-neon-cyan/30 rounded-lg p-4 bg-cyber-dark space-y-4">
      <ArticleReviewsHeader tips={data.tips} onAddReview={reviewForm.open} />
      {reviewForm.show && (
        <ReviewForm
          article={article}
          onSuccess={reviewForm.onSuccess}
          onCancel={reviewForm.close}
        />
      )}
      {data.loading && <p className="text-sm text-cyber-accent">{t('common.loading')}</p>}
      {data.error && <p className="text-sm text-red-400">{data.error}</p>}
      {!data.loading && !data.error && data.reviews.length === 0 && !reviewForm.show && (
        <p className="text-sm text-cyber-accent/70">{t('review.empty')}</p>
      )}
      {!data.loading && !data.error && <ArticleReviewsList reviews={data.reviews} onTipReview={tipSelection.select} />}
      <SelectedReviewTipForm selection={tipSelection} />
    </div>
  )
}

interface ReviewTipSelectionController {
  article: Article
  selectedReviewForTip: Review | null
  onTipSuccess: () => void
  clear: () => void
  select: (reviewId: string) => void
}

interface ArticleReviewsData {
  reviews: Review[]
  tips: number
  loading: boolean
  error: string | null
  reload: () => Promise<void>
}

function useArticleReviewsData({
  articleId,
  authorPubkey,
}: {
  articleId: string
  authorPubkey: string
}): ArticleReviewsData {
  const [reviews, setReviews] = useState<Review[]>([])
  const [tips, setTips] = useState<number>(0)
  const [loading, setLoading] = useState(false)
  const [error, setError] = useState<string | null>(null)

  const reload = useCallback(async (): Promise<void> => {
    setLoading(true)
    setError(null)
    try {
      const [list, tipsTotal] = await Promise.all([
        getReviewsForArticle(articleId),
        getReviewTipsForArticle({ authorPubkey, articleId }),
      ])
      setReviews(list)
      setTips(tipsTotal)
    } catch (loadError) {
      setError(loadError instanceof Error ? loadError.message : 'Erreur lors du chargement des critiques')
    } finally {
      setLoading(false)
    }
  }, [articleId, authorPubkey])

  useEffect(() => {
    void reload()
  }, [reload])

  return {
    reviews,
    tips,
    loading,
    error,
    reload,
  }
}

function useReviewFormState({ reload }: { reload: () => Promise<void> }): {
  show: boolean
  open: () => void
  close: () => void
  onSuccess: () => void
} {
  const [show, setShow] = useState(false)
  const open = useCallback((): void => setShow(true), [])
  const close = useCallback((): void => setShow(false), [])

  const onSuccess = useCallback((): void => {
    close()
    void reload()
  }, [close, reload])

  return { show, open, close, onSuccess }
}

function useReviewTipSelection({
  article,
  reviews,
  reload,
}: {
  article: Article
  reviews: Review[]
  reload: () => Promise<void>
}): ReviewTipSelectionController {
  const [selectedReviewId, setSelectedReviewId] = useState<string | null>(null)

  const select = useCallback((reviewId: string): void => setSelectedReviewId(reviewId), [])
  const clear = useCallback((): void => setSelectedReviewId(null), [])

  const onTipSuccess = useCallback((): void => {
    clear()
    void reload()
  }, [clear, reload])

  const selectedReviewForTip = selectedReviewId ? findReviewById(reviews, selectedReviewId) : null

  return { article, selectedReviewForTip, onTipSuccess, clear, select }
}

function findReviewById(reviews: Review[], reviewId: string): Review | null {
  const review = reviews.find((r) => r.id === reviewId)
  return review ?? null
}

function SelectedReviewTipForm({ selection }: { selection: ReviewTipSelectionController }): React.ReactElement | null {
  if (!selection.selectedReviewForTip) {
    return null
  }

  return (
    <ReviewTipForm
      review={selection.selectedReviewForTip}
      article={selection.article}
      onSuccess={selection.onTipSuccess}
      onCancel={selection.clear}
    />
  )
}

function ArticleReviewsHeader({ tips, onAddReview }: { tips: number; onAddReview: () => void }): React.ReactElement {
  return (
    <div className="flex items-center justify-between">
      <h3 className="text-lg font-semibold text-neon-cyan">{t('review.title')}</h3>
      <div className="flex items-center gap-4">
        <span className="text-sm text-cyber-accent/70">{t('review.tips.total', { amount: tips })}</span>
        <button
          onClick={onAddReview}
          className="px-3 py-1 text-sm bg-neon-green/20 hover:bg-neon-green/30 text-neon-green rounded-lg font-medium transition-all border border-neon-green/50"
        >
          {t('review.add')}
        </button>
      </div>
    </div>
  )
}

function ArticleReviewsList({ reviews, onTipReview }: { reviews: Review[]; onTipReview: (reviewId: string) => void }): React.ReactElement {
  return (
    <div className="space-y-4">
      {reviews.map((r) => (
        <div key={r.id} className="border-t border-neon-cyan/20 pt-4 space-y-2">
          {r.title && (
            <h4 className="font-semibold text-neon-cyan">{r.title}</h4>
          )}
          <div className="text-cyber-accent whitespace-pre-wrap">{r.content}</div>
          {r.text && (
            <div className="text-sm text-cyber-accent/70 italic border-l-2 border-neon-cyan/30 pl-3">
              {r.text}
            </div>
          )}
          <div className="text-xs text-cyber-accent/50 flex gap-2 items-center">
            <span>{t('review.reviewer')}: {formatPubkey(r.reviewerPubkey)}</span>
            <span>•</span>
            <span>{formatDate(r.createdAt)}</span>
            <button
              onClick={() => {
                onTipReview(r.id)
              }}
              className="ml-auto px-2 py-1 text-xs bg-neon-green/20 hover:bg-neon-green/30 text-neon-green rounded transition-all border border-neon-green/50"
            >
              {t('review.tip.button')}
            </button>
          </div>
        </div>
      ))}
    </div>
  )
}

function formatPubkey(pubkey: string): string {
  return `${pubkey.slice(0, 8)}...${pubkey.slice(-8)}`
}

function formatDate(timestamp: number): string {
  return new Date(timestamp * 1000).toLocaleString()
}
