import { Button } from '@/components/ui/button'
import {
  Card,
  CardContent,
  CardDescription,
  CardFooter,
  CardHeader,
  CardTitle
} from '@/components/ui/card'
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
import cashuTokenService, { TCashuToken, TokenScope } from '@/services/cashu-token.service'
import { useNostr } from '@/providers/NostrProvider'
import { Clock, Copy, Key, RefreshCw, Shield } from 'lucide-react'
import { useCallback, useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { toast } from 'sonner'
import QrCode from '../QrCode'
import dayjs from 'dayjs'
import relativeTime from 'dayjs/plugin/relativeTime'
import * as utils from '@noble/curves/abstract/utils'

dayjs.extend(relativeTime)

interface TokenDisplayProps {
  bunkerPubkey: string
  mintUrl: string
}

export default function TokenDisplay({ bunkerPubkey, mintUrl }: TokenDisplayProps) {
  const { t } = useTranslation()
  const { signHttpAuth, pubkey } = useNostr()
  const [currentToken, setCurrentToken] = useState<TCashuToken | null>(null)
  const [nextToken, setNextToken] = useState<TCashuToken | null>(null)
  const [loading, setLoading] = useState(false)
  const [refreshing, setRefreshing] = useState(false)

  // Load tokens on mount
  useEffect(() => {
    const stored = cashuTokenService.loadTokens(bunkerPubkey)
    if (stored) {
      setCurrentToken(stored.current || null)
      setNextToken(stored.next || null)
    }
  }, [bunkerPubkey])

  // Request a new token
  const requestToken = useCallback(async () => {
    if (!pubkey) {
      toast.error(t('You must be logged in to request a token'))
      return
    }

    setLoading(true)
    try {
      cashuTokenService.setMint(mintUrl)
      await cashuTokenService.fetchMintInfo()

      const userPubkey = utils.hexToBytes(pubkey)
      const token = await cashuTokenService.requestToken(
        TokenScope.NIP46,
        userPubkey,
        signHttpAuth,
        [24133] // NIP-46 kind
      )

      // Store the token
      if (currentToken && cashuTokenService.verifyToken(currentToken)) {
        // Current still valid, store new as next
        cashuTokenService.storeTokens(bunkerPubkey, currentToken, token)
        setNextToken(token)
      } else {
        // Current expired or missing, use new as current
        cashuTokenService.storeTokens(bunkerPubkey, token)
        setCurrentToken(token)
        setNextToken(null)
      }

      toast.success(t('Token obtained successfully'))
    } catch (err) {
      toast.error(t('Failed to get token') + ': ' + (err as Error).message)
    } finally {
      setLoading(false)
    }
  }, [bunkerPubkey, mintUrl, pubkey, signHttpAuth, currentToken, t])

  // Refresh tokens (promote next to current if needed)
  const refreshTokens = useCallback(async () => {
    if (!pubkey) return

    setRefreshing(true)
    try {
      // Check if current needs refresh
      if (currentToken && cashuTokenService.needsRefresh(currentToken)) {
        // Request a new token as next
        if (!nextToken) {
          await requestToken()
        }
      }

      // Promote next to current if current expired
      const now = Date.now() / 1000
      if (currentToken && currentToken.expiry <= now && nextToken) {
        cashuTokenService.storeTokens(bunkerPubkey, nextToken)
        setCurrentToken(nextToken)
        setNextToken(null)
        toast.info(t('Token rotated'))
      }
    } finally {
      setRefreshing(false)
    }
  }, [bunkerPubkey, currentToken, nextToken, pubkey, requestToken, t])

  // Copy token to clipboard
  const copyToken = useCallback(
    (token: TCashuToken) => {
      const encoded = cashuTokenService.encodeToken(token)
      navigator.clipboard.writeText(encoded)
      toast.success(t('Token copied to clipboard'))
    },
    [t]
  )

  // Format expiry time
  const formatExpiry = (expiry: number) => {
    const date = dayjs.unix(expiry)
    const now = dayjs()
    if (date.isBefore(now)) {
      return t('Expired')
    }
    return date.fromNow()
  }

  // Check if token is expired
  const isExpired = (token: TCashuToken) => {
    return token.expiry < Date.now() / 1000
  }

  return (
    <Card>
      <CardHeader>
        <CardTitle className="flex items-center gap-2">
          <Shield className="h-5 w-5" />
          {t('Access Tokens')}
        </CardTitle>
        <CardDescription>
          {t('Cashu tokens for authenticated bunker access')}
        </CardDescription>
      </CardHeader>

      <CardContent>
        {!currentToken && !nextToken ? (
          <div className="text-center py-8">
            <Key className="h-12 w-12 mx-auto text-muted-foreground mb-4" />
            <p className="text-muted-foreground mb-4">
              {t('No tokens available. Request one to enable bunker access.')}
            </p>
            <Button onClick={requestToken} disabled={loading}>
              {loading ? t('Requesting...') : t('Request Token')}
            </Button>
          </div>
        ) : (
          <Tabs defaultValue="current" className="w-full">
            <TabsList className="grid w-full grid-cols-2">
              <TabsTrigger value="current" className="relative">
                {t('Current')}
                {currentToken && isExpired(currentToken) && (
                  <span className="absolute top-1 right-1 h-2 w-2 rounded-full bg-destructive" />
                )}
              </TabsTrigger>
              <TabsTrigger value="next">
                {t('Next')}
                {nextToken && (
                  <span className="absolute top-1 right-1 h-2 w-2 rounded-full bg-green-500" />
                )}
              </TabsTrigger>
            </TabsList>

            <TabsContent value="current" className="space-y-4">
              {currentToken ? (
                <TokenCard
                  token={currentToken}
                  formatExpiry={formatExpiry}
                  isExpired={isExpired(currentToken)}
                  onCopy={() => copyToken(currentToken)}
                />
              ) : (
                <div className="text-center py-4 text-muted-foreground">
                  {t('No current token')}
                </div>
              )}
            </TabsContent>

            <TabsContent value="next" className="space-y-4">
              {nextToken ? (
                <TokenCard
                  token={nextToken}
                  formatExpiry={formatExpiry}
                  isExpired={isExpired(nextToken)}
                  onCopy={() => copyToken(nextToken)}
                />
              ) : (
                <div className="text-center py-4 text-muted-foreground">
                  {t('No pending token. One will be requested before current expires.')}
                </div>
              )}
            </TabsContent>
          </Tabs>
        )}
      </CardContent>

      <CardFooter className="flex gap-2">
        <Button variant="outline" onClick={refreshTokens} disabled={refreshing} className="flex-1">
          <RefreshCw className={`h-4 w-4 mr-2 ${refreshing ? 'animate-spin' : ''}`} />
          {t('Refresh')}
        </Button>
        <Button onClick={requestToken} disabled={loading} className="flex-1">
          {loading ? t('Requesting...') : t('Request New Token')}
        </Button>
      </CardFooter>
    </Card>
  )
}

// Individual token display card
function TokenCard({
  token,
  formatExpiry,
  isExpired,
  onCopy
}: {
  token: TCashuToken
  formatExpiry: (expiry: number) => string
  isExpired: boolean
  onCopy: () => void
}) {
  const { t } = useTranslation()
  const encoded = cashuTokenService.encodeToken(token)

  return (
    <div className="space-y-4">
      <div className="flex justify-center">
        <QrCode value={encoded} size={200} />
      </div>

      <div className="space-y-2 text-sm">
        <div className="flex items-center justify-between">
          <span className="text-muted-foreground">{t('Scope')}</span>
          <span className="font-mono">{token.scope}</span>
        </div>

        <div className="flex items-center justify-between">
          <span className="text-muted-foreground">{t('Keyset')}</span>
          <span className="font-mono text-xs">{token.keysetId}</span>
        </div>

        <div className="flex items-center justify-between">
          <span className="text-muted-foreground flex items-center gap-1">
            <Clock className="h-3 w-3" />
            {t('Expires')}
          </span>
          <span className={isExpired ? 'text-destructive' : 'text-green-600'}>
            {formatExpiry(token.expiry)}
          </span>
        </div>

        {token.kinds && token.kinds.length > 0 && (
          <div className="flex items-center justify-between">
            <span className="text-muted-foreground">{t('Kinds')}</span>
            <span className="font-mono text-xs">{token.kinds.join(', ')}</span>
          </div>
        )}
      </div>

      <Button variant="outline" onClick={onCopy} className="w-full">
        <Copy className="h-4 w-4 mr-2" />
        {t('Copy Token')}
      </Button>
    </div>
  )
}
