import { NextRequest, NextResponse } from 'next/server';
import { Pool } from 'pg';
import { getAuvikClient } from '@/lib/services/auvik-factory';
import { AuvikTenantMapping } from '@/lib/types/auvik';

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,
});

export async function GET(request: NextRequest) {
  try {
    const searchParams = request.nextUrl.searchParams;
    const includeUnmapped = searchParams.get('includeUnmapped') === 'true';

    // Get all mappings from database
    const result = await pool.query<{
      id: number;
      auvik_tenant_id: string;
      auvik_tenant_name: string;
      autotask_company_id: number;
      autotask_company_name: string;
      created_at: string;
      updated_at: string;
    }>('SELECT * FROM auvik_tenant_mappings ORDER BY auvik_tenant_name');

    const mappings: AuvikTenantMapping[] = result.rows.map((row) => ({
      id: row.id,
      auvikTenantId: row.auvik_tenant_id,
      auvikTenantName: row.auvik_tenant_name,
      autotaskCompanyId: row.autotask_company_id,
      autotaskCompanyName: row.autotask_company_name,
      createdAt: row.created_at,
      updatedAt: row.updated_at,
    }));

    // If includeUnmapped is true, fetch all Auvik tenants and merge
    if (includeUnmapped) {
      const auvikClient = getAuvikClient();
      const allTenants = await auvikClient.getTenants();
      
      // Populate auvik_tenants table with all tenants
      for (const tenant of allTenants) {
        try {
          await pool.query(
            `INSERT INTO auvik_tenants (tenant_id, tenant_name, domain_prefix, last_sync_at)
             VALUES ($1, $2, $3, CURRENT_TIMESTAMP)
             ON CONFLICT (tenant_id) DO UPDATE SET
               tenant_name = EXCLUDED.tenant_name,
               domain_prefix = EXCLUDED.domain_prefix,
               last_sync_at = CURRENT_TIMESTAMP,
               updated_at = CURRENT_TIMESTAMP`,
            [tenant.id, tenant.domainPrefix, tenant.domainPrefix]
          );
        } catch (err) {
          console.error(`Failed to upsert tenant ${tenant.id}:`, err);
        }
      }
      
      const mappedTenantIds = new Set(mappings.map((m) => m.auvikTenantId));
      
      const unmappedTenants = allTenants
        .filter((t) => !mappedTenantIds.has(t.id))
        .map((t) => ({
          id: 0, // Temporary ID for unmapped
          auvikTenantId: t.id,
          auvikTenantName: t.domainPrefix,
          autotaskCompanyId: 0,
          autotaskCompanyName: '',
          createdAt: '',
          updatedAt: '',
        }));

      return NextResponse.json({
        mappings: [...mappings, ...unmappedTenants],
        totalMapped: mappings.length,
        totalUnmapped: unmappedTenants.length,
      });
    }

    return NextResponse.json({ mappings });
  } catch (error) {
    console.error('Error fetching tenant mappings:', error);
    return NextResponse.json(
      { error: 'Failed to fetch tenant mappings' },
      { status: 500 }
    );
  }
}

export async function POST(request: NextRequest) {
  try {
    const body = await request.json();
    const {
      auvikTenantId,
      auvikTenantName,
      autotaskCompanyId,
      autotaskCompanyName,
    } = body;

    if (!auvikTenantId || !autotaskCompanyId) {
      return NextResponse.json(
        { error: 'Missing required fields' },
        { status: 400 }
      );
    }

    // Insert or update mapping
    const result = await pool.query<{
      id: number;
      auvik_tenant_id: string;
      auvik_tenant_name: string;
      autotask_company_id: number;
      autotask_company_name: string;
      created_at: string;
      updated_at: string;
    }>(
      `INSERT INTO auvik_tenant_mappings 
        (auvik_tenant_id, auvik_tenant_name, autotask_company_id, autotask_company_name)
       VALUES ($1, $2, $3, $4)
       ON CONFLICT (auvik_tenant_id) 
       DO UPDATE SET 
         autotask_company_id = EXCLUDED.autotask_company_id,
         autotask_company_name = EXCLUDED.autotask_company_name,
         updated_at = CURRENT_TIMESTAMP
       RETURNING *`,
      [auvikTenantId, auvikTenantName, autotaskCompanyId, autotaskCompanyName]
    );

    const mapping: AuvikTenantMapping = {
      id: result.rows[0].id,
      auvikTenantId: result.rows[0].auvik_tenant_id,
      auvikTenantName: result.rows[0].auvik_tenant_name,
      autotaskCompanyId: result.rows[0].autotask_company_id,
      autotaskCompanyName: result.rows[0].autotask_company_name,
      createdAt: result.rows[0].created_at,
      updatedAt: result.rows[0].updated_at,
    };

    return NextResponse.json({ mapping });
  } catch (error) {
    console.error('Error creating tenant mapping:', error);
    return NextResponse.json(
      { error: 'Failed to create tenant mapping' },
      { status: 500 }
    );
  }
}

export async function DELETE(request: NextRequest) {
  try {
    const searchParams = request.nextUrl.searchParams;
    const id = searchParams.get('id');

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

    await pool.query('DELETE FROM auvik_tenant_mappings WHERE id = $1', [
      parseInt(id),
    ]);

    return NextResponse.json({ success: true });
  } catch (error) {
    console.error('Error deleting tenant mapping:', error);
    return NextResponse.json(
      { error: 'Failed to delete tenant mapping' },
      { status: 500 }
    );
  }
}
