import { NextRequest, NextResponse } from 'next/server';
import { nodeService } from '@/services/database';
import { Node, NodeFilters } from '@/types/database';
import { autoEmbedQueue } from '@/services/embedding/autoEmbedQueue';
import { hasSufficientContent } from '@/services/embedding/constants';
import { DimensionService } from '@/services/database/dimensionService';
import { generateDescription } from '@/services/database/descriptionService';
import { scheduleAutoEdgeCreation } from '@/services/agents/autoEdge';

export const runtime = 'nodejs';

export async function GET(request: NextRequest) {
  try {
    const searchParams = request.nextUrl.searchParams;
    
    const filters: NodeFilters = {
      search: searchParams.get('search') || undefined,
      limit: searchParams.get('limit') ? parseInt(searchParams.get('limit')!) : 100,
      offset: searchParams.get('offset') ? parseInt(searchParams.get('offset')!) : 0
    };

    // Handle dimensions parameter (comma-separated)
    const dimensionsParam = searchParams.get('dimensions');
    if (dimensionsParam) {
      filters.dimensions = dimensionsParam.split(',').map(dim => dim.trim()).filter(Boolean);
    }

    // Handle sortBy parameter
    const sortByParam = searchParams.get('sortBy');
    if (sortByParam === 'edges' || sortByParam === 'updated') {
      filters.sortBy = sortByParam;
    }

    const nodes = await nodeService.getNodes(filters);
    
    return NextResponse.json({
      success: true,
      data: nodes,
      count: nodes.length
    });
  } catch (error) {
    console.error('Error fetching nodes:', error);
    
    return NextResponse.json({
      success: false,
      error: error instanceof Error ? error.message : 'Failed to fetch nodes'
    }, { status: 500 });
  }
}

export async function POST(request: NextRequest) {
  try {
    const body = await request.json();
    
    // Validate required fields
    if (!body.title) {
      return NextResponse.json({
        success: false,
        error: 'Missing required field: title is required'
      }, { status: 400 });
    }

    const rawContent = typeof body.content === 'string' ? body.content : null;

    // Process provided dimensions first (needed for description generation)
    const providedDimensions = Array.isArray(body.dimensions) ? body.dimensions : [];
    const trimmedProvidedDimensions = providedDimensions
      .map((dim: unknown) => typeof dim === 'string' ? dim.trim() : '')
      .filter(Boolean)
      .slice(0, 8);

    // Generate description with all available context
    let nodeDescription: string | undefined;
    try {
      nodeDescription = await generateDescription({
        title: body.title,
        content: rawContent || undefined,
        link: body.link || undefined,
        metadata: body.metadata,
        type: body.type,
        dimensions: trimmedProvidedDimensions
      });
    } catch (error) {
      console.error('Error generating description:', error);
      // Continue without description - dimension assignment will use content as fallback
    }

    // Auto-assign locked dimensions + keyword dimensions for all new nodes
    const { locked, keywords } = await DimensionService.assignDimensions({
      title: body.title,
      content: rawContent || undefined,
      link: body.link,
      description: nodeDescription
    });

    // Ensure keyword dimensions exist in the database (create if new)
    for (const keyword of keywords) {
      await DimensionService.ensureKeywordDimension(keyword);
    }

    // Combine provided, locked, and keyword dimensions, remove duplicates
    const finalDimensions = [...new Set([...trimmedProvidedDimensions, ...locked, ...keywords])]
      .slice(0, 8); // max 8 total
    const rawChunk = typeof body.chunk === 'string' ? body.chunk : null;
    let chunkToStore = rawChunk;
    let chunkStatus: Node['chunk_status'];

    if (chunkToStore && chunkToStore.trim().length > 0) {
      chunkStatus = 'not_chunked';
    } else if (!chunkToStore && hasSufficientContent(rawContent)) {
      chunkToStore = rawContent;
      chunkStatus = 'not_chunked';
    }

    const node = await nodeService.createNode({
      title: body.title,
      description: nodeDescription,
      content: rawContent ?? undefined,
      link: body.link,
      dimensions: finalDimensions,
      chunk: chunkToStore ?? undefined,
      chunk_status: chunkStatus,
      metadata: body.metadata || {}
    });

    if (chunkStatus === 'not_chunked' && node.id) {
      autoEmbedQueue.enqueue(node.id, { reason: 'node_created' });
    }

    // Schedule auto-edge creation (fire-and-forget, non-blocking)
    if (node.id) {
      scheduleAutoEdgeCreation(node.id);
    }

    return NextResponse.json({
      success: true,
      data: node,
      message: `Node created successfully with dimensions: ${finalDimensions.join(', ')}`
    }, { status: 201 });
  } catch (error) {
    console.error('Error creating node:', error);
    
    return NextResponse.json({
      success: false,
      error: error instanceof Error ? error.message : 'Failed to create node'
    }, { status: 500 });
  }
}
