/* ============================================================
   MESTAFF – EMPLOYEE EDIT SERVICE
   Bez zásahu do existujícího EmployeeService.gs.
============================================================ */


function getEmployeeDetail(
  token,
  employeeId
) {

  const currentUser =
    requireUser_(
      token,
      [
        'ADMIN',
        'MANAGER'
      ]
    );


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


  const employee =
    employees.find(
      function(row) {

        return (
          String(
            row.employee_id
          ) ===
          String(
            employeeId
          )
        );

      }
    );


  if (
    !employee
  ) {

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

  }


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


  const employeeUser =
    users.find(
      function(row) {

        return (
          String(
            row.employee_id
          ) ===
          String(
            employeeId
          )
        );

      }
    );


  if (
    currentUser.role !==
      'ADMIN' &&
    employeeUser &&
    employeeUser.role ===
      'ADMIN'
  ) {

    throw new Error(
      'Vedoucí nemůže upravovat administrátora.'
    );

  }


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


  const currentRate =
    employeeEditCurrentRate_(
      rates,
      employeeId,
      new Date()
    );


  return {

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

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

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

    email:
      String(
        employee.email ||
        (
          employeeUser
            ? employeeUser.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:
      employeeEditDateOnly_(
        employee.start_date
      ),

    end_date:
      employeeEditDateOnly_(
        employee.end_date
      ),

    active:
      employeeEditBool_(
        employee.active
      ),

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

    hourly_rate:
      currentRate
        ? numberFromSheet_(
            currentRate.hourly_rate
          )
        : 0

  };

}



function updateEmployee(
  token,
  data
) {

  const currentUser =
    requireUser_(
      token,
      [
        'ADMIN',
        'MANAGER'
      ]
    );


  data =
    data ||
    {};


  const employeeId =
    String(
      data.employee_id ||
      ''
    ).trim();


  if (
    !employeeId
  ) {

    throw new Error(
      'Chybí employee_id.'
    );

  }


  const firstName =
    String(
      data.first_name ||
      ''
    ).trim();


  const lastName =
    String(
      data.last_name ||
      ''
    ).trim();


  const email =
    String(
      data.email ||
      ''
    )
      .trim()
      .toLowerCase();


  const role =
    String(
      data.role ||
      'EMPLOYEE'
    )
      .trim()
      .toUpperCase();


  if (
    !firstName ||
    !lastName
  ) {

    throw new Error(
      'Jméno a příjmení jsou povinné.'
    );

  }


  if (
    !email ||
    !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(
      email
    )
  ) {

    throw new Error(
      'Zadej platný e-mail.'
    );

  }


  if (
    ![
      'EMPLOYEE',
      'MANAGER',
      'ACCOUNTANT',
      'ADMIN'
    ].includes(
      role
    )
  ) {

    throw new Error(
      'Neplatná role.'
    );

  }


  if (
    currentUser.role !==
      'ADMIN' &&
    role ===
      'ADMIN'
  ) {

    throw new Error(
      'Pouze administrátor může přidělit roli ADMIN.'
    );

  }


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


  const employee =
    employees.find(
      function(row) {

        return (
          String(
            row.employee_id
          ) ===
          employeeId
        );

      }
    );


  if (
    !employee
  ) {

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

  }


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


  const employeeUser =
    users.find(
      function(row) {

        return (
          String(
            row.employee_id
          ) ===
          employeeId
        );

      }
    );


  if (
    currentUser.role !==
      'ADMIN' &&
    employeeUser &&
    String(
      employeeUser.role
    ) ===
      'ADMIN'
  ) {

    throw new Error(
      'Vedoucí nemůže upravovat administrátora.'
    );

  }


  /*
   * Kontrola e-mailové duplicity.
   */

  const duplicateEmployee =
    employees.find(
      function(row) {

        return (
          String(
            row.employee_id
          ) !==
          employeeId &&
          String(
            row.email ||
            ''
          )
            .trim()
            .toLowerCase() ===
          email
        );

      }
    );


  const duplicateUser =
    users.find(
      function(row) {

        return (
          String(
            row.employee_id ||
            ''
          ) !==
          employeeId &&
          String(
            row.email ||
            ''
          )
            .trim()
            .toLowerCase() ===
          email
        );

      }
    );


  if (
    duplicateEmployee ||
    duplicateUser
  ) {

    throw new Error(
      'Tento e-mail už používá jiný účet.'
    );

  }


  const pin =
    String(
      data.terminal_pin ||
      ''
    ).trim();


  if (
    pin &&
    !/^\d{4,6}$/.test(
      pin
    )
  ) {

    throw new Error(
      'PIN musí obsahovat 4 až 6 číslic.'
    );

  }


  if (
    pin
  ) {

    const duplicatePin =
      employees.find(
        function(row) {

          return (
            String(
              row.employee_id
            ) !==
            employeeId &&
            employeeEditBool_(
              row.active
            ) &&
            String(
              row.terminal_pin ||
              ''
            ).trim() ===
            pin
          );

        }
      );


    if (
      duplicatePin
    ) {

      throw new Error(
        'Tento PIN už používá jiný aktivní zaměstnanec.'
      );

    }

  }


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


  /*
   * Základní data zaměstnance.
   */

  updateBy_(
    CFG.SHEETS.EMPLOYEES,
    'employee_id',
    employeeId,
    {

      first_name:
        firstName,

      last_name:
        lastName,

      email:
        email,

      phone:
        String(
          data.phone ||
          ''
        ).trim(),

      company_id:
        String(
          data.company_id ||
          ''
        ).trim(),

      location_id:
        String(
          data.location_id ||
          ''
        ).trim(),

      position:
        String(
          data.position ||
          ''
        ).trim(),

      employment_type:
        String(
          data.employment_type ||
          ''
        ).trim(),

      terminal_pin:
        pin,

      start_date:
        String(
          data.start_date ||
          ''
        ).trim(),

      end_date:
        String(
          data.end_date ||
          ''
        ).trim(),

      active:
        active

    }
  );


  /*
   * Synchronizace přihlašovacího účtu.
   */

  if (
    employeeUser
  ) {

    updateBy_(
      CFG.SHEETS.USERS,
      'user_id',
      employeeUser.user_id,
      {

        email:
          email,

        role:
          role,

        active:
          active

      }
    );

  }


  /*
   * Historická změna hodinové sazby.
   */

  let rateChanged =
    false;


  const newRate =
    employeeEditNumber_(
      data.hourly_rate
    );


  const validFrom =
    String(
      data.rate_valid_from ||
      Utilities.formatDate(
        new Date(),
        CFG.TZ,
        'yyyy-MM-dd'
      )
    ).trim();


  if (
    !/^\d{4}-\d{2}-\d{2}$/.test(
      validFrom
    )
  ) {

    throw new Error(
      'Neplatné datum účinnosti nové sazby.'
    );

  }


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


  const currentRate =
    employeeEditCurrentRate_(
      rates,
      employeeId,
      employeeEditParseDate_(
        validFrom
      )
    );


  const currentRateAmount =
    currentRate
      ? numberFromSheet_(
          currentRate.hourly_rate
        )
      : 0;


  if (
    Math.abs(
      newRate -
      currentRateAmount
    ) >
    0.0001
  ) {

    /*
     * Zavřeme předchozí sazbu den před účinností nové.
     */

    if (
      currentRate &&
      currentRate.pay_rate_id
    ) {

      const previousDay =
        employeeEditAddDays_(
          validFrom,
          -1
        );


      const currentValidFrom =
        employeeEditDateOnly_(
          currentRate.valid_from
        );


      if (
        !currentValidFrom ||
        currentValidFrom <
        validFrom
      ) {

        updateBy_(
          CFG.SHEETS.PAY_RATES,
          'pay_rate_id',
          currentRate.pay_rate_id,
          {

            valid_to:
              previousDay

          }
        );

      }

    }


    append_(
      CFG.SHEETS.PAY_RATES,
      {

        pay_rate_id:
          uuid_(
            'RATE'
          ),

        employee_id:
          employeeId,

        valid_from:
          validFrom,

        valid_to:
          '',

        hourly_rate:
          newRate,

        created_by:
          currentUser.user_id,

        created_at:
          now_()

      }
    );


    rateChanged =
      true;

  }


  audit_(
    currentUser.user_id,
    'EMPLOYEE_UPDATED',
    'EMPLOYEE',
    employeeId,
    '',
    JSON.stringify({

      email:
        email,

      role:
        role,

      active:
        active,

      hourly_rate:
        newRate,

      rate_changed:
        rateChanged

    })
  );


  return {

    ok:true,

    rate_changed:
      rateChanged

  };

}



/* ============================================================
   HELPERS
============================================================ */

function employeeEditBool_(
  value
) {

  if (
    value ===
    true
  ) {

    return true;

  }


  return [
    'TRUE',
    'ANO',
    'YES',
    '1'
  ].includes(
    String(
      value ||
      ''
    )
      .trim()
      .toUpperCase()
  );

}


function employeeEditNumber_(
  value
) {

  const number =
    Number(
      String(
        value == null
          ? 0
          : value
      )
        .trim()
        .replace(
          ',',
          '.'
        )
    );


  if (
    !isFinite(
      number
    ) ||
    number <
    0
  ) {

    throw new Error(
      'Hodinová sazba musí být nezáporné číslo.'
    );

  }


  return Math.round(
    number *
    100
  ) /
  100;

}


function employeeEditParseDate_(
  value
) {

  const match =
    String(
      value ||
      ''
    )
      .trim()
      .match(
        /^(\d{4})-(\d{2})-(\d{2})$/
      );


  if (
    !match
  ) {

    return null;

  }


  return new Date(
    Number(
      match[1]
    ),
    Number(
      match[2]
    ) -
    1,
    Number(
      match[3]
    )
  );

}


function employeeEditDateOnly_(
  value
) {

  if (
    !value
  ) {

    return '';

  }


  if (
    /^\d{4}-\d{2}-\d{2}$/.test(
      String(
        value
      ).trim()
    )
  ) {

    return String(
      value
    ).trim();

  }


  const date =
    typeof parseEmployeeDate_ ===
      'function'
      ? parseEmployeeDate_(
          value
        )
      : new Date(
          value
        );


  if (
    !date ||
    isNaN(
      date.getTime()
    )
  ) {

    return '';

  }


  return Utilities.formatDate(
    date,
    CFG.TZ,
    'yyyy-MM-dd'
  );

}


function employeeEditCurrentRate_(
  rates,
  employeeId,
  targetDate
) {

  if (
    !targetDate
  ) {

    return null;

  }


  const target =
    Utilities.formatDate(
      targetDate,
      CFG.TZ,
      'yyyy-MM-dd'
    );


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

          if (
            String(
              rate.employee_id
            ) !==
            String(
              employeeId
            )
          ) {

            return false;

          }


          const from =
            employeeEditDateOnly_(
              rate.valid_from
            ) ||
            '0000-00-00';


          const to =
            employeeEditDateOnly_(
              rate.valid_to
            ) ||
            '9999-12-31';


          return (
            from <=
            target &&
            to >=
            target
          );

        }
      )
      .sort(
        function(a,b) {

          return employeeEditDateOnly_(
            b.valid_from
          ).localeCompare(
            employeeEditDateOnly_(
              a.valid_from
            )
          );

        }
      );


  return valid.length
    ? valid[0]
    : null;

}


function employeeEditAddDays_(
  yyyyMmDd,
  days
) {

  const date =
    employeeEditParseDate_(
      yyyyMmDd
    );


  if (
    !date
  ) {

    return '';

  }


  date.setDate(
    date.getDate() +
    Number(
      days ||
      0
    )
  );


  return Utilities.formatDate(
    date,
    CFG.TZ,
    'yyyy-MM-dd'
  );

}



/* ============================================================
   DIAGNOSTIKA
============================================================ */

function testEmployeeEditService() {

  Logger.log(
    'EMPLOYEES: ' +
    JSON.stringify(
      displayRows_(
        CFG.SHEETS.EMPLOYEES
      )
    )
  );


  Logger.log(
    'USERS: ' +
    JSON.stringify(
      displayRows_(
        CFG.SHEETS.USERS
      )
    )
  );


  Logger.log(
    'PAY_RATES: ' +
    JSON.stringify(
      displayRows_(
        CFG.SHEETS.PAY_RATES
      )
    )
  );


  Logger.log(
    'EmployeeEditService OK'
  );

}
