function createEmployee(token, data) {
  const admin = requireUser_(token,['ADMIN','MANAGER']);
  const email = emailNorm_(data.email);

  if (!email) throw new Error('E-mail je povinný.');
  if (findOne_(CFG.SHEETS.EMPLOYEES, r => emailNorm_(r.email) === email)) {
    throw new Error('Zaměstnanec s tímto e-mailem už existuje.');
  }

  const role = String(data.role || 'EMPLOYEE');
  if (!['EMPLOYEE','MANAGER','ACCOUNTANT','ADMIN'].includes(role)) {
    throw new Error('Neplatná role.');
  }

  const hourlyRate = data.hourly_rate === '' || data.hourly_rate === undefined
    ? ''
    : Number(data.hourly_rate);

  if (hourlyRate !== '' && (isNaN(hourlyRate) || hourlyRate < 0)) {
    throw new Error('Hodinová sazba není platná.');
  }

  const pin = String(data.terminal_pin || '').trim();
  if (pin && !/^\d{4,6}$/.test(pin)) {
    throw new Error('PIN musí mít 4 až 6 číslic.');
  }

  const emp = {
    employee_id: uuid_('EMP'),
    first_name: String(data.first_name || '').trim(),
    last_name: String(data.last_name || '').trim(),
    email: email,
    phone: String(data.phone || '').trim(),
    company_id: String(data.company_id || 'COMPANY_MAIN'),
    location_id: String(data.location_id || 'LOCATION_MAIN'),
    position: String(data.position || '').trim(),
    employment_type: String(data.employment_type || '').trim(),
    terminal_pin: pin,
    start_date: data.start_date || isoDate_(now_()),
    end_date: '',
    active: true
  };

  if (!emp.first_name || !emp.last_name) {
    throw new Error('Jméno a příjmení jsou povinné.');
  }

  append_(CFG.SHEETS.EMPLOYEES, emp);

  const user = {
    user_id: uuid_('USR'),
    email: email,
    role: role,
    employee_id: emp.employee_id,
    password_salt: '',
    password_hash: '',
    active: true,
    created_at: now_(),
    last_login: ''
  };

  append_(CFG.SHEETS.USERS, user);
  append_(CFG.SHEETS.USER_COMPANIES, {
    user_id: user.user_id,
    company_id: emp.company_id
  });

  if (hourlyRate !== '') {
    append_(CFG.SHEETS.PAY_RATES, {
      pay_rate_id: uuid_('RATE'),
      employee_id: emp.employee_id,
      valid_from: emp.start_date,
      valid_to: '',
      hourly_rate: hourlyRate,
      created_by: admin.user_id,
      created_at: now_()
    });
  }

  audit_(admin.user_id,'EMPLOYEE_CREATED','EMPLOYEE',emp.employee_id,'',emp);

  requestActivation(email);

  return {
    ok: true,
    employee_id: emp.employee_id
  };
}


function listEmployees(token) {

  requireUser_(
    token,
    ['ADMIN','MANAGER','ACCOUNTANT']
  );

  const employees =
    rows_(CFG.SHEETS.EMPLOYEES);

  const users =
    rows_(CFG.SHEETS.USERS);

  const rates =
    rows_(CFG.SHEETS.PAY_RATES);


  return employees.map(function(employee) {

    const user =
      users.find(function(u) {

        return String(u.employee_id) ===
               String(employee.employee_id);

      });


    const employeeRates =
      rates.filter(function(rate) {

        return String(rate.employee_id) ===
               String(employee.employee_id);

      });


    employeeRates.sort(function(a,b) {

      const dateA =
        a.valid_from
          ? new Date(a.valid_from).getTime()
          : 0;

      const dateB =
        b.valid_from
          ? new Date(b.valid_from).getTime()
          : 0;

      return dateB - dateA;

    });


    let hourlyRate = 0;

    if (employeeRates.length > 0) {

      hourlyRate =
        Number(
          employeeRates[0].hourly_rate || 0
        );

    }


    const active =
      employee.active === true ||
      String(employee.active)
        .toUpperCase() === 'TRUE';


    return {

      employee_id:
        String(employee.employee_id || ''),

      first_name:
        String(employee.first_name || ''),

      last_name:
        String(employee.last_name || ''),

      name:
        (
          String(employee.first_name || '') +
          ' ' +
          String(employee.last_name || '')
        ).trim(),

      email:
        String(employee.email || ''),

      phone:
        String(employee.phone || ''),

      company_id:
        String(employee.company_id || ''),

      location_id:
        String(employee.location_id || ''),

      position:
        String(employee.position || ''),

      employment_type:
        String(employee.employment_type || ''),

      terminal_pin:
        String(employee.terminal_pin || ''),

      start_date:
        employee.start_date
          ? String(employee.start_date)
          : '',

      end_date:
        employee.end_date
          ? String(employee.end_date)
          : '',

      active:
        active,

      role:
        user
          ? String(user.role || 'EMPLOYEE')
          : 'EMPLOYEE',

      hourly_rate:
        hourlyRate

    };

  });

}


function setEmployeeActive(token, employeeId, active) {
  const admin = requireUser_(token,['ADMIN']);

  const emp = findOne_(
    CFG.SHEETS.EMPLOYEES,
    r => String(r.employee_id) === String(employeeId)
  );

  if (!emp) throw new Error('Zaměstnanec nebyl nalezen.');

  const user = findOne_(
    CFG.SHEETS.USERS,
    r => String(r.employee_id) === String(employeeId)
  );

  updateBy_(
    CFG.SHEETS.EMPLOYEES,
    'employee_id',
    employeeId,
    {
      active: !!active,
      end_date: active ? '' : isoDate_(now_())
    }
  );

  if (user) {
    updateBy_(
      CFG.SHEETS.USERS,
      'user_id',
      user.user_id,
      { active: !!active }
    );
  }

  audit_(
    admin.user_id,
    'EMPLOYEE_ACTIVE_CHANGED',
    'EMPLOYEE',
    employeeId,
    emp.active,
    !!active
  );

  return { ok: true };
}


function getCompaniesAndLocations(token) {
  requireUser_(token,['ADMIN','MANAGER']);

  return {
    companies: rows_(CFG.SHEETS.COMPANIES)
      .filter(x =>
        x.active === true ||
        String(x.active).toUpperCase() === 'TRUE'
      ),

    locations: rows_(CFG.SHEETS.LOCATIONS)
      .filter(x =>
        x.active === true ||
        String(x.active).toUpperCase() === 'TRUE'
      )
  };
}