/**
 * This file is part of the NocoBase (R) project.
 * Copyright (c) 2020-2024 NocoBase Co., Ltd.
 * Authors: NocoBase Team.
 *
 * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
 * For more information, please refer to: https://www.nocobase.com/agreement.
 */

/**
 * This file is part of the NocoBase (R) project.
 * Copyright (c) 2020-2024 NocoBase Co., Ltd.
 * Authors: NocoBase Team.
 *
 * This program is offered under a commercial license.
 * For more information, see <https://www.nocobase.com/agreement>
 */

import { Database, Repository } from '@nocobase/database';
import { MockServer, createMockServer } from '@nocobase/test';

describe('actions', () => {
  let app: MockServer;
  let db: Database;
  let repo: Repository;
  let agent: any;

  beforeAll(async () => {
    app = await createMockServer({
      plugins: ['error-handler', 'field-sort', 'users', 'departments'],
    });
    db = app.db;
    repo = db.getRepository('departments');
    agent = app.agent();
  });

  afterAll(async () => {
    await app.destroy();
  });

  afterEach(async () => {
    await repo.destroy({ truncate: true });
  });

  it('should list users exclude department', async () => {
    const user = await db.getRepository('users').findOne();
    const dept = await repo.create({
      values: {
        title: 'Test department',
        members: [user.id],
      },
    });
    const res = await agent.resource('users').listExcludeDept({
      departmentId: dept.id,
    });
    expect(res.status).toBe(200);
    expect(res.body.data.length).toBe(0);
  });

  it('should list users exclude department with filter', async () => {
    const user = await db.getRepository('users').findOne();
    let res = await agent.resource('users').listExcludeDept({
      departmentId: 1,
    });
    expect(res.status).toBe(200);
    expect(res.body.data.length).toBe(1);

    res = await agent.resource('users').listExcludeDept({
      departmentId: 1,
      filter: {
        id: user.id,
      },
    });
    expect(res.status).toBe(200);
    expect(res.body.data.length).toBe(1);

    res = await agent.resource('users').listExcludeDept({
      departmentId: 1,
      filter: {
        id: 2,
      },
    });
    expect(res.status).toBe(200);
    expect(res.body.data.length).toBe(0);
  });

  it('should set main department', async () => {
    const user = await db.getRepository('users').findOne();
    const depts = await repo.create({
      values: [
        {
          title: 'Dept1',
          members: [user.id],
        },
        {
          title: 'Dept2',
          members: [user.id],
        },
      ],
    });

    const userRepo = db.getRepository('users');
    await userRepo.update({
      filterByTk: 1,
      values: {
        mainDepartmentId: depts[0].id,
      },
    });

    const res = await agent.resource('users').setMainDepartment({
      values: {
        userId: user.id,
        departmentId: depts[1].id,
      },
    });
    expect(res.status).toBe(200);

    const user2 = await userRepo.findOne({
      filterByTk: 1,
      fields: ['id', 'mainDepartmentId'],
    });
    expect(user2.mainDepartmentId).toBe(depts[1].id);
  });

  it('should allow setting mainDepartmentId when submitting departments together (user had none before)', async () => {
    const userRepo = db.getRepository('users');
    const user = await userRepo.findOne();

    const dept = await repo.create({
      values: { title: 'Dept3' },
    });

    const resBefore = await db.getRepository('departmentsUsers').count({
      filter: { userId: user.id },
    });
    expect(resBefore).toBe(0);

    await userRepo.update({
      filterByTk: user.id,
      values: {
        departments: [dept.id],
        mainDepartmentId: dept.id,
      },
    });

    const userReload = await userRepo.findOne({
      filterByTk: user.id,
      fields: ['id', 'mainDepartmentId'],
    });
    expect(userReload.mainDepartmentId).toBe(dept.id);

    const membershipCount = await db.getRepository('departmentsUsers').count({
      filter: { userId: user.id, departmentId: dept.id },
    });
    expect(membershipCount).toBe(1);
  });
});
