import { formatABN } from "@/lib/abn-utils";
import { NextRequest, NextResponse } from 'next/server';
import { isValidABN, cleanABN } from '@/lib/abn-utils';
import { checkRateLimit, getClientIP, createRateLimitResponse } from '@/lib/rate-limit';

/**
 * ABN Lookup API Route — GET /api/abn-lookup?abn=XXXXXXXXXXX
 *
 * Validates the ABN locally (checksum), then calls the ABR JSON endpoint
 * to fetch entity details.
 *
 * ABR JSON docs: https://abr.business.gov.au/json/
 * Registration:  https://abr.business.gov.au/Tools/WebServices
 *
 * Required env var:
 *   ABR_GUID — the authentication GUID issued after registration
 *
 * Optional env var:
 *   ABR_DEV_MODE — set to 'true' to enable development mode with mock data
 */

// ── ABR configuration ──────────────────────────────────────────────
const ABR_JSON_URL = 'https://abr.business.gov.au/json/AbnDetails.aspx';
const ABR_GUID = process.env.ABR_GUID ?? '';
const ABR_DEV_MODE = process.env.ABR_DEV_MODE === 'true' || process.env.NODE_ENV === 'development';

// ── Types ──────────────────────────────────────────────────────────

/** Shape returned by the ABR JSON endpoint (JSONP-unwrapped). */
interface ABRJsonResponse {
  Abn: string;
  AbnStatus: string;
  AbnStatusEffectiveFrom: string;
  Acn: string;
  AddressDate: string | null;
  AddressPostcode: string;
  AddressState: string;
  BusinessName: Array<string | { Value: string; EffectiveFrom: string }>;
  EntityName: string;
  EntityTypeCode: string;
  EntityTypeName: string;
  Gst: string | null;
  Message: string;
}

/** Director verification result */
interface DirectorVerification {
  status: 'pending' | 'verified' | 'mismatch' | 'not_available';
  message: string;
  requiresManualReview?: boolean;
}

/** Company data from ABR */
interface CompanyData {
  name: string;
  abn: string;
  status: string;
  statusDate: string;
  state: string;
  postcode: string;
  type: string;
  typeCode: string;
  gstRegistered: boolean;
  acn?: string;
  directorVerification?: DirectorVerification;
}

/** Our normalised response. */
interface ABNLookupResult {
  success: boolean;
  data?: CompanyData;
  error?: string;
  devMode?: boolean;
}

// ── Development Mode Mock Data ─────────────────────────────────────

/**
 * Mock company data for development when ABR_GUID is not configured.
 * Uses obviously fake ABNs to prevent confusion with real data.
 */
const MOCK_COMPANIES: Record<string, CompanyData> = {
  // Test ABN for development - passes checksum but is obviously fake
  '51824753556': {
    name: 'TEST COMPANY PTY LTD (Dev Mode)',
    abn: '51 824 753 556',
    status: 'Active',
    statusDate: '2020-01-01',
    state: 'NSW',
    postcode: '2000',
    type: 'Australian Private Company',
    typeCode: 'PRV',
    gstRegistered: true,
    directorVerification: {
      status: 'not_available',
      message: 'Director verification unavailable in development mode',
    },
  },
  // Another test ABN
  '34241177887': {
    name: 'EXAMPLE BUILDERS PTY LTD (Dev Mode)',
    abn: '34 241 177 887',
    status: 'Active',
    statusDate: '2019-06-15',
    state: 'VIC',
    postcode: '3000',
    type: 'Australian Private Company',
    typeCode: 'PRV',
    gstRegistered: true,
    directorVerification: {
      status: 'not_available',
      message: 'Director verification unavailable in development mode',
    },
  },
};

/**
 * Generate mock data for any valid ABN in development mode.
 */
function generateMockData(abn: string): CompanyData {
  const formatted = formatABN(abn);
  return {
    name: `MOCK COMPANY ${abn.slice(-4)} PTY LTD (Dev Mode)`,
    abn: formatted,
    status: 'Active',
    statusDate: new Date().toISOString().split('T')[0],
    state: 'NSW',
    postcode: '2000',
    type: 'Australian Private Company',
    typeCode: 'PRV',
    gstRegistered: Math.random() > 0.3,
    directorVerification: {
      status: 'not_available',
      message: 'Director verification unavailable in development mode. Register at https://abr.business.gov.au/Tools/WebServices',
    },
  };
}

// ── Helpers ────────────────────────────────────────────────────────

function buildABRUrl(abn: string): string {
  const params = new URLSearchParams({
    abn,
    guid: ABR_GUID,
    callback: 'cbr',
  });
  return `${ABR_JSON_URL}?${params.toString()}`;
}

function stripJSONP(jsonp: string): ABRJsonResponse {
  const match = jsonp.match(/^cbr\((.*)\)$/);
  if (!match) throw new Error('Unexpected ABR response format');
  return JSON.parse(match[1]);
}

