'use strict';

const { sql } = require('../../db');
const { db } = require('../../utils/dbName');

async function extract(pool, watermark, limit) {
  const metadata = await pool.request().query(`
    SELECT
      COL_LENGTH('${db()}productos', 'fechamodificacion') AS has_fechamodificacion,
      COL_LENGTH('${db()}productos', 'fecha') AS has_fecha,
      COL_LENGTH('${db()}productos', 'descripcion') AS has_descripcion,
      COL_LENGTH('${db()}productos', 'idgrupo') AS has_idgrupo,
      COL_LENGTH('${db()}productos', 'precio') AS has_precio,
      COL_LENGTH('${db()}productos', 'activo') AS has_activo,
      OBJECT_ID('${db()}productosdetalle') AS has_productosdetalle,
      COL_LENGTH('${db()}productosdetalle', 'precio') AS has_pd_precio,
      COL_LENGTH('${db()}productosdetalle', 'impuesto1') AS has_pd_impuesto1,
      COL_LENGTH('${db()}productosdetalle', 'bloqueado') AS has_pd_bloqueado,
      COL_LENGTH('${db()}productosdetalle', 'idunidad') AS has_pd_idunidad,
      COL_LENGTH('${db()}productosdetalle', 'idarea') AS has_pd_idarea,
      OBJECT_ID('${db()}grupos') AS has_grupos,
      COL_LENGTH('${db()}grupos', 'descripcion') AS has_grupo_descripcion,
      OBJECT_ID('${db()}subgruposproductos') AS has_subgruposproductos,
      OBJECT_ID('${db()}subgrupos') AS has_subgrupos,
      COL_LENGTH('${db()}subgrupos', 'descripcion') AS has_subgrupo_descripcion
  `);
  const row = metadata.recordset[0] || {};
  const hasUpdatedColumn = Boolean(row.has_fechamodificacion || row.has_fecha);
  const updatedExpr = row.has_fechamodificacion
    ? 'p.fechamodificacion'
    : (row.has_fecha ? 'p.fecha' : "CAST('2000-01-01' AS datetime)");
  const descripcionExpr = row.has_descripcion ? 'p.descripcion' : "CAST(p.idproducto AS nvarchar(80))";
  const idGrupoExpr = row.has_idgrupo ? 'p.idgrupo' : 'NULL';
  const hasProductDetail = Boolean(row.has_productosdetalle);
  const detailJoin = hasProductDetail ? `LEFT JOIN ${db()}productosdetalle pd ON pd.idproducto = p.idproducto` : '';
  const groupJoin = row.has_grupos ? `LEFT JOIN ${db()}grupos g ON g.idgrupo = p.idgrupo` : '';
  const subgroupJoin = row.has_subgruposproductos && row.has_subgrupos
    ? `LEFT JOIN ${db()}subgruposproductos sp ON sp.idproducto = p.idproducto
       LEFT JOIN ${db()}subgrupos sg ON sg.idsubgrupo = sp.idsubgrupo`
    : '';
  const precioExpr = row.has_pd_precio ? 'pd.precio' : (row.has_precio ? 'p.precio' : '0');
  const impuestoExpr = row.has_pd_impuesto1 ? 'pd.impuesto1' : '0';
  const bloqueadoExpr = row.has_pd_bloqueado ? 'pd.bloqueado' : '0';
  const unidadExpr = row.has_pd_idunidad ? 'pd.idunidad' : "''";
  const areaExpr = row.has_pd_idarea ? 'pd.idarea' : "''";
  const grupoDescExpr = row.has_grupo_descripcion ? 'g.descripcion' : "''";
  const subgrupoIdExpr = row.has_subgruposproductos ? 'sp.idsubgrupo' : "''";
  const subgrupoDescExpr = row.has_subgrupo_descripcion ? 'sg.descripcion' : "''";
  const activoExpr = row.has_activo ? 'p.activo' : '1';
  const whereExpr = hasUpdatedColumn
    ? `WHERE ${updatedExpr} > @last`
    : '';
  const orderExpr = hasUpdatedColumn
    ? `COALESCE(${updatedExpr}, CAST('2000-01-01' AS datetime)), p.idproducto`
    : 'p.idproducto';
  const result = await pool.request()
    .input('last', sql.DateTime, watermark ? new Date(watermark) : new Date('2000-01-01T00:00:00'))
    .input('limit', sql.Int, limit)
    .query(`
      SELECT TOP (@limit)
        CAST(p.idproducto AS varchar(80)) AS external_id,
        NULL AS source_created_at,
        COALESCE(${updatedExpr}, CAST('2000-01-01' AS datetime)) AS source_updated_at,
        NULL AS business_date,
        p.idproducto,
        ${descripcionExpr} AS descripcion,
        ${idGrupoExpr} AS idgrupo,
        ${grupoDescExpr} AS grupo,
        ${subgrupoIdExpr} AS idsubgrupo,
        ${subgrupoDescExpr} AS subgrupo,
        ${precioExpr} AS precio,
        ${impuestoExpr} AS impuesto1,
        ${bloqueadoExpr} AS bloqueado,
        ${unidadExpr} AS unidad,
        ${areaExpr} AS idarea,
        ${activoExpr} AS activo
      FROM ${db()}productos p
      ${detailJoin}
      ${groupJoin}
      ${subgroupJoin}
      ${whereExpr}
      ORDER BY ${orderExpr}
    `);
  return result.recordset.map((row) => ({ ...row, payload: row }));
}

module.exports = { entityType: 'products', extract };
