import { NextRequest, NextResponse } from 'next/server';
import { Pool } from 'pg';
import { getDattoRMMClient } from '@/lib/services/datto-rmm-factory';
import { DattoRMMSite } from '@/lib/types/datto-rmm';

const pool = new Pool({
  host: process.env.POSTGRES_HOST,
  port: parseInt(process.env.POSTGRES_PORT || '5432'),
  database: process.env.POSTGRES_DB,
  user: process.env.POSTGRES_USER,
  password: process.env.POSTGRES_PASSWORD,
});

interface RMMSiteMapping {
  id: number;
  company_id: number;
  company_name?: string;
  rmm_site_uid: string;
  rmm_site_name: string;
  is_primary: boolean;
  device_count: number;
  notes: string | null;
  last_sync_at: string | null;
  created_at: string;
  updated_at: string;
  created_by: string | null;
}

// GET /api/rmm/site-mappings
// Get all RMM site mappings, optionally including unmapped sites
export async function GET(request: NextRequest) {
  try {
    const searchParams = request.nextUrl.searchParams;
    const includeUnmapped = searchParams.get('includeUnmapped') === 'true';
    const companyId = searchParams.get('companyId');

    // Get all existing mappings
    let query = `
      SELECT 
        rsm.id,
        rsm.company_id,
        rsm.rmm_site_uid,
        rsm.rmm_site_name,
        rsm.is_primary,
        rsm.device_count,
        rsm.notes,
        rsm.last_sync_at,
        rsm.created_at,
        rsm.updated_at,
        rsm.created_by,
        c.company_name
      FROM rmm_site_mappings rsm
      JOIN companies c ON c.id = rsm.company_id
    `;
    
    const queryParams: any[] = [];
    
    if (companyId) {
      query += ' WHERE rsm.company_id = $1';
      queryParams.push(companyId);
    }
    
    query += ' ORDER BY c.company_name, rsm.rmm_site_name';
    
    const mappingsResult = await pool.query(query, queryParams);
    const mappings = mappingsResult.rows;

    if (!includeUnmapped) {
      return NextResponse.json({ mappings });
    }

    // Get all RMM sites from the RMM API
    const rmmClient = getDattoRMMClient();
    const allSites = await rmmClient.getSites();

    // Populate rmm_sites table with all sites
    for (const site of allSites) {
      try {
        await pool.query(
          `INSERT INTO rmm_sites (site_uid, site_name, last_sync_at)
           VALUES ($1, $2, CURRENT_TIMESTAMP)
           ON CONFLICT (site_uid) DO UPDATE SET
             site_name = EXCLUDED.site_name,
             last_sync_at = CURRENT_TIMESTAMP,
             updated_at = CURRENT_TIMESTAMP`,
          [site.uid, site.name]
        );
      } catch (err) {
        console.error(`Failed to upsert site ${site.uid}:`, err);
      }
    }

    // Get list of already mapped site UIDs
    const mappedSiteUids = new Set(mappings.map((m: any) => m.rmm_site_uid));

    // Create mapping entries for unmapped sites
    const unmappedSites = allSites
      .filter((site: DattoRMMSite) => !mappedSiteUids.has(site.uid))
      .map((site: DattoRMMSite) => ({
        id: null,
        company_id: null,
        company_name: null,
        rmm_site_uid: site.uid,
        rmm_site_name: site.name,
        is_primary: false,
        device_count: 0,
        notes: null,
        last_sync_at: null,
        created_at: null,
        updated_at: null,
        created_by: null,
      }));

    // Combine mapped and unmapped sites
    const allMappings = [...mappings, ...unmappedSites];

    // Sort by mapping status (mapped first), then by site name
    allMappings.sort((a, b) => {
      if (a.company_id && !b.company_id) return -1;
      if (!a.company_id && b.company_id) return 1;
      return (a.rmm_site_name || '').localeCompare(b.rmm_site_name || '');
    });

    return NextResponse.json({ 
      mappings: allMappings,
      stats: {
        total: allMappings.length,
        mapped: mappings.length,
        unmapped: unmappedSites.length
      }
    });
  } catch (error) {
    console.error('Error fetching RMM site mappings:', error);
    return NextResponse.json(
      { error: 'Failed to fetch RMM site mappings' },
      { status: 500 }
    );
  }
}

