/**
 * Tests for settings schema
 */

import {
  SettingsSchema,
  PermissionsSchema,
  AttributionSchema,
  SandboxSchema,
  SettingsHooksSchema,
} from '../../src/validators/schemas';

describe('SettingsSchema', () => {
  describe('valid configurations', () => {
    it('should accept empty settings object', () => {
      const result = SettingsSchema.safeParse({});
      expect(result.success).toBe(true);
    });

    it('should accept settings with all fields', () => {
      const result = SettingsSchema.safeParse({
        $schema: 'https://json.schemastore.org/claude-code-settings.json',
        permissions: {
          allow: ['Read'],
          deny: ['Bash(rm *)'],
          ask: ['Write'],
        },
        env: {
          NODE_ENV: 'development',
        },
        model: 'sonnet',
        apiKeyHelper: 'get-api-key.sh',
        hooks: {},
        attribution: {
          commit: 'Generated by Claude',
          pr: 'Created with Claude Code',
        },
        statusLine: 'default',
        outputStyle: 'concise',
        sandbox: {
          enabled: true,
        },
        enabledPlugins: {
          'my-plugin': true,
        },
        autoUpdatesChannel: 'stable',
        cleanupPeriodDays: 30,
        language: 'en',
        respectGitignore: true,
        enableAllProjectMcpServers: false,
        disableAllHooks: false,
        teammateMode: false,
        showTurnDuration: true,
        terminalProgressBarEnabled: true,
        spinnerTipsEnabled: true,
        alwaysThinkingEnabled: false,
        prefersReducedMotion: false,
        plansDirectory: '.claude/plans',
        skipWebFetchPreflight: false,
      });
      expect(result.success).toBe(true);
    });
  });

  describe('model field', () => {
    it('should accept any string for model', () => {
      const result = SettingsSchema.safeParse({
        model: 'sonnet',
      });
      expect(result.success).toBe(true);
    });

    it('should accept model aliases', () => {
      const result = SettingsSchema.safeParse({
        model: 'claude-sonnet-4-5-20250929',
      });
      expect(result.success).toBe(true);
    });

    it('should accept custom model names', () => {
      const result = SettingsSchema.safeParse({
        model: 'my-custom-model',
      });
      expect(result.success).toBe(true);
    });
  });

  describe('env field', () => {
    it('should accept env variables object', () => {
      const result = SettingsSchema.safeParse({
        env: {
          API_KEY: 'secret',
          DEBUG: 'true',
        },
      });
      expect(result.success).toBe(true);
    });

    it('should accept empty env object', () => {
      const result = SettingsSchema.safeParse({
        env: {},
      });
      expect(result.success).toBe(true);
    });
  });

  describe('enabledPlugins field', () => {
    it('should accept plugin enable/disable map', () => {
      const result = SettingsSchema.safeParse({
        enabledPlugins: {
          'plugin-a': true,
          'plugin-b': false,
          'plugin-c': true,
        },
      });
      expect(result.success).toBe(true);
    });
  });
});

describe('PermissionsSchema', () => {
  describe('permission arrays', () => {
    it('should accept allow array', () => {
      const result = PermissionsSchema.safeParse({
        allow: ['Read', 'Bash(ls)'],
      });
      expect(result.success).toBe(true);
    });

    it('should accept deny array', () => {
      const result = PermissionsSchema.safeParse({
        deny: ['Bash(rm -rf /)', 'Write(.env)'],
      });
      expect(result.success).toBe(true);
    });

    it('should accept ask array', () => {
      const result = PermissionsSchema.safeParse({
        ask: ['Write', 'Edit'],
      });
      expect(result.success).toBe(true);
    });

    it('should accept all three arrays', () => {
      const result = PermissionsSchema.safeParse({
        allow: ['Read'],
        deny: ['Bash(rm *)'],
        ask: ['Write'],
      });
      expect(result.success).toBe(true);
    });

    it('should accept empty arrays', () => {
      const result = PermissionsSchema.safeParse({
        allow: [],
        deny: [],
        ask: [],
      });
      expect(result.success).toBe(true);
    });
  });

  describe('defaultMode field', () => {
    it('should accept acceptEdits mode', () => {
      const result = PermissionsSchema.safeParse({
        defaultMode: 'acceptEdits',
      });
      expect(result.success).toBe(true);
    });

    it('should accept bypassPermissions mode', () => {
      const result = PermissionsSchema.safeParse({
        defaultMode: 'bypassPermissions',
      });
      expect(result.success).toBe(true);
    });

    it('should accept default mode', () => {
      const result = PermissionsSchema.safeParse({
        defaultMode: 'default',
      });
      expect(result.success).toBe(true);
    });

    it('should accept plan mode', () => {
      const result = PermissionsSchema.safeParse({
        defaultMode: 'plan',
      });
      expect(result.success).toBe(true);
    });

    it('should reject invalid mode', () => {
      const result = PermissionsSchema.safeParse({
        defaultMode: 'invalid',
      });
      expect(result.success).toBe(false);
    });
  });

  describe('disableBypassPermissionsMode field', () => {
    it('should accept disable value', () => {
      const result = PermissionsSchema.safeParse({
        disableBypassPermissionsMode: 'disable',
      });
      expect(result.success).toBe(true);
    });

    it('should reject other values', () => {
      const result = PermissionsSchema.safeParse({
        disableBypassPermissionsMode: 'enable',
      });
      expect(result.success).toBe(false);
    });
  });

  describe('additionalDirectories field', () => {
    it('should accept array of directory paths', () => {
      const result = PermissionsSchema.safeParse({
        additionalDirectories: ['/path/to/dir1', '/path/to/dir2'],
      });
      expect(result.success).toBe(true);
    });

    it('should accept empty array', () => {
      const result = PermissionsSchema.safeParse({
        additionalDirectories: [],
      });
      expect(result.success).toBe(true);
    });
  });
});

