/**
 * Real-LadybugDB round trip for `Route.method` (issue #2138, Part 1).
 *
 * This is the test the mocked `http-route-graph-method.test.ts` could NOT
 * provide: it persists a `Route` node carrying `method` through the actual
 * CSV generator + `COPY` path into a real LadybugDB, then runs the exact
 * production `HANDLES_ROUTE_QUERY` and asserts the verb comes back.
 *
 * Before the schema/CSV/COPY columns were added, `HANDLES_ROUTE_QUERY`'s
 * `route.method AS routeMethod` failed to bind against the real schema
 * (`Binder exception: Cannot find property method for r.`) and the
 * extractor's `catch { return [] }` silently swallowed it — so this test
 * would have failed (empty rows / throw), pinning the exact regression.
 *
 * Coverage spans all three persistence points touched by Part 1:
 *   - `ROUTE_SCHEMA` (schema.ts) — the `method` column must exist
 *   - the Route CSV row (csv-generator.ts) — the value must be written
 *   - `getCopyQuery('Route')` (lbug-adapter.ts) — the COPY must load it
 */
import { it, expect } from 'vitest';
import path from 'path';
import fs from 'fs/promises';
import { withTestLbugDB } from '../helpers/test-indexed-db.js';
import { buildTestGraph } from '../helpers/test-graph.js';
import { streamAllCSVsToDisk } from '../../src/core/lbug/csv-generator.js';
import { HANDLES_ROUTE_QUERY } from '../../src/core/group/extractors/http-route-extractor.js';
import { generateId } from '../../src/lib/utils.js';
import { routeNodeKey } from '../../src/core/ingestion/route-extractors/route-path.js';

// Composite Route id — what the routes phase emits post-#2289 for a
// method-bearing declarative route. Hand-pinning the pre-#2289 URL-only
// `Route:/api/orders` shape would no longer cover the production
// CSV→COPY→`HANDLES_ROUTE_QUERY` path the COPY query has to load.
const ROUTE_ID = generateId('Route', routeNodeKey('POST', '/api/orders'));

withTestLbugDB('route-method-roundtrip', (handle) => {
  it('persists Route.method through CSV→COPY and HANDLES_ROUTE_QUERY returns it', async () => {
    const adapter = await import('../../src/core/lbug/lbug-adapter.js');

    // 1. Build a graph with a single framework Route node carrying `method`,
    //    keyed by the composite `(method, url)` id the routes phase now emits
    //    so the CSV row + COPY load exercise the post-#2289 id shape (a value
    //    containing a literal space — `Route:POST /api/orders`).
    const graph = buildTestGraph([
      {
        id: ROUTE_ID,
        label: 'Route',
        name: '/api/orders',
        filePath: 'OrderController.java',
        extra: {
          method: 'POST',
          responseKeys: [],
          errorKeys: [],
          middleware: [],
        },
      },
    ]);

    // 2. Generate CSVs through the real generator (exercises the new
    //    `method` column in the Route CSV row).
    const csvDir = path.join(handle.tmpHandle.dbPath, 'csv-roundtrip');
    const repoDir = path.join(handle.tmpHandle.dbPath, 'repo-roundtrip');
    await fs.mkdir(repoDir, { recursive: true });
    await streamAllCSVsToDisk(graph, repoDir, csvDir);

    // Sanity: the generated route.csv header + row include the method column,
    // and the composite id (with its literal space) round-trips into the CSV
    // — a space-in-id COPY failure on the new id format would surface here.
    const routeCsv = await fs.readFile(path.join(csvDir, 'route.csv'), 'utf-8');
    expect(routeCsv.split('\n')[0]).toContain('method');
    expect(routeCsv).toContain('POST');
    expect(routeCsv).toContain(ROUTE_ID);

    // 3. COPY the Route node into the real DB via the production COPY query
    //    (exercises the new `method` column in getCopyQuery('Route')).
    const routeCsvPath = path.join(csvDir, 'route.csv').replace(/\\/g, '/');
    await adapter.executeQuery(adapter.getCopyQuery('Route', routeCsvPath));

    // 4. Seed the handler File node + HANDLES_ROUTE edge via Cypher.
    await adapter.executeQuery(
      `CREATE (:File {id: 'File:OrderController.java', name: 'OrderController.java', filePath: 'OrderController.java'})`,
    );
    await adapter.executeQuery(
      `MATCH (f:File {id: 'File:OrderController.java'}), (r:Route {id: '${ROUTE_ID}'})
       CREATE (f)-[:CodeRelation {type: 'HANDLES_ROUTE', confidence: 1.0, reason: 'framework-route', step: 0}]->(r)`,
    );

    // 5. Run the EXACT production query and assert the verb round-trips.
    const rows = (await adapter.executeQuery(HANDLES_ROUTE_QUERY)) as Record<string, unknown>[];
    const row = rows.find((r) => String(r.routePath) === '/api/orders');
    expect(row, 'HANDLES_ROUTE_QUERY returned no row for the seeded route').toBeTruthy();
    expect(row!.routeMethod).toBe('POST');
  });
});
