import { describe, expect, it } from 'vitest';

import {
  createEmptyAgent,
  useAgentDesignerState,
} from './useAgentDesignerState';

describe('useAgentDesignerState generation stream', () => {
  it('defaults new and legacy agents to streaming', () => {
    expect(createEmptyAgent().generationConfigJson?.stream).toBe(true);

    const designer = useAgentDesignerState();
    designer.reset({ name: '旧智能体' });

    expect(designer.state.agent.generationConfigJson?.stream).toBe(true);
    expect(designer.buildPayloadAgent().generationConfigJson?.stream).toBe(
      true,
    );
  });

  it('preserves an explicitly disabled stream value in the payload', () => {
    const designer = useAgentDesignerState();
    designer.reset({
      name: '非流式智能体',
      generationConfigJson: { stream: false },
    });

    expect(designer.state.agent.generationConfigJson?.stream).toBe(false);
    expect(designer.buildPayloadAgent().generationConfigJson?.stream).toBe(
      false,
    );
  });
});

describe('useAgentDesignerState visibility scope', () => {
  it('defaults new and legacy agents to private visibility', () => {
    expect(createEmptyAgent().visibilityScope).toBe('PRIVATE');

    const designer = useAgentDesignerState();
    designer.reset({ name: '旧智能体' });

    expect(designer.state.agent.visibilityScope).toBe('PRIVATE');
    expect(designer.buildPayloadAgent().visibilityScope).toBe('PRIVATE');
  });

  it('preserves the selected visibility scope in the save payload', () => {
    const designer = useAgentDesignerState();
    designer.reset({ name: '部门智能体', visibilityScope: 'DEPT' });

    expect(designer.buildPayloadAgent().visibilityScope).toBe('DEPT');
  });
});

describe('useAgentDesignerState document context budget', () => {
  it('defaults new and legacy agents to twenty thousand tokens', () => {
    expect(
      createEmptyAgent().executionConfigJson?.documentContextBudgetTokens,
    ).toBe(20_000);

    const designer = useAgentDesignerState();
    designer.reset({ name: '旧智能体' });

    expect(
      designer.state.agent.executionConfigJson?.documentContextBudgetTokens,
    ).toBe(20_000);
    expect(
      designer.buildPayloadAgent().executionConfigJson
        ?.documentContextBudgetTokens,
    ).toBe(20_000);
  });

  it('preserves a positive custom document context budget', () => {
    const designer = useAgentDesignerState();
    designer.reset({
      executionConfigJson: { documentContextBudgetTokens: 32_000 },
      name: '长文档智能体',
    });

    expect(
      designer.buildPayloadAgent().executionConfigJson
        ?.documentContextBudgetTokens,
    ).toBe(32_000);
  });
});

describe('useAgentDesignerState memory compression', () => {
  it('keeps the manually configured token threshold in state and payload', () => {
    expect(
      createEmptyAgent().memoryConfigJson?.compressionParameter,
    ).not.toHaveProperty('msgThreshold');

    const designer = useAgentDesignerState();
    designer.reset({
      name: '旧压缩配置智能体',
      memoryConfigJson: {
        maxAttachedMessageCount: 12,
        compressionParameter: {
          enabled: true,
          msgThreshold: 12,
          lastKeep: 6,
          minCompressionTokenThreshold: 800_000,
        },
      },
    });

    const stateCompressionParameter =
      designer.state.agent.memoryConfigJson?.compressionParameter;
    expect(stateCompressionParameter).not.toHaveProperty('msgThreshold');
    expect(stateCompressionParameter?.lastKeep).toBe(6);
    expect(stateCompressionParameter?.minCompressionTokenThreshold).toBe(
      800_000,
    );

    const payloadMemoryConfig = designer.buildPayloadAgent().memoryConfigJson;
    expect(payloadMemoryConfig).not.toHaveProperty('maxAttachedMessageCount');
    expect(payloadMemoryConfig?.compressionParameter).not.toHaveProperty(
      'msgThreshold',
    );
    expect(
      payloadMemoryConfig?.compressionParameter.minCompressionTokenThreshold,
    ).toBe(800_000);
  });
});

describe('useAgentDesignerState skill bindings', () => {
  it('adds unique skills, keeps summaries safe and caps the list at twenty', () => {
    const designer = useAgentDesignerState();
    const options = Array.from({ length: 22 }, (_, index) => ({
      label: `技能 ${index + 1}`,
      value: String(index + 1),
      raw: {
        binaryResourceCount: 1,
        description: `描述 ${index + 1}`,
        internalSnapshot: { secret: true },
        textResourceCount: 2,
        toolCount: index,
        visibilityScope: 'DEPARTMENT',
      },
    }));

    designer.appendSkillOptions([...options, ...options.slice(0, 1)]);

    expect(designer.state.skillBindings).toHaveLength(20);
    expect(designer.state.selectedNodeId).toBe('skills');
    expect(designer.state.skillBindings[0]?.resourceSummary).toEqual({
      binaryExcludedCount: 1,
      description: '描述 1',
      displayName: '技能 1',
      hasUpdate: false,
      snapshotHash: '',
      textResourceCount: 2,
      toolCount: 0,
      visibilityScope: 'DEPARTMENT',
    });
    expect(designer.state.skillBindings[0]?.resourceSummary).not.toHaveProperty(
      'internalSnapshot',
    );
  });

  it('reorders and removes skills while generating a minimal save payload', () => {
    const designer = useAgentDesignerState();
    designer.reset({
      id: 'agent-1',
      name: '技能智能体',
      skillBindings: [
        { skillId: 'skill-1', sortNo: 1 },
        { skillId: 'skill-2', sortNo: 2 },
        { skillId: 'skill-3', sortNo: 3 },
      ],
    });

    designer.moveSkill('skill-3', -1);
    designer.removeSkill('skill-1');

    expect(designer.buildSkillPayload()).toEqual([
      { skillId: 'skill-3', sortNo: 1 },
      { skillId: 'skill-2', sortNo: 2 },
    ]);
    expect(designer.buildPayloadAgent()).not.toHaveProperty('skillBindings');
  });
});

describe('useAgentDesignerState binding change tracking', () => {
  it('sends only persisted fields and marks only changed binding groups', () => {
    const designer = useAgentDesignerState();
    designer.reset({
      id: 'agent-1',
      name: '保存性能测试',
      knowledgeBindings: [
        {
          id: 'knowledge-binding-1',
          knowledgeId: 'knowledge-1',
          localId: 'local-knowledge',
          resourceSummary: { title: '知识库' },
        },
      ],
      toolBindings: [
        {
          id: 'tool-binding-1',
          localId: 'local-tool',
          resourceSummary: { title: '工具' },
          targetId: 'tool-1',
          toolName: 'lookup',
          toolType: 'PLUGIN',
        },
      ],
    });

    expect(designer.getBindingChanges()).toEqual({
      knowledge: false,
      skill: false,
      tool: false,
    });
    expect(designer.buildToolPayload('agent-1')[0]).not.toHaveProperty(
      'localId',
    );
    expect(designer.buildToolPayload('agent-1')[0]).not.toHaveProperty(
      'resourceSummary',
    );

    const toolBinding = designer.state.toolBindings[0];
    expect(toolBinding).toBeDefined();
    if (!toolBinding) return;
    toolBinding.hitlEnabled = true;
    expect(designer.getBindingChanges()).toEqual({
      knowledge: false,
      skill: false,
      tool: true,
    });

    designer.commitBindingBaseline();
    expect(designer.getBindingChanges().tool).toBe(false);
  });
});