describe('AttributionSchema', () => {
  it('should accept commit message template', () => {
    const result = AttributionSchema.safeParse({
      commit: 'Generated by Claude',
    });
    expect(result.success).toBe(true);
  });

  it('should accept pr message template', () => {
    const result = AttributionSchema.safeParse({
      pr: 'This PR was generated with Claude Code',
    });
    expect(result.success).toBe(true);
  });

  it('should accept both commit and pr', () => {
    const result = AttributionSchema.safeParse({
      commit: 'Generated by Claude',
      pr: 'Created with Claude Code',
    });
    expect(result.success).toBe(true);
  });

  it('should accept all fields optional', () => {
    const result = AttributionSchema.safeParse({});
    expect(result.success).toBe(true);
  });
});

describe('SandboxSchema', () => {
  it('should accept enabled flag', () => {
    const result = SandboxSchema.safeParse({
      enabled: true,
    });
    expect(result.success).toBe(true);
  });

  it('should accept autoAllowBashIfSandboxed', () => {
    const result = SandboxSchema.safeParse({
      enabled: true,
      autoAllowBashIfSandboxed: true,
    });
    expect(result.success).toBe(true);
  });

  it('should accept excludedCommands array', () => {
    const result = SandboxSchema.safeParse({
      enabled: true,
      excludedCommands: ['rm', 'sudo'],
    });
    expect(result.success).toBe(true);
  });

  it('should accept allowUnsandboxedCommands array', () => {
    const result = SandboxSchema.safeParse({
      enabled: true,
      allowUnsandboxedCommands: ['docker', 'brew'],
    });
    expect(result.success).toBe(true);
  });

  it('should accept network config', () => {
    const result = SandboxSchema.safeParse({
      enabled: true,
      network: {
        allowedHosts: ['api.example.com'],
        allowedPorts: [443, 8080],
      },
    });
    expect(result.success).toBe(true);
  });

  it('should accept enableWeakerNestedSandbox', () => {
    const result = SandboxSchema.safeParse({
      enableWeakerNestedSandbox: true,
    });
    expect(result.success).toBe(true);
  });

  it('should accept ignoreViolations', () => {
    const result = SandboxSchema.safeParse({
      ignoreViolations: true,
    });
    expect(result.success).toBe(true);
  });

  it('should accept all fields optional', () => {
    const result = SandboxSchema.safeParse({});
    expect(result.success).toBe(true);
  });

  it('should accept full sandbox configuration', () => {
    const result = SandboxSchema.safeParse({
      enabled: true,
      autoAllowBashIfSandboxed: true,
      excludedCommands: ['rm -rf'],
      allowUnsandboxedCommands: ['docker'],
      network: {
        allowedHosts: ['localhost'],
        allowedPorts: [3000],
      },
      enableWeakerNestedSandbox: false,
      ignoreViolations: false,
    });
    expect(result.success).toBe(true);
  });
});

describe('SettingsHooksSchema', () => {
  it('should accept PreToolUse hooks', () => {
    const result = SettingsHooksSchema.safeParse({
      PreToolUse: [
        {
          matcher: 'Write',
          hooks: [
            {
              type: 'command',
              command: 'echo before',
            },
          ],
        },
      ],
    });
    expect(result.success).toBe(true);
  });

  it('should accept PostToolUse hooks', () => {
    const result = SettingsHooksSchema.safeParse({
      PostToolUse: [
        {
          hooks: [
            {
              type: 'command',
              command: 'echo after',
            },
          ],
        },
      ],
    });
    expect(result.success).toBe(true);
  });

  it('should accept all hook event types', () => {
    const result = SettingsHooksSchema.safeParse({
      PreToolUse: [],
      PostToolUse: [],
      PostToolUseFailure: [],
      PermissionRequest: [],
      Notification: [],
      UserPromptSubmit: [],
      Stop: [],
      SubagentStart: [],
      SubagentStop: [],
      PreCompact: [],
      SessionStart: [],
      SessionEnd: [],
      TeammateIdle: [],
      TaskCompleted: [],
    });
    expect(result.success).toBe(true);
  });

  it('should accept empty hooks object', () => {
    const result = SettingsHooksSchema.safeParse({});
    expect(result.success).toBe(true);
  });

  it('should accept hooks with matcher pattern', () => {
    const result = SettingsHooksSchema.safeParse({
      PostToolUse: [
        {
          matcher: 'Write|Edit',
          hooks: [
            {
              type: 'command',
              command: 'prettier --write $FILE',
            },
          ],
        },
      ],
    });
    expect(result.success).toBe(true);
  });

  it('should accept hooks without matcher', () => {
    const result = SettingsHooksSchema.safeParse({
      PostToolUse: [
        {
          hooks: [
            {
              type: 'command',
              command: 'echo done',
            },
          ],
        },
      ],
    });
    expect(result.success).toBe(true);
  });
});
