/**
 * US-9 — SOC analyst fills their part; redteam fields blocked.
 * Covers AC-9.1 → AC-9.4.
 */
import { test, expect } from '@playwright/test';
import {
  adminToken,
  createEngagement,
  deleteEngagement,
  deleteUserByUsername,
  ensureUser,
  login,
  makeClient,
} from '../fixtures/api';
import { seedTokenInStorage } from '../fixtures/auth';

const REDTEAM_USER = 'us9-redteam';
const SOC_USER = 'us9-soc';
const PASS = 'us9-pass-strong';

interface Simulation {
  id: number;
  status: string;
  [key: string]: unknown;
}

async function createSimulation(
  token: string,
  engagementId: number,
  name = 'US-9 sim',
): Promise<Simulation> {
  const client = makeClient(token);
  const r = await client.post(`/engagements/${engagementId}/simulations`, { name });
  if (r.status !== 201) {
    throw new Error(`create simulation failed: ${r.status} ${JSON.stringify(r.data)}`);
  }
  return r.data as Simulation;
}

async function deleteSimulation(token: string, simId: number): Promise<void> {
  const client = makeClient(token);
  await client.delete(`/simulations/${simId}`);
}

async function advanceToReviewRequired(
  redteamToken: string,
  simId: number,
): Promise<void> {
  const client = makeClient(redteamToken);
  // Trigger auto-transition to in_progress
  await client.patch(`/simulations/${simId}`, { name: 'ready' });
  // Transition to review_required
  const r = await client.post(`/simulations/${simId}/transition`, {
    to: 'review_required',
  });
  if (r.status !== 200) {
    throw new Error(`transition to review_required failed: ${r.status}`);
  }
}

test.describe('US-9 — SOC restricted edit', () => {
  let redteamToken: string;
  let socToken: string;
  let engagementId: number;

  test.beforeAll(async () => {
    await ensureUser(REDTEAM_USER, PASS, 'redteam');
    await ensureUser(SOC_USER, PASS, 'soc');
    redteamToken = (await login(REDTEAM_USER, PASS)).token;
    socToken = (await login(SOC_USER, PASS)).token;
    const eng = await createEngagement(redteamToken, {
      name: 'US-9 Test Engagement',
      start_date: '2026-01-01',
    });
    engagementId = eng.id;
  });

  test.afterAll(async () => {
    try {
      const tok = await adminToken();
      await deleteEngagement(tok, engagementId);
      for (const u of [REDTEAM_USER, SOC_USER]) {
        await deleteUserByUsername(tok, u);
      }
    } catch {
      /* noop */
    }
  });

  test('AC-9.1 — soc PATCH with redteam field → 403 soc cannot edit redteam fields', async () => {
    const sim = await createSimulation(redteamToken, engagementId, 'AC-9.1 sim');
    await advanceToReviewRequired(redteamToken, sim.id);

    const socClient = makeClient(socToken);

    // Redteam field in payload → 403
    const r = await socClient.patch(`/simulations/${sim.id}`, {
      name: 'SOC tries to change name',
    });
    expect(r.status).toBe(403);
    expect(r.data.error).toMatch(/soc cannot edit redteam fields/i);

    // SOC-only fields → 200
    const rOk = await socClient.patch(`/simulations/${sim.id}`, {
      soc_comment: 'Detected',
      log_source: 'SIEM',
      logs: 'log entry',
      incident_number: 'INC-001',
    });
    expect(rOk.status).toBe(200);

    await deleteSimulation(redteamToken, sim.id);
  });

  test('AC-9.2 — soc PATCH blocked when status is pending or in_progress', async () => {
    const socClient = makeClient(socToken);

    // pending → 403
    const simPending = await createSimulation(redteamToken, engagementId, 'AC-9.2 pending');
    const rPending = await socClient.patch(`/simulations/${simPending.id}`, {
      soc_comment: 'too early',
    });
    expect(rPending.status).toBe(403);
    expect(rPending.data.error).toMatch(/simulation not ready for SOC review/i);

    // in_progress → 403
    const simInProgress = await createSimulation(
      redteamToken,
      engagementId,
      'AC-9.2 in_progress',
    );
    const rtClient = makeClient(redteamToken);
    await rtClient.patch(`/simulations/${simInProgress.id}`, { name: 'trigger' });
    const rInProgress = await socClient.patch(`/simulations/${simInProgress.id}`, {
      soc_comment: 'still too early',
    });
    expect(rInProgress.status).toBe(403);
    expect(rInProgress.data.error).toMatch(/simulation not ready for SOC review/i);

    await deleteSimulation(redteamToken, simPending.id);
    await deleteSimulation(redteamToken, simInProgress.id);
  });

  test('AC-9.3 — edit page for soc: RT section read-only, SOC section editable when review_required', async ({
    page,
    context,
  }) => {
    const sim = await createSimulation(redteamToken, engagementId, 'AC-9.3 sim');
    await advanceToReviewRequired(redteamToken, sim.id);

    await seedTokenInStorage(context, socToken);
    await page.goto(`/engagements/${engagementId}/simulations/${sim.id}/edit`);

    // RT fields are disabled
    await expect(page.locator('#sim-name')).toBeDisabled();
    await expect(page.locator('#sim-description')).toBeDisabled();
    await expect(page.locator('#sim-commands')).toBeDisabled();

    // SOC fields are enabled
    await expect(page.locator('#sim-log-source')).toBeEnabled();
    await expect(page.locator('#sim-logs')).toBeEnabled();
    await expect(page.locator('#sim-soc-comment')).toBeEnabled();
    await expect(page.locator('#sim-incident')).toBeEnabled();

    await deleteSimulation(redteamToken, sim.id);
  });

  test('AC-9.4 — soc visits pending/in_progress simulation: banner visible, SOC fields disabled', async ({
    page,
    context,
  }) => {
    // Test with pending status
    const simPending = await createSimulation(redteamToken, engagementId, 'AC-9.4 pending');

    await seedTokenInStorage(context, socToken);
    await page.goto(`/engagements/${engagementId}/simulations/${simPending.id}/edit`);

    // Banner must be visible
    await expect(page.getByTestId('soc-blocked-banner')).toBeVisible();
    await expect(
      page.getByText(/simulation not yet ready for review/i),
    ).toBeVisible();

    // SOC fields are disabled
    await expect(page.locator('#sim-log-source')).toBeDisabled();
    await expect(page.locator('#sim-soc-comment')).toBeDisabled();

    // Test with in_progress status
    const simIP = await createSimulation(redteamToken, engagementId, 'AC-9.4 in_progress');
    const rtClient = makeClient(redteamToken);
    await rtClient.patch(`/simulations/${simIP.id}`, { name: 'trigger' });

    await page.goto(`/engagements/${engagementId}/simulations/${simIP.id}/edit`);
    await expect(page.getByTestId('soc-blocked-banner')).toBeVisible();
    await expect(page.locator('#sim-log-source')).toBeDisabled();

    await deleteSimulation(redteamToken, simPending.id);
    await deleteSimulation(redteamToken, simIP.id);
  });
});
