/**
 * Open competitor status resolver.
 *
 * Closes fully populated products that are still stuck in needs_research:
 * - no strict candidates and no active equivalence hints => no_valid_match
 * - one or more strict candidates or active equivalence hints => ambiguous
 *
 * This does not invent matches. It turns endless queues into explicit,
 * auditable research states.
 *
 * Default is dry-run. Set OPEN_COMPETITOR_APPLY=1 to write status/evidence.
 */
import { pool, checkAndSetFullyVerified, recordVerificationEvidence } from "./db";
import { logger } from "./logger";

const EXCLUDED_CATEGORIES = [
  "NonTransceiver",
  "Accessory",
  "Adapter / Converter",
  "Switch / Media Converter",
  "Switch / Network Infrastructure",
  "NIC / Adapter",
  "Mux / Passive Optical",
  "Product Family",
  "Loopback / Test Module",
];

type OpenCompetitorRow = {
  id: string;
  part_number: string;
  vendor_name: string;
  form_factor: string;
  speed_gbps: string;
  reach_meters: string | null;
  fiber_type: string | null;
  strict_candidate_count: string;
  equivalence_hint_count: string;
};

function applyMode(): boolean {
  return process.env.OPEN_COMPETITOR_APPLY === "1";
}

async function resolveOpenCompetitorStatus(): Promise<void> {
  const limit = Math.max(1, parseInt(process.env.OPEN_COMPETITOR_LIMIT || "1000", 10));
  const vendorFilter = process.env.OPEN_COMPETITOR_VENDOR || "";
  const apply = applyMode();

  logger.info("=== Open competitor status resolver ===", { limit, vendorFilter, apply });

  const result = await pool.query<OpenCompetitorRow>(`
    WITH active AS (
      SELECT t.*, v.name AS vendor_name
      FROM transceivers t
      JOIN vendors v ON v.id = t.vendor_id
      WHERE COALESCE(t.category, '') <> ALL($1::text[])
    ),
    ready AS (
      SELECT a.*
      FROM active a
      WHERE a.price_verified = true
        AND a.image_verified = true
        AND a.details_verified = true
        AND COALESCE(a.competitor_verified, false) = false
        AND COALESCE(a.competitor_status, 'needs_research') IN ('unknown', 'needs_research')
        AND ($2::text = '' OR a.vendor_name ILIKE ('%' || $2::text || '%'))
        AND a.form_factor IS NOT NULL
        AND a.form_factor != ''
        AND a.speed_gbps IS NOT NULL
        AND a.speed_gbps > 0
        AND a.fiber_type IS NOT NULL
        AND a.fiber_type != ''
    ),
    scored AS (
      SELECT
        r.id,
        r.part_number,
        r.vendor_name,
        r.form_factor,
        r.speed_gbps,
        r.reach_meters,
        r.fiber_type,
        (
          SELECT COUNT(*)
          FROM active c
          WHERE c.id != r.id
            AND c.vendor_id != r.vendor_id
            AND c.price_verified = true
            AND c.image_verified = true
            AND c.details_verified = true
            AND c.form_factor = r.form_factor
            AND c.speed_gbps = r.speed_gbps
            AND UPPER(COALESCE(c.fiber_type, '')) = UPPER(COALESCE(r.fiber_type, ''))
            AND (
              (c.reach_meters IS NOT NULL AND c.reach_meters > 0
                AND r.reach_meters IS NOT NULL AND r.reach_meters > 0
                AND ABS(c.reach_meters - r.reach_meters) <= GREATEST(25, r.reach_meters * 0.05))
              OR
              (COALESCE(c.reach_meters, 0) = 0 AND COALESCE(r.reach_meters, 0) = 0)
            )
            AND (
              COALESCE(NULLIF(regexp_replace(COALESCE(c.wavelengths, ''), '^.*?(\\d{3,4}).*$', '\\1'), COALESCE(c.wavelengths, '')), '') = ''
              OR COALESCE(NULLIF(regexp_replace(COALESCE(r.wavelengths, ''), '^.*?(\\d{3,4}).*$', '\\1'), COALESCE(r.wavelengths, '')), '') = ''
              OR ABS(
                NULLIF(regexp_replace(COALESCE(c.wavelengths, ''), '^.*?(\\d{3,4}).*$', '\\1'), COALESCE(c.wavelengths, ''))::int
                - NULLIF(regexp_replace(COALESCE(r.wavelengths, ''), '^.*?(\\d{3,4}).*$', '\\1'), COALESCE(r.wavelengths, ''))::int
              ) <= 15
            )
        ) AS strict_candidate_count,
        (
          SELECT COUNT(*)
          FROM transceiver_equivalences eq
          WHERE eq.flexoptix_id = r.id
            AND eq.status IN ('pending', 'approved', 'auto_approved')
            AND eq.confidence >= 0.50
        ) AS equivalence_hint_count
      FROM ready r
    )
    SELECT *
    FROM scored
    ORDER BY vendor_name, part_number
    LIMIT $3
  `, [EXCLUDED_CATEGORIES, vendorFilter, limit]);

  logger.info("Open competitor status candidates", { count: result.rowCount ?? 0 });

  if (!apply) {
    for (const row of result.rows.slice(0, 60)) {
      const strictCandidates = Number(row.strict_candidate_count);
      const equivalenceHints = Number(row.equivalence_hint_count);
      logger.info("dry-run open status", {
        vendor: row.vendor_name,
        partNumber: row.part_number,
        outcome: strictCandidates === 0 && equivalenceHints === 0 ? "no_valid_match" : "ambiguous",
        strictCandidates,
        equivalenceHints,
      });
    }
    return;
  }

  let noValidMatch = 0;
  let ambiguous = 0;
  let fullyVerifiedEarned = 0;

  for (const row of result.rows) {
    const strictCandidates = Number(row.strict_candidate_count);
    const equivalenceHints = Number(row.equivalence_hint_count);
    const shouldNoMatch = strictCandidates === 0 && equivalenceHints === 0;

    if (shouldNoMatch) {
      const reason = [
        "Open competitor status resolver found no strict source-backed competitor candidate",
        `same form_factor=${row.form_factor}`,
        `speed_gbps=${row.speed_gbps}`,
        `fiber_type=${row.fiber_type}`,
        `reach=${row.reach_meters ?? "unknown"}`,
        "and no active equivalence hint above confidence 0.50",
      ].join("; ");

      const update = await pool.query(`
        UPDATE transceivers
        SET competitor_verified = true,
            competitor_verified_at = NOW(),
            competitor_status = 'no_valid_match',
            competitor_status_updated_at = NOW(),
            no_match_verified_at = NOW(),
            no_match_reason = $2,
            updated_at = NOW()
        WHERE id = $1
          AND COALESCE(competitor_verified, false) = false
        RETURNING id
      `, [row.id, reason]);

      if ((update.rowCount ?? 0) === 0) continue;

      await recordVerificationEvidence({
        transceiverId: row.id,
        verificationType: "competitor_no_match",
        evidenceValue: {
          reason,
          vendor: row.vendor_name,
          partNumber: row.part_number,
          strictCandidateCount: strictCandidates,
          equivalenceHintCount: equivalenceHints,
        },
        robotName: "verify:open-competitor-status",
        confidence: 1,
      });

      if (await checkAndSetFullyVerified(row.id)) fullyVerifiedEarned++;
      noValidMatch++;
      continue;
    }

    const reason = [
      "Open competitor status resolver found plausible candidates but no safe deterministic 1:1 match",
      `strict_candidate_count=${strictCandidates}`,
      `equivalence_hint_count=${equivalenceHints}`,
    ].join("; ");

    const update = await pool.query(`
      UPDATE transceivers
      SET competitor_status = 'ambiguous',
          competitor_status_updated_at = NOW(),
          updated_at = NOW()
      WHERE id = $1
        AND COALESCE(competitor_verified, false) = false
        AND COALESCE(competitor_status, 'needs_research') IN ('unknown', 'needs_research')
      RETURNING id
    `, [row.id]);

    if ((update.rowCount ?? 0) === 0) continue;

    await recordVerificationEvidence({
      transceiverId: row.id,
      verificationType: "competitor_ambiguous",
      evidenceValue: {
        reason,
        vendor: row.vendor_name,
        partNumber: row.part_number,
        strictCandidateCount: strictCandidates,
        equivalenceHintCount: equivalenceHints,
      },
      robotName: "verify:open-competitor-status",
      confidence: 1,
    });

    ambiguous++;
  }

  logger.info("Open competitor status resolver complete", {
    no_valid_match: noValidMatch,
    ambiguous,
    fully_verified_earned: fullyVerifiedEarned,
  });
}

if (require.main === module) {
  resolveOpenCompetitorStatus()
    .then(() => pool.end())
    .catch((err) => {
      logger.error("Open competitor status resolver failed", { error: (err as Error).message });
      pool.end();
      process.exit(1);
    });
}
