/**
 * API endpoint to fetch Discord channels from database
 */
import sql from '../../../utils/db.ts';
import { requireApiAuth, createApiResponse } from '../../../utils/apiAuth.ts';
import {
  checkRateLimit,
  recordRequest,
} from '../../../utils/rateLimit.ts';
import { signImageId } from './cached-image.ts';
import type { APIContext } from 'astro';

interface ChannelRow {
  channel_id: string;
  name: string;
  type: number;
  position: number;
  parent_id: string | null;
  topic: string | null;
  guild_id: string;
  guild_name: string | null;
  guild_icon: string | null;
  guild_cached_icon_id: string | null;
  message_count: number;
}

export async function GET({ request }: APIContext): Promise<Response> {
  // Rate limit check
  const rateCheck = checkRateLimit(request, {
    limit: 60,
    windowMs: 1000,
    burstLimit: 240,
    burstWindowMs: 10_000,
  });

  if (!rateCheck.allowed) {
    return new Response(JSON.stringify({ 
      error: rateCheck.isFlooding ? 'Too many requests - please slow down' : 'Rate limit exceeded' 
    }), {
      status: 429,
      headers: { 'Content-Type': 'application/json', 'Retry-After': '1' },
    });
  }

  recordRequest(request, 1000);

  // Check authentication
  const { user, error: authError, setCookieHeader } = await requireApiAuth(request);
  if (authError) return authError;

  // Helper to validate Discord snowflake IDs (17-20 digit strings)
  const isValidSnowflake = (id: string | null): boolean => !id || /^\d{17,20}$/.test(id);

  try {
    const url = new URL(request.url);
    const guildId = url.searchParams.get('guildId');

    // Validate snowflake format
    if (!isValidSnowflake(guildId)) {
      return createApiResponse({ error: 'Invalid guildId format' }, 400);
    }

    let channels;
    
    // Channel types: 0=text, 2=voice, 4=category, 5=announcement, 10/11/12=threads
    // Fetch text channels (type 0), categories (type 4), and threads (types 10, 11, 12)
    
    if (guildId) {
      // Fetch channels for specific guild with message counts
      // Use LEFT JOIN with aggregated counts to avoid N+1 subqueries
      channels = await sql`
        WITH channel_counts AS (
          SELECT channel_id, COUNT(*) as message_count
          FROM messages
          WHERE is_deleted = FALSE
          GROUP BY channel_id
        )
        SELECT 
          c.channel_id,
          c.name,
          c.type,
          c.position,
          c.parent_id,
          c.topic,
          c.guild_id,
          g.name as guild_name,
          g.icon_url as guild_icon,
          g.cached_icon_id as guild_cached_icon_id,
          COALESCE(cc.message_count, 0) as message_count
        FROM channels c
        LEFT JOIN guilds g ON c.guild_id = g.guild_id
        LEFT JOIN channel_counts cc ON c.channel_id = cc.channel_id
        WHERE c.guild_id = ${guildId}
          AND c.type IN (0, 4, 10, 11, 12)
        ORDER BY c.position ASC, c.name ASC
      `;
    } else {
      // Fetch all text channels, categories, and threads with message counts
      // Use LEFT JOIN with aggregated counts to avoid N+1 subqueries
      channels = await sql`
        WITH channel_counts AS (
          SELECT channel_id, COUNT(*) as message_count
          FROM messages
          WHERE is_deleted = FALSE
          GROUP BY channel_id
        )
        SELECT 
          c.channel_id,
          c.name,
          c.type,
          c.position,
          c.parent_id,
          c.topic,
          c.guild_id,
          g.name as guild_name,
          g.icon_url as guild_icon,
          g.cached_icon_id as guild_cached_icon_id,
          COALESCE(cc.message_count, 0) as message_count
        FROM channels c
        LEFT JOIN guilds g ON c.guild_id = g.guild_id
        LEFT JOIN channel_counts cc ON c.channel_id = cc.channel_id
        WHERE c.type IN (0, 4, 10, 11, 12)
        ORDER BY g.name ASC, c.position ASC, c.name ASC
      `;
    }

    // Get base URL for cached image URLs
    const baseUrl = new URL(request.url).origin;

    // Transform to expected format
    const formattedChannels = channels.map(ch => {
      // Use cached icon URL if available, otherwise fall back to Discord CDN
      let guildIcon = ch.guild_icon;
      if (ch.guild_cached_icon_id) {
        const sig = signImageId(ch.guild_cached_icon_id);
        guildIcon = `${baseUrl}/api/discord/cached-image?id=${ch.guild_cached_icon_id}&sig=${sig}`;
      }

      return {
        id: ch.channel_id.toString(),
        name: ch.name,
        type: ch.type,
        position: ch.position,
        parentId: ch.parent_id?.toString() || null,
        topic: ch.topic || null,
        guildId: ch.guild_id?.toString() || null,
        guildName: ch.guild_name,
        guildIcon,
        messageCount: parseInt(ch.message_count) || 0,
      };
    });

    return createApiResponse(formattedChannels, 200, setCookieHeader);
  } catch (error) {
    console.error('Error fetching channels:', error);
    return createApiResponse({ error: 'Failed to fetch channels' }, 500, setCookieHeader);
  }
}
