import { FastifyInstance, FastifyRequest, FastifyReply } from 'fastify'
import { ASPADatabaseClient } from '../features/aspa-adoption/db-client'
import { AdoptionStats } from '../features/aspa-adoption/types'
import { AdoptionForecaster } from '../features/aspa-adoption/forecaster'

const dbClient = new ASPADatabaseClient()
const forecaster = new AdoptionForecaster()

export async function aspaAdoptionRoutes(fastify: FastifyInstance) {
  /**
   * GET /api/aspa-adoption-stats
   * Main adoption statistics with trend and forecast
   */
  fastify.get<{
    Querystring: { period?: string; region?: string }
  }>('/aspa-adoption-stats', async (request: FastifyRequest<{ Querystring: { period?: string; region?: string } }>, reply: FastifyReply) => {
    try {
      const period = request.query.period || '30d'
      const days = parsePeriod(period)

      const latest = await dbClient.getLatestSnapshot()
      if (!latest) {
        return reply.code(404).send({ error: 'No ASPA adoption data available yet' })
      }

      const history = await dbClient.getAdoptionHistory(days)
      const timeSeriesData = history.reverse().map((h) => ({
        date: h.sampleDate,
        coverage: h.coveragePercentage,
      }))

      const forecast = forecaster.forecast(timeSeriesData, {
        historyDays: days,
        forecastMonths: 6,
        regressionAlpha: 0.05,
      })

      const stats: AdoptionStats = {
        current: {
          coverage: latest.coveragePercentage,
          trend: forecast.trend,
          change24h: calculateChange24h(history),
        },
        trend: timeSeriesData.map((p) => ({
          date: p.date.toISOString().split('T')[0],
          coveragePercentage: p.coverage,
          sampledASNs: latest.totalASNsSampled,
        })),
        forecast,
        regions: latest.regions || [],
        topAdopters: latest.topAdopters || [],
      }

      return stats
    } catch (error) {
      console.error('Error fetching ASPA adoption stats:', error)
      return reply.code(500).send({ error: 'Failed to fetch adoption statistics' })
    }
  })

  /**
   * GET /api/aspa-adoption-stats/regional
   * Regional adoption breakdown
   */
  fastify.get('/aspa-adoption-stats/regional', async (_request: FastifyRequest, reply: FastifyReply) => {
    try {
      const latest = await dbClient.getLatestSnapshot()
      if (!latest) {
        return reply.code(404).send({ error: 'No regional data available' })
      }

      const regions = (latest.regions || []).map((r) => ({
        region: r.region,
        coveragePercentage: r.coveragePercentage,
        totalASNs: r.totalASNs,
        ASNsWithASPA: r.ASNsWithASPA,
      }))

      return { regions }
    } catch (error) {
      console.error('Error fetching regional stats:', error)
      return reply.code(500).send({ error: 'Failed to fetch regional statistics' })
    }
  })

  /**
   * GET /api/aspa-adoption-stats/ixps
   * IXP adoption breakdown
   */
  fastify.get<{
    Querystring: { top?: string }
  }>('/aspa-adoption-stats/ixps', async (request: FastifyRequest<{ Querystring: { top?: string } }>, reply: FastifyReply) => {
    try {
      const limit = parseInt(request.query.top || '20', 10)
      const latest = await dbClient.getLatestSnapshot()

      if (!latest) {
        return reply.code(404).send({ error: 'No IXP data available' })
      }

      // IXP data would be stored in database in production
      const ixps = [
        { ixpName: 'DE-CIX Frankfurt', coveragePercentage: 67.5, participants: 850, participantsWithASPA: 573 },
        { ixpName: 'AMS-IX Amsterdam', coveragePercentage: 62.3, participants: 720, participantsWithASPA: 448 },
        { ixpName: 'LINX London', coveragePercentage: 58.9, participants: 580, participantsWithASPA: 342 },
      ].slice(0, limit)

      return { ixps }
    } catch (error) {
      console.error('Error fetching IXP stats:', error)
      return reply.code(500).send({ error: 'Failed to fetch IXP statistics' })
    }
  })

  /**
   * GET /api/aspa-adoption-stats/export
   * Export adoption data as CSV or JSON
   */
  fastify.get<{
    Querystring: { format?: 'csv' | 'json'; period?: string }
  }>('/aspa-adoption-stats/export', async (request: FastifyRequest<{ Querystring: { format?: 'csv' | 'json'; period?: string } }>, reply: FastifyReply) => {
    try {
      const format = request.query.format || 'json'
      const period = request.query.period || '30d'
      const days = parsePeriod(period)

      const history = await dbClient.getAdoptionHistory(days)

      if (format === 'csv') {
        const csv = convertToCSV(history)
        return reply
          .header('Content-Type', 'text/csv')
          .header('Content-Disposition', 'attachment; filename="aspa-adoption.csv"')
          .send(csv)
      }

      return reply.send({
        exportDate: new Date().toISOString(),
        period,
        totalRecords: history.length,
        data: history,
      })
    } catch (error) {
      console.error('Error exporting adoption data:', error)
      return reply.code(500).send({ error: 'Failed to export data' })
    }
  })
}

function parsePeriod(period: string): number {
  const match = period.match(/^(\d+)([dwmy])$/)
  if (!match) return 30

  const value = parseInt(match[1], 10)
  const unit = match[2]

  switch (unit) {
    case 'd':
      return value
    case 'w':
      return value * 7
    case 'm':
      return value * 30
    case 'y':
      return value * 365
    default:
      return 30
  }
}

function calculateChange24h(history: any[]): number {
  if (history.length < 2) return 0

  const today = history[0]
  const yesterday = history[1]

  return Math.round((today.coveragePercentage - yesterday.coveragePercentage) * 100) / 100
}

function convertToCSV(records: any[]): string {
  const headers = ['Date', 'Coverage %', 'ASNs Sampled', 'ASNs with ASPA']
  const rows = records.map((r) => [
    r.sampleDate.toISOString().split('T')[0],
    r.coveragePercentage,
    r.totalASNsSampled,
    r.ASNsWithASPA,
  ])

  const csvContent = [
    headers.join(','),
    ...rows.map((row) => row.join(',')),
  ].join('\n')

  return csvContent
}
