import { NextRequest, NextResponse } from 'next/server';
import { Pool } from 'pg';
import { TimeEntry } from '@/lib/types/database';

// Initialize PostgreSQL connection
const pool = new Pool({
  host: process.env.POSTGRES_HOST,
  port: parseInt(process.env.POSTGRES_PORT || '5432'),
  database: process.env.POSTGRES_DB || 'pulse_autotask',
  user: process.env.POSTGRES_USER,
  password: process.env.POSTGRES_PASSWORD,
  ssl: process.env.POSTGRES_SSL === 'true' ? { rejectUnauthorized: false } : false,
});

export async function GET(request: NextRequest) {
  try {
    const { searchParams } = new URL(request.url);
    
    // Parse query parameters
    const limit = parseInt(searchParams.get('limit') || '100');
    const offset = parseInt(searchParams.get('offset') || '0');
    const search = searchParams.get('search') || '';
    const resourceId = searchParams.get('resource_id');
    const ticketId = searchParams.get('ticket_id');
    const taskId = searchParams.get('task_id');
    const projectId = searchParams.get('project_id');
    const companyId = searchParams.get('company_id');
    const startDate = searchParams.get('start_date');
    const endDate = searchParams.get('end_date');
    const sortBy = searchParams.get('sort_by') || 'entry_date';
    const sortOrder = searchParams.get('sort_order') || 'desc';
    const minHours = searchParams.get('min_hours');
    const maxHours = searchParams.get('max_hours');
    const billable = searchParams.get('billable');
    const approved = searchParams.get('approved');
    const hasTicket = searchParams.get('has_ticket');

    // Build WHERE conditions
    const conditions: string[] = ['te.is_deleted = false'];
    const params: any[] = [];
    let paramIndex = 1;

    // Add search condition (search in notes, title, internal_notes)
    if (search) {
      conditions.push(`(
        te.notes ILIKE $${paramIndex} OR 
        te.title ILIKE $${paramIndex} OR 
        te.internal_notes ILIKE $${paramIndex}
      )`);
      params.push(`%${search}%`);
      paramIndex++;
    }

    // Add filter conditions
    if (resourceId) {
      conditions.push(`te.resource_id = $${paramIndex}`);
      params.push(resourceId);
      paramIndex++;
    }

    if (ticketId) {
      conditions.push(`te.ticket_id = $${paramIndex}`);
      params.push(ticketId);
      paramIndex++;
    }

    if (taskId) {
      conditions.push(`te.task_id = $${paramIndex}`);
      params.push(taskId);
      paramIndex++;
    }

    if (projectId) {
      conditions.push(`te.project_id = $${paramIndex}`);
      params.push(projectId);
      paramIndex++;
    }

    if (companyId) {
      conditions.push(`te.company_id = $${paramIndex}`);
      params.push(companyId);
      paramIndex++;
    }

    if (startDate) {
      conditions.push(`te.entry_date >= $${paramIndex}`);
      params.push(startDate);
      paramIndex++;
    }

    if (endDate) {
      conditions.push(`te.entry_date <= $${paramIndex}`);
      params.push(endDate);
      paramIndex++;
    }

    if (minHours) {
      conditions.push(`te.hours_worked >= $${paramIndex}`);
      params.push(minHours);
      paramIndex++;
    }

    if (maxHours) {
      conditions.push(`te.hours_worked <= $${paramIndex}`);
      params.push(maxHours);
      paramIndex++;
    }

    if (billable !== null && billable !== undefined) {
      conditions.push(`te.billable = $${paramIndex}`);
      params.push(billable === 'true');
      paramIndex++;
    }

    if (approved !== null && approved !== undefined) {
      conditions.push(`te.approved = $${paramIndex}`);
      params.push(approved === 'true');
      paramIndex++;
    }

    if (hasTicket === 'true') {
      conditions.push(`te.ticket_id IS NOT NULL`);
    }

    // Validate sort column
    const validSortColumns = [
      'entry_date', 'hours_worked', 'created_at', 'updated_at',
      'resource_id', 'ticket_id', 'task_id', 'project_id', 'company_id',
      'title', 'billable', 'approved'
    ];
    const validSortBy = validSortColumns.includes(sortBy) ? sortBy : 'entry_date';
    const validSortOrder = sortOrder.toLowerCase() === 'asc' ? 'ASC' : 'DESC';

    // Build the main query
    const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';
    
    const query = `
      SELECT 
        te.id,
        te.resource_id,
        r.first_name || ' ' || r.last_name as resource_name,
        te.ticket_id,
        t.ticket_number,
        t.title as ticket_title,
        te.task_id,
        task.title as task_title,
        te.project_id,
        p.project_name,
        te.company_id,
        c.company_name,
        te.entry_date,
        te.hours_worked,
        te.notes,
        te.internal_notes,
        te.title,
        te.type,
        te.start_date_time,
        te.end_date_time,
        te.billable,
        te.billing_rate,
        te.approved,
        te.approved_date_time,
        te.non_billable,
        te.created_at,
        te.updated_at,
        te.synced_at
      FROM time_entries te
      LEFT JOIN resources r ON te.resource_id = r.id
      LEFT JOIN tickets t ON te.ticket_id = t.id
      LEFT JOIN tasks task ON te.task_id = task.id
      LEFT JOIN projects p ON te.project_id = p.id
      LEFT JOIN companies c ON te.company_id = c.id
      ${whereClause}
      ORDER BY te.${validSortBy} ${validSortOrder}
      LIMIT $${paramIndex} OFFSET $${paramIndex + 1}
    `;

    params.push(limit, offset);
    paramIndex += 2;

    // Get total count
    const countQuery = `
      SELECT COUNT(*) as total
      FROM time_entries te
      ${whereClause}
    `;

    const client = await pool.connect();
    
    try {
      // Execute both queries in parallel
      const [result, countResult] = await Promise.all([
        client.query(query, params),
        client.query(countQuery, params.slice(0, -2)) // Remove limit and offset for count
      ]);

      const timeEntries: TimeEntry[] = result.rows;
      const total = parseInt(countResult.rows[0].total);

      // Get summary statistics
      const summaryQuery = `
        SELECT 
          COUNT(*) as total_entries,
          SUM(hours_worked) as total_hours,
          AVG(hours_worked) as avg_hours,
          MIN(entry_date) as earliest_date,
          MAX(entry_date) as latest_date,
          COUNT(CASE WHEN billable = true THEN 1 END) as billable_entries,
          COUNT(CASE WHEN approved = true THEN 1 END) as approved_entries
        FROM time_entries te
        ${whereClause}
      `;

      const summaryResult = await client.query(summaryQuery, params.slice(0, -2));
      const summary = summaryResult.rows[0];

      return NextResponse.json({
        timeEntries,
        pagination: {
          total,
          limit,
          offset,
          hasMore: offset + limit < total,
        },
        summary: {
          totalEntries: parseInt(summary.total_entries),
          totalHours: parseFloat(summary.total_hours) || 0,
          averageHours: parseFloat(summary.avg_hours) || 0,
          earliestDate: summary.earliest_date,
          latestDate: summary.latest_date,
          billableEntries: parseInt(summary.billable_entries),
          approvedEntries: parseInt(summary.approved_entries),
        },
      });
    } finally {
      client.release();
    }
  } catch (error) {
    console.error('Error fetching time entries:', error);
    return NextResponse.json(
      { error: 'Failed to fetch time entries' },
      { status: 500 }
    );
  }
}