function normaliseABRResponse(abr: ABRJsonResponse): CompanyData {
  const name = abr.EntityName || 
    (Array.isArray(abr.BusinessName) && abr.BusinessName[0]) || 
    'Unknown';

  return {
    name: typeof name === 'string' ? name : (name as any).Value || 'Unknown',
    abn: formatABN(abr.Abn),
    status: abr.AbnStatus,
    statusDate: abr.AbnStatusEffectiveFrom,
    state: abr.AddressState,
    postcode: abr.AddressPostcode,
    type: abr.EntityTypeName,
    typeCode: abr.EntityTypeCode,
    gstRegistered: abr.Gst !== null,
    acn: abr.Acn || undefined,
    // Director verification will be done separately via ASIC
    directorVerification: {
      status: 'pending',
      message: 'Director verification pending. ASIC lookup required.',
      requiresManualReview: true,
    },
  };
}

/**
 * ASIC Director Verification (Stub)
 * 
 * ASIC Connect API requires paid subscription.
 * For MVP, we flag all signups for manual review.
 * 
 * Future implementation:
 * - Call ASIC Connect API to get director list
 * - Cross-reference user email/name with director records
 * - Auto-verify if match found
 * - Flag for manual review if no match
 * 
 * @see https://connectonline.asic.gov.au/
 */
async function verifyDirector(
  abn: string, 
  acn?: string, 
  userEmail?: string
): Promise<DirectorVerification> {
  // TODO: Implement ASIC Connect API integration
  // For now, flag all for manual review
  
  console.log(`[ASIC] Director verification requested for ABN ${abn}, ACN ${acn || 'N/A'}`);
  
  return {
    status: 'pending',
    message: 'Director verification requires manual review. ASIC integration pending.',
    requiresManualReview: true,
  };
}

// ── Route Handler ──────────────────────────────────────────────────

// Rate limit: 10 requests per 15 minutes per IP (external API call)
const ABN_LOOKUP_RATE_LIMIT = 10;
const ABN_LOOKUP_WINDOW_MS = 15 * 60 * 1000;

export async function GET(request: NextRequest) {
  try {
    // --- 0. Rate limiting ---------------------------------------------------
    const clientIP = getClientIP(request);
    const rateLimit = checkRateLimit(`abn-lookup:${clientIP}`, ABN_LOOKUP_RATE_LIMIT, ABN_LOOKUP_WINDOW_MS);
    
    if (!rateLimit.allowed) {
      const retryAfter = Math.ceil((rateLimit.resetTime - Date.now()) / 1000);
      return createRateLimitResponse(clientIP, retryAfter);
    }
    
    const searchParams = request.nextUrl.searchParams;
    const rawABN = searchParams.get('abn');
    const userEmail = searchParams.get('email'); // Optional: for director verification

    // --- 1. Validate input --------------------------------------------------
    if (!rawABN) {
      return NextResponse.json({ 
        success: false, 
        error: 'Missing query parameter: abn' 
      }, { status: 400 });
    }

    const abn = cleanABN(rawABN);
    if (!isValidABN(abn)) {
      return NextResponse.json({ 
        success: false, 
        error: 'Invalid ABN format. Please check the number and try again.' 
      }, { status: 400 });
    }

    // --- 2. Check if ABR_GUID is configured --------------------------------
    const isGuidConfigured = ABR_GUID && 
      ABR_GUID !== 'REGISTER-TOMORROW-AT-ABR-BUSINESS-GOV-AU' &&
      ABR_GUID !== 'temporary-abr-guid-for-build';

    if (!isGuidConfigured) {
      // Development mode: return mock data
      if (ABR_DEV_MODE) {
        console.log(`[ABN Lookup] Dev mode - returning mock data for ${abn}`);
        const mockData = MOCK_COMPANIES[abn] || generateMockData(abn);
        return NextResponse.json({
          success: true,
          data: mockData,
          devMode: true,
        });
      }

      // Production without GUID: return error with validation info
      return NextResponse.json({
        success: false,
        error: 'ABR service not configured',
        devMode: false,
      }, { status: 503 });
    }

    // --- 3. Call ABR web service -------------------------------------------
    const url = buildABRUrl(abn);
    const abrResponse = await fetch(url, {
      method: 'GET',
      headers: { 'User-Agent': 'RateRight/1.0' },
      signal: AbortSignal.timeout(10000),
    });

    if (!abrResponse.ok) {
      const text = await abrResponse.text();
      console.error(`[ABN Lookup] ABR error ${abrResponse.status}:`, text);
      return NextResponse.json({
        success: false,
        error: `ABR service error: ${abrResponse.status}`,
      }, { status: 502 });
    }

    const jsonpText = await abrResponse.text();
    const abrData = stripJSONP(jsonpText);

    // --- 4. Handle ABR business logic ---------------------------------------
    if (abrData.Message) {
      return NextResponse.json({ 
        success: false, 
        error: abrData.Message 
      }, { status: 404 });
    }

    const result = normaliseABRResponse(abrData);

    // --- 5. Director verification (async, non-blocking) --------------------
    if (result.acn || userEmail) {
      result.directorVerification = await verifyDirector(
        abn, 
        result.acn, 
        userEmail || undefined
      );
    }

    return NextResponse.json({
      success: true,
      data: result,
    });

  } catch (err: any) {
    console.error('[ABN Lookup] Uncaught error:', err);
    return NextResponse.json({
      success: false,
      error: 'Internal server error',
    }, { status: 500 });
  }
}
