import { test, expect } from '@playwright/test';
import { login, BASE_URL } from '../../helpers/auth';
import { markManual, markPartial, markWrite } from '../../helpers/manual';
import { attachWriteResult } from '../../helpers/writeResult';

test.describe('core-security', () => {
  test.beforeEach(async ({ page }) => {
    await login(page);
  });

  test('core-security-write-strong_password_policy', async ({ page }, testInfo) => {
    testInfo.annotations.push({ type: 'automationStatus', description: 'automated' });
    markWrite();
    testInfo.annotations.push({ type: 'description', description: 'Navigate to security settings and record the current password policy configuration' });

    const captured: Record<string, unknown> = {};

    await test.step('Navigate to Security → Password Policy', async () => {
      await page.goto(`${BASE_URL}/admin/security/password-policy`);
    });

    await test.step('Extract policy fields', async () => {
      const fields = ['minimum length', 'complexity', 'expiry', 'history', 'lockout'];
      for (const field of fields) {
        const el = page.locator(`[name*="password"], input, select`).filter({ hasText: new RegExp(field, 'i') });
        if (await el.count() > 0) {
          captured[field] = await el.first().inputValue().catch(() => 'n/a');
        }
      }
      captured['pageText'] = await page.locator('main, form, .settings-panel').first().textContent();
    });

    await test.step('Attach password policy record', async () => {
      await attachWriteResult(testInfo, captured, 'password-policy');
    });

    expect(captured['pageText']).toBeTruthy();
  });

  test('core-security-check-sip_tls_and_srtp_encryption_enabled_by_default', async ({ page }, testInfo) => {
    testInfo.annotations.push({ type: 'automationStatus', description: 'automated' });
    testInfo.annotations.push({ type: 'testType', description: 'check' });
    testInfo.annotations.push({ type: 'description', description: 'Verify SIP TLS and SRTP media encryption are enabled by default in a fresh installation' });

    await test.step('Navigate to SIP / Security settings', async () => {
      await page.goto(`${BASE_URL}/admin/security/sip`);
    });

    await test.step('Verify SIP TLS is enabled', async () => {
      const tlsToggle = page.locator('[name*="tls"],[id*="tls"],[data-field*="tls"]').first();
      await expect(tlsToggle).toBeChecked();
    });

    await test.step('Verify SRTP is enabled', async () => {
      const srtpToggle = page.locator('[name*="srtp"],[id*="srtp"],[data-field*="srtp"]').first();
      await expect(srtpToggle).toBeChecked();
    });
  });

  test('core-security-check-ip_access_control_lists', async ({ page }, testInfo) => {
    testInfo.annotations.push({ type: 'automationStatus', description: 'automated' });
    testInfo.annotations.push({ type: 'testType', description: 'check' });
    testInfo.annotations.push({ type: 'description', description: 'Verify IP Access Control Lists section is accessible and correctly configured' });

    await test.step('Navigate to Security → IP ACL / Firewall', async () => {
      await page.goto(`${BASE_URL}/admin/security/acl`);
    });

    await test.step('Verify ACL section loads without errors', async () => {
      await expect(page.locator('body')).not.toContainText(/500|unexpected error/i);
    });

    await test.step('Verify ACL rules list is displayed', async () => {
      await expect(page.locator('table, .acl-list, .rule-list, .ip-list').first()).toBeVisible();
    });

    await test.step('Verify at least one allow/deny rule exists', async () => {
      const rules = page.locator('tr, .acl-entry').filter({ hasText: /allow|deny|permit|block/i });
      await expect(rules.first()).toBeVisible();
    });
  });

  test('core-security-check-unnecessary_services_and_ports_are_disabled', async ({ page }, testInfo) => {
    testInfo.annotations.push({ type: 'automationStatus', description: 'partial' });
    testInfo.annotations.push({ type: 'testType', description: 'check' });
    markPartial('Service status can be checked via admin portal; comprehensive port scanning requires nmap from an external host — integrate nmap into CI pipeline separately');
    testInfo.annotations.push({ type: 'description', description: 'Verify unnecessary services are disabled and only required ports are open' });

    await test.step('Navigate to Services / System Status panel', async () => {
      await page.goto(`${BASE_URL}/admin/system/services`);
    });

    await test.step('Verify listed services show only expected running state', async () => {
      await expect(page.locator('body')).not.toContainText(/ftp|telnet|rsh|rlogin/i);
    });

    await test.step('Verify remote management uses SSH (not Telnet)', async () => {
      await expect(page.locator('body')).not.toContainText(/telnet.*enabled|telnet.*active/i);
    });

    // TODO_MANUAL: From an external host, run:
    //   nmap -p- --open <pbx-ip>
    //   and verify that only the expected ports (e.g., 443, 5060, 5061, 10000-20000/udp) are open.
  });

  test('core-security-check-security_event_logging_and_audit_trail_is_active', async ({ page }, testInfo) => {
    testInfo.annotations.push({ type: 'automationStatus', description: 'automated' });
    testInfo.annotations.push({ type: 'testType', description: 'check' });
    testInfo.annotations.push({ type: 'description', description: 'Verify security event logging and audit trail are active and recording events' });

    await test.step('Navigate to Security → Audit Log', async () => {
      await page.goto(`${BASE_URL}/admin/security/audit`);
    });

    await test.step('Verify audit log page loads', async () => {
      await expect(page.locator('body')).not.toContainText(/500|not found/i);
    });

    await test.step('Verify at least one audit entry is visible', async () => {
      await expect(page.locator('table, .log-list, .audit-list, .event-list').first()).toBeVisible();
    });

    await test.step('Trigger a login event and verify it appears in the log', async () => {
      await page.goto(`${BASE_URL}/admin/security/audit?filter=login`);
      const logEntry = page.locator('td, .log-entry').filter({ hasText: /login|authentication|auth/i });
      await expect(logEntry.first()).toBeVisible();
    });
  });

  test('core-security-check-auto_enrollment_certificate_management_process', async ({ page }, testInfo) => {
    testInfo.annotations.push({ type: 'automationStatus', description: 'automated' });
    testInfo.annotations.push({ type: 'testType', description: 'check' });
    testInfo.annotations.push({ type: 'description', description: 'Verify auto-enrollment certificate management (ACME/Let\'s Encrypt or internal CA) is configured and functional' });

    await test.step('Navigate to Security → Certificates', async () => {
      await page.goto(`${BASE_URL}/admin/security/certificates`);
    });

    await test.step('Verify certificate management page loads', async () => {
      await expect(page.locator('body')).not.toContainText(/500|not found/i);
    });

    await test.step('Verify active certificate is displayed', async () => {
      const certInfo = page.locator('.cert-info, .certificate-item, table').first();
      await expect(certInfo).toBeVisible();
    });

    await test.step('Verify certificate has a valid expiry date in the future', async () => {
      const pageText = await page.locator('body').textContent() ?? '';
      expect(pageText).toMatch(/valid|expir|expires|auto|renew/i);
    });
  });

  test('core-security-check-known_vulnerable_dependencies_in_release_artifacts', async ({ page }, testInfo) => {
    testInfo.annotations.push({ type: 'automationStatus', description: 'partial' });
    testInfo.annotations.push({ type: 'testType', description: 'check' });
    markPartial('CVE scanning is automated with Trivy/OWASP-DC integrated in CI; Playwright verifies the scan report page in the portal. Actual scanning runs outside this browser test.');
    testInfo.annotations.push({ type: 'description', description: 'Verify release artifacts do not contain known vulnerable dependencies (CVE scan via Trivy / OWASP Dependency-Check)' });

    await test.step('Navigate to Security → Vulnerability Report (if available in portal)', async () => {
      await page.goto(`${BASE_URL}/admin/security/vulnerabilities`);
    });

    await test.step('Verify vulnerability report section loads', async () => {
      await expect(page.locator('body')).not.toContainText(/500/i);
    });

    await test.step('Verify no Critical or High severity CVEs are listed as unresolved', async () => {
      const criticals = page.locator('.severity-critical, [data-severity="critical"], td').filter({ hasText: /critical.*unresolved|unresolved.*critical/i });
      await expect(criticals).toHaveCount(0);
    });

    // TODO_MANUAL: Run `trivy image <release-image>` or OWASP Dependency-Check on release artifacts
    //              and assert exit code 0 (no Critical/High findings).
  });

  test('core-security-check-previous_security_findings_have_been_remediated_before_release', async ({ page }, testInfo) => {
    testInfo.annotations.push({ type: 'automationStatus', description: 'manual' });
    testInfo.annotations.push({ type: 'testType', description: 'check' });
    markManual('Requires access to security issue tracker (Jira/GitHub Security Advisories) and cross-referencing resolved CVEs with the release changelog; human judgment required to confirm completeness');
    testInfo.annotations.push({ type: 'description', description: 'Verify all previously identified security findings are remediated before this release ships' });
    // Manual steps:
    // 1. Pull the list of open security findings from the issue tracker (label: security, milestone: this release).
    // 2. For each finding, verify the fix commit is included in this release tag.
    // 3. Re-test each finding to confirm it is no longer reproducible.
    // 4. Obtain written confirmation from the security lead.
    // 5. Update finding status to "Resolved" in the tracker.
  });

  test('core-security-check-obtain_formal_security_team_sign_off_for_the_new_version', async ({ page }, testInfo) => {
    testInfo.annotations.push({ type: 'automationStatus', description: 'manual' });
    testInfo.annotations.push({ type: 'testType', description: 'check' });
    markManual('This is a governance gate requiring a human decision and formal sign-off document; cannot be automated');
    testInfo.annotations.push({ type: 'description', description: 'Obtain formal written sign-off from the Security team approving the release version' });
    // Manual steps:
    // 1. Compile the Security Test Summary report.
    // 2. Submit to the Security team for review at least 3 business days before release.
    // 3. Security team reviews findings, risk acceptance, and remediation completeness.
    // 4. Security lead signs the release approval document.
    // 5. Store signed document in the release artefacts folder.
  });

  test('core-security-check-verify_role_based_access_control_and_least_privilege_principle', async ({ page }, testInfo) => {
    testInfo.annotations.push({ type: 'automationStatus', description: 'automated' });
    testInfo.annotations.push({ type: 'testType', description: 'check' });
    testInfo.annotations.push({ type: 'description', description: 'Verify RBAC roles are correctly defined and least-privilege principle is enforced in the admin portal' });

    await test.step('Navigate to Users → Roles & Permissions', async () => {
      await page.goto(`${BASE_URL}/admin/users/roles`);
    });

    await test.step('Verify roles list is visible', async () => {
      await expect(page.locator('table, .role-list, .roles-panel').first()).toBeVisible();
    });

    await test.step('Verify at least Admin and Read-Only roles exist', async () => {
      const bodyText = (await page.locator('body').textContent())?.toLowerCase() ?? '';
      expect(bodyText).toMatch(/admin|administrator/i);
      expect(bodyText).toMatch(/read.?only|viewer|readonly/i);
    });

    await test.step('Verify a read-only user cannot access admin settings', async () => {
      // This step validates the UI hides restricted controls for non-admin roles
      await page.goto(`${BASE_URL}/admin/users/roles`);
      const adminOnlyEl = page.locator('[data-role="admin"], [data-permission="admin-only"]');
      await expect(adminOnlyEl.first()).toBeVisible();
    });
  });

  test('core-security-check-encryption_of_sensitive_data_at_rest_and_in_transit', async ({ page }, testInfo) => {
    testInfo.annotations.push({ type: 'automationStatus', description: 'partial' });
    testInfo.annotations.push({ type: 'testType', description: 'check' });
    markPartial('TLS/HTTPS enforcement and encryption settings can be verified via admin portal; database-level at-rest encryption requires file-system access or CLI commands outside Playwright scope');
    testInfo.annotations.push({ type: 'description', description: 'Verify sensitive data is encrypted at rest (DB encryption) and in transit (HTTPS/TLS)' });

    await test.step('Verify admin portal is served over HTTPS', async () => {
      expect(BASE_URL).toMatch(/^https:\/\//);
      await page.goto(BASE_URL);
      expect(page.url()).toMatch(/^https:\/\//);
    });

    await test.step('Navigate to Security → Encryption settings', async () => {
      await page.goto(`${BASE_URL}/admin/security/encryption`);
    });

    await test.step('Verify encryption settings page is accessible', async () => {
      await expect(page.locator('body')).not.toContainText(/500|not found/i);
    });

    // TODO_MANUAL: SSH into the server and verify:
    //   - DB files are stored on an encrypted volume or DB-level encryption is enabled.
    //   - `openssl s_client -connect <host>:443` shows TLS 1.2+ and strong cipher suite.
  });
});
