import type { Client } from 'ssh2'
import { execCommand } from './common.js'

export interface LoginRecord {
  user: string
  ip: string
  time: string
  status: 'success' | 'failed'
}

export interface LoginStats {
  recentLogins: LoginRecord[]
  failedLogins: LoginRecord[]
  totalLogins: number
  uniqueIPs: number
}

export async function collectLoginStats(client: Client): Promise<LoginStats> {
  const recentLogins: LoginRecord[] = []
  const failedLogins: LoginRecord[] = []
  const ipSet = new Set<string>()

  try {
    const lastOut = await execCommand(client, "last -n 20 -F -w 2>/dev/null | grep -v 'reboot\\|wtmp' | head -20")
    const lines = lastOut.stdout.split('\n').map((l) => l.trim()).filter(Boolean)
    for (const line of lines) {
      const parts = line.split(/\s+/)
      if (parts.length < 10) continue
      const user = parts[0]
      const tty = parts[1]
      const ip = parts[2] === ':' || parts[2].startsWith(':') ? 'local' : parts[2]
      const dayIdx = parts.findIndex((p) => /^(Mon|Tue|Wed|Thu|Fri|Sat|Sun)/.test(p))
      if (dayIdx > 0 && parts.length > dayIdx + 4 && user && user !== 'wtmp' && tty !== 'system') {
        const timeStr = parts.slice(dayIdx, dayIdx + 5).join(' ')
        const date = new Date(timeStr)
        recentLogins.push({ user, ip, time: isNaN(date.getTime()) ? timeStr : date.toISOString(), status: 'success' })
        if (ip !== 'local') ipSet.add(ip)
      }
    }
  } catch {
    // best-effort
  }

  try {
    const failedOut = await execCommand(
      client,
      "grep 'Failed password' /var/log/auth.log 2>/dev/null | tail -10 || grep 'authentication failure' /var/log/secure 2>/dev/null | tail -10 || true",
    )
    const lines = failedOut.stdout.split('\n').map((l) => l.trim()).filter(Boolean)
    for (const line of lines) {
      const user = line.match(/for (?:invalid user )?(\S+)/)?.[1] ?? 'unknown'
      const ip = line.match(/from (\d+\.\d+\.\d+\.\d+)/)?.[1] ?? 'unknown'
      const dateMatch = line.match(/^(\w+)\s+(\d+)\s+(\d+:\d+:\d+)/)
      let time = 'unknown'
      if (dateMatch) {
        const [, month, day, t] = dateMatch
        const year = new Date().getFullYear()
        const candidate = new Date(`${month} ${day}, ${year} ${t}`)
        time = !isNaN(candidate.getTime()) ? candidate.toISOString() : `${month} ${day}, ${year} ${t}`
      }
      failedLogins.push({ user, ip, time, status: 'failed' })
      if (ip !== 'unknown') ipSet.add(ip)
    }
  } catch {
    // best-effort
  }

  return {
    recentLogins: recentLogins.slice(0, 10),
    failedLogins: failedLogins.slice(0, 10),
    totalLogins: recentLogins.length,
    uniqueIPs: ipSet.size,
  }
}
