import { NextRequest, NextResponse } from 'next/server';
import { db } from '@/lib/db';
import { spanAnnotations, candles } from '@/lib/db/schema';
import { eq } from 'drizzle-orm';

function toUnix(d: Date): number {
  return Math.floor(d.getTime() / 1000);
}

export async function GET(request: NextRequest) {
  try {
    const searchParams = request.nextUrl.searchParams;
    const chartId = searchParams.get('chartId');
    const format = searchParams.get('format') || 'json';
    const contextPadding = parseInt(searchParams.get('context_padding') || '10', 10);

    if (!chartId) {
      return NextResponse.json({ error: 'chartId is required' }, { status: 400 });
    }

    const chartIdNum = parseInt(chartId, 10);
    if (isNaN(chartIdNum)) {
      return NextResponse.json(
        { error: 'Invalid parameter: chartId must be an integer' },
        { status: 400 }
      );
    }

    if (isNaN(contextPadding)) {
      return NextResponse.json(
        { error: 'Invalid parameter: context_padding must be an integer' },
        { status: 400 }
      );
    }

    // Fetch span annotations for the chart
    const spans = await db
      .select()
      .from(spanAnnotations)
      .where(eq(spanAnnotations.chart_id, chartIdNum))
      .orderBy(spanAnnotations.start_time);

    // Fetch candles for the chart
    const chartCandles = await db
      .select()
      .from(candles)
      .where(eq(candles.chart_id, chartIdNum))
      .orderBy(candles.time);

    if (format === 'json') {
      // Raw Annotations JSON export
      const exportData = {
        chart_id: chartIdNum,
        export_date: new Date().toISOString(),
        total_spans: spans.length,
        spans: spans.map((span) => ({
          id: span.id,
          start_time: toUnix(span.start_time),
          end_time: toUnix(span.end_time),
          label: span.label,
          confidence: span.confidence,
          outcome: span.outcome,
          notes: span.notes,
          sub_spans: span.sub_spans,
          color: span.color,
          created_at: toUnix(span.created_at),
        })),
        summary: {
          labels: spans.reduce((acc, span) => {
            acc[span.label] = (acc[span.label] || 0) + 1;
            return acc;
          }, {} as Record<string, number>),
        },
      };

      return NextResponse.json(exportData, {
        headers: {
          'Content-Disposition': `attachment; filename="span-annotations-${chartId}.json"`,
        },
      });
    } else if (format === 'windowed') {
      // Windowed Classification CSV
      const csvRows: string[] = [
        'span_id,label,confidence,outcome,start_time,end_time,context_start,context_end,' +
          'candle_time,open,high,low,close,position',
      ];

      for (const span of spans) {
        const spanStart = toUnix(span.start_time);
        const spanEnd = toUnix(span.end_time);

        // Add context padding (assuming 1-minute candles)
        const contextStart = spanStart - contextPadding * 60;
        const contextEnd = spanEnd + contextPadding * 60;

        const contextCandles = chartCandles.filter((c) => {
          const t = toUnix(c.time);
          return t >= contextStart && t <= contextEnd;
        });

        // Create one row per candle in the context window
        contextCandles.forEach((candle) => {
          const candleTime = toUnix(candle.time);
          const position =
            candleTime >= spanStart && candleTime <= spanEnd ? 'span' : 'context';

          csvRows.push(
            [
              span.id,
              span.label,
              span.confidence || '',
              span.outcome || '',
              spanStart,
              spanEnd,
              contextStart,
              contextEnd,
              candleTime,
              candle.open,
              candle.high,
              candle.low,
              candle.close,
              position,
            ].join(',')
          );
        });
      }

      const csvContent = csvRows.join('\n');

      return new NextResponse(csvContent, {
        headers: {
          'Content-Type': 'text/csv',
          'Content-Disposition': `attachment; filename="span-annotations-windowed-${chartId}.csv"`,
        },
      });
    } else if (format === 'bio') {
      // BIO-tagged CSV — one row per candle, with BIO tags for each label type

      // Get all unique labels
      const labelTypes = Array.from(new Set(spans.map((s) => s.label)));

      // Pre-compute unix times for spans
      const spansUnix = spans.map((s) => ({
        ...s,
        startUnix: toUnix(s.start_time),
        endUnix: toUnix(s.end_time),
      }));

      // Create header
      const header = ['time', 'open', 'high', 'low', 'close'];
      labelTypes.forEach((label) => header.push(`bio_${label}`));

      const csvRows: string[] = [header.join(',')];

      // Process each candle
      chartCandles.forEach((candle) => {
        const candleTime = toUnix(candle.time);
        const row = [
          candleTime.toString(),
          candle.open.toString(),
          candle.high.toString(),
          candle.low.toString(),
          candle.close.toString(),
        ];

        // For each label type, determine BIO tag
        labelTypes.forEach((label) => {
          const spansWithLabel = spansUnix.filter((s) => s.label === label);

          let bioTag = 'O'; // Outside by default

          for (const span of spansWithLabel) {
            if (candleTime >= span.startUnix && candleTime <= span.endUnix) {
              bioTag = candleTime === span.startUnix ? `B-${label}` : `I-${label}`;
              break;
            }
          }

          row.push(bioTag);
        });

        csvRows.push(row.join(','));
      });

      const csvContent = csvRows.join('\n');

      return new NextResponse(csvContent, {
        headers: {
          'Content-Type': 'text/csv',
          'Content-Disposition': `attachment; filename="span-annotations-bio-${chartId}.csv"`,
        },
      });
    } else {
      return NextResponse.json({ error: 'Invalid format. Use json, windowed, or bio' }, { status: 400 });
    }
  } catch (error) {
    console.error('Export error:', error);
    return NextResponse.json({ error: 'Failed to export span annotations' }, { status: 500 });
  }
}