// POST /api/rmm/site-mappings
// Create or update an RMM site mapping
export async function POST(request: NextRequest) {
  try {
    const body = await request.json();
    const { 
      rmmSiteUid, 
      rmmSiteName, 
      companyId, 
      companyName,
      isPrimary = false,
      notes = null,
      createdBy = 'system'
    } = body;

    if (!rmmSiteUid || !rmmSiteName || !companyId) {
      return NextResponse.json(
        { error: 'Missing required fields: rmmSiteUid, rmmSiteName, and companyId are required' },
        { status: 400 }
      );
    }

    // If setting as primary, unset other primary sites for this company
    if (isPrimary) {
      await pool.query(
        'UPDATE rmm_site_mappings SET is_primary = false WHERE company_id = $1',
        [companyId]
      );
    }

    // Insert or update the mapping
    const query = `
      INSERT INTO rmm_site_mappings (
        company_id, 
        rmm_site_uid, 
        rmm_site_name, 
        is_primary, 
        notes, 
        created_by
      )
      VALUES ($1, $2, $3, $4, $5, $6)
      ON CONFLICT (company_id, rmm_site_uid)
      DO UPDATE SET
        rmm_site_name = EXCLUDED.rmm_site_name,
        is_primary = EXCLUDED.is_primary,
        notes = EXCLUDED.notes,
        updated_at = CURRENT_TIMESTAMP
      RETURNING *
    `;

    const result = await pool.query(query, [
      companyId,
      rmmSiteUid,
      rmmSiteName,
      isPrimary,
      notes,
      createdBy
    ]);

    return NextResponse.json({
      success: true,
      mapping: result.rows[0]
    });
  } catch (error) {
    console.error('Error saving RMM site mapping:', error);
    return NextResponse.json(
      { error: 'Failed to save RMM site mapping' },
      { status: 500 }
    );
  }
}

// DELETE /api/rmm/site-mappings
// Delete an RMM site mapping
export async function DELETE(request: NextRequest) {
  try {
    const searchParams = request.nextUrl.searchParams;
    const id = searchParams.get('id');

    if (!id) {
      return NextResponse.json(
        { error: 'Missing required parameter: id' },
        { status: 400 }
      );
    }

    const result = await pool.query(
      'DELETE FROM rmm_site_mappings WHERE id = $1 RETURNING *',
      [id]
    );

    if (result.rowCount === 0) {
      return NextResponse.json(
        { error: 'Mapping not found' },
        { status: 404 }
      );
    }

    return NextResponse.json({
      success: true,
      deleted: result.rows[0]
    });
  } catch (error) {
    console.error('Error deleting RMM site mapping:', error);
    return NextResponse.json(
      { error: 'Failed to delete RMM site mapping' },
      { status: 500 }
    );
  }
}

// PUT /api/rmm/site-mappings/bulk
// Create multiple mappings at once
export async function PUT(request: NextRequest) {
  try {
    const body = await request.json();
    const { mappings, createdBy = 'system' } = body;

    if (!mappings || !Array.isArray(mappings)) {
      return NextResponse.json(
        { error: 'Missing required field: mappings (array)' },
        { status: 400 }
      );
    }

    const client = await pool.connect();
    try {
      await client.query('BEGIN');

      const results = [];
      for (const mapping of mappings) {
        const { 
          rmmSiteUid, 
          rmmSiteName, 
          companyId, 
          isPrimary = false,
          notes = null
        } = mapping;

        if (!rmmSiteUid || !rmmSiteName || !companyId) {
          await client.query('ROLLBACK');
          return NextResponse.json(
            { error: 'Each mapping must have rmmSiteUid, rmmSiteName, and companyId' },
            { status: 400 }
          );
        }

        // If setting as primary, unset other primary sites for this company
        if (isPrimary) {
          await client.query(
            'UPDATE rmm_site_mappings SET is_primary = false WHERE company_id = $1',
            [companyId]
          );
        }

        const result = await client.query(
          `
          INSERT INTO rmm_site_mappings (
            company_id, 
            rmm_site_uid, 
            rmm_site_name, 
            is_primary, 
            notes, 
            created_by
          )
          VALUES ($1, $2, $3, $4, $5, $6)
          ON CONFLICT (company_id, rmm_site_uid)
          DO UPDATE SET
            rmm_site_name = EXCLUDED.rmm_site_name,
            is_primary = EXCLUDED.is_primary,
            notes = EXCLUDED.notes,
            updated_at = CURRENT_TIMESTAMP
          RETURNING *
          `,
          [companyId, rmmSiteUid, rmmSiteName, isPrimary, notes, createdBy]
        );

        results.push(result.rows[0]);
      }

      await client.query('COMMIT');

      return NextResponse.json({
        success: true,
        mappings: results
      });
    } catch (error) {
      await client.query('ROLLBACK');
      throw error;
    } finally {
      client.release();
    }
  } catch (error) {
    console.error('Error saving bulk RMM site mappings:', error);
    return NextResponse.json(
      { error: 'Failed to save bulk RMM site mappings' },
      { status: 500 }
    );
  }
}