export async function POST(request: NextRequest) {
  try {
    const body = await request.json();
    
    // Validate required fields
    const requiredFields = ['resource_id', 'entry_date', 'hours_worked'];
    for (const field of requiredFields) {
      if (!body[field]) {
        return NextResponse.json(
          { error: `Missing required field: ${field}` },
          { status: 400 }
        );
      }
    }

    const client = await pool.connect();
    
    try {
      const query = `
        INSERT INTO time_entries (
          resource_id, ticket_id, task_id, project_id, company_id,
          entry_date, hours_worked, notes, internal_notes, title,
          type, start_date_time, end_date_time, billable,
          billing_rate, approved, approved_date_time, non_billable,
          created_at, updated_at, synced_at
        ) VALUES (
          $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, NOW(), NOW(), NOW()
        )
        RETURNING *
      `;

      const values = [
        body.resource_id,
        body.ticket_id || null,
        body.task_id || null,
        body.project_id || null,
        body.company_id || null,
        body.entry_date,
        body.hours_worked,
        body.notes || null,
        body.internal_notes || null,
        body.title || null,
        body.type || null,
        body.start_date_time || null,
        body.end_date_time || null,
        body.billable !== undefined ? body.billable : true,
        body.billing_rate || null,
        body.approved !== undefined ? body.approved : false,
        body.approved_date_time || null,
        body.non_billable !== undefined ? body.non_billable : false,
      ];

      const result = await client.query(query, values);
      const timeEntry: TimeEntry = result.rows[0];

      return NextResponse.json({ timeEntry }, { status: 201 });
    } finally {
      client.release();
    }
  } catch (error) {
    console.error('Error creating time entry:', error);
    return NextResponse.json(
      { error: 'Failed to create time entry' },
      { status: 500 }
    );
  }
}
