import { describe, it, expect, beforeEach } from 'vitest';
import { rewriteUrl } from './index';

describe('rewriteUrl', () => {
  beforeEach(() => {
    window.csrfToken = 'test-csrf-token';
    (window.ACMS as unknown as { Config: Record<string, unknown> }).Config = {
      previewAllowedOrigins: ['https://preview.example.com'],
    };
  });

  it('許可オリジンのURLには acms-preview-mode クエリとして CSRF トークンを付与する', () => {
    const result = rewriteUrl('https://preview.example.com/entry/1/');
    expect(result).toContain('acms-preview-mode=test-csrf-token');
  });

  it('許可オリジン外のURL（攻撃者のURL）にはトークンを付与せずそのまま返す', () => {
    const result = rewriteUrl('https://attacker.example/');
    expect(result).toBe('https://attacker.example/');
  });

  it('許可オリジンのURLに既存の acms-preview-mode クエリがある場合はトークン部分だけ置き換える', () => {
    const result = rewriteUrl('https://preview.example.com/entry/1/?acms-preview-mode=old-token');
    expect(result).toContain('acms-preview-mode=test-csrf-token');
    expect(result).not.toContain('old-token');
  });

  it('空文字はそのまま返す', () => {
    expect(rewriteUrl('')).toBe('');
  });

  it('previewAllowedOrigins が未設定の場合はどの URL にもトークンを付与しない', () => {
    (window.ACMS as unknown as { Config: Record<string, unknown> }).Config = {};
    const result = rewriteUrl('https://preview.example.com/entry/1/');
    expect(result).toBe('https://preview.example.com/entry/1/');
  });

  it('previewAllowedOrigins が配列でない場合（型不整合）でも例外を投げずトークンを付与しない', () => {
    // qs のパース結果が配列でなくオブジェクトになる等の想定外ケースに対する防御を確認する
    (window.ACMS as unknown as { Config: Record<string, unknown> }).Config = {
      previewAllowedOrigins: { 0: 'https://preview.example.com' },
    };
    const result = rewriteUrl('https://preview.example.com/entry/1/');
    expect(result).toBe('https://preview.example.com/entry/1/');
  });

  it('base URL に対して解決しても絶対URLとして構文エラーになる文字列にはトークンを付与しない', () => {
    // new URL('http://[', base) は base の有無にかかわらず構文エラーで throw する
    // （scheme://... の形をした時点で絶対URLとして解釈され、base への相対解決にフォールバックしないため）
    const result = rewriteUrl('http://[');
    expect(result).toBe('http://[');
  });
});
