import test from 'node:test';
import assert from 'node:assert/strict';

import {
  filterOvertimeRecordsForExportMonth,
  filterOvertimeRecordsForViewer,
  type OvertimeRecord,
} from './overtime';
import type { AuthUser } from './auth-user';
import type { Department, Member, RoleItem } from './members';

const departments: Department[] = [
  { id: 'dept-tech', name: 'Tech', order: 1, createdAt: '2024-01-01' },
  { id: 'dept-front', name: 'Frontend', parentId: 'dept-tech', order: 1, createdAt: '2024-01-01' },
  { id: 'dept-back', name: 'Backend', parentId: 'dept-tech', order: 2, createdAt: '2024-01-01' },
  { id: 'dept-product', name: 'Product', order: 2, createdAt: '2024-01-01' },
];

const members: Member[] = [
  member('m-lead', 'Lead', 'dept-tech', 'role-lead'),
  member('m-front', 'Frontend Alice', 'dept-front', 'role-dev'),
  member('m-back', 'Backend Bob', 'dept-back', 'role-dev'),
  member('m-pm', 'PM Carol', 'dept-product', 'role-pm'),
];

const records: OvertimeRecord[] = [
  record('ot-front', 'Frontend Alice'),
  record('ot-back', 'Backend Bob'),
  record('ot-pm', 'PM Carol'),
];

const exportRecords: OvertimeRecord[] = [
  {
    id: 'july-1',
    projectId: 'project-1',
    person: 'Alice',
    startTime: '2026-07-01T19:00:00',
    endTime: '2026-07-01T21:00:00',
    duration: 2,
    reasonId: 'reason-1',
    createdAt: '2026-07-01',
  },
  {
    id: 'august-1',
    projectId: 'project-1',
    person: 'Bob',
    startTime: '2026-08-02T19:00:00',
    endTime: '2026-08-02T21:00:00',
    duration: 2,
    reasonId: 'reason-1',
    createdAt: '2026-08-02',
  },
];

test('filterOvertimeRecordsForViewer limits non-admin viewers to their department tree', () => {
  const visible = filterOvertimeRecordsForViewer(records, {
    viewer: toAuthUser(members[0]),
    viewerRole: role('role-lead', ['overtime:view']),
    members,
    departments,
  });

  assert.deepEqual(visible.map((item) => item.id), ['ot-front', 'ot-back']);
});

test('filterOvertimeRecordsForViewer lets wildcard admin view every department', () => {
  const visible = filterOvertimeRecordsForViewer(records, {
    viewer: toAuthUser(members[0]),
    viewerRole: role('role-admin', ['*']),
    members,
    departments,
  });

  assert.deepEqual(visible.map((item) => item.id), ['ot-front', 'ot-back', 'ot-pm']);
});

test('filters export records by selected month', () => {
  const result = filterOvertimeRecordsForExportMonth(exportRecords, '2026-07');

  assert.deepEqual(result.map((record) => record.id), ['july-1']);
});

test('keeps all export records when all months are selected', () => {
  const result = filterOvertimeRecordsForExportMonth(exportRecords, '');

  assert.deepEqual(result.map((record) => record.id), ['july-1', 'august-1']);
});

function member(id: string, name: string, departmentId: string, roleId: string): Member {
  return {
    id,
    name,
    username: id.toUpperCase(),
    departmentId,
    roleId,
    phone: '',
    email: '',
    password: '',
    createdAt: '2024-01-01',
  };
}

function record(id: string, person: string): OvertimeRecord {
  return {
    id,
    person,
    projectId: 'project-1',
    startTime: '2026-06-01T19:00',
    endTime: '2026-06-01T21:00',
    duration: 2,
    reasonId: 'reason-1',
    createdAt: '2026-06-01',
  };
}

function role(id: string, permissions: string[]): RoleItem {
  return {
    id,
    name: id,
    createdAt: '2024-01-01',
    permissions,
  };
}

function toAuthUser(member: Member): AuthUser {
  return {
    id: member.id,
    name: member.name,
    username: member.username ?? member.id.toUpperCase(),
    roleId: member.roleId,
    departmentId: member.departmentId,
    email: member.email,
  };
}
