/**
 * Generate the Python code for the notebook
 *
 * Copyright 2022 CS GROUP - France, http://www.c-s.fr
 * All rights reserved
 */

import { geojsonToWKT } from '@terraformer/wkt';

import { IFormInput } from '../types';
import { isUndefined } from 'lodash';
import { useEodagSettings } from '../hooks/useEodagSettings';

const formatDate = (date: Date): string => {
  const local = new Date(date);
  local.setMinutes(date.getMinutes() - date.getTimezoneOffset());
  return local.toJSON().slice(0, 10);
};

export const codeGenerator = async (
  {
    startDate,
    endDate,
    productType,
    geometry,
    additionalParameters,
    provider,
    id,
    ...extraParams
  }: IFormInput,
  replaceCode: boolean
) => {
  const { getEodagSettings } = useEodagSettings();
  const settings = await getEodagSettings();
  const searchCount = settings.searchCount;

  const start = startDate ? formatDate(startDate) : undefined;
  const end = endDate ? formatDate(endDate) : undefined;
  const tab = ' '.repeat(4);
  const geometryIsOk = geometry?.type && geometry?.coordinates;

  const replacedCellIntro =
    '# Code generated by eodag-labextension, will be automatically replaced if a new search is performed';
  const standardMessage = `from eodag import EODataAccessGateway, setup_logging

setup_logging(1)  # 0: nothing, 1: only progress bars, 2: INFO, 3: DEBUG

dag = EODataAccessGateway()`;

  let code = replaceCode
    ? `${replacedCellIntro}
${standardMessage}`
    : `${standardMessage}`;

  if (geometryIsOk) {
    code += `
geometry = "${geojsonToWKT(geometry)}"`;
  }
  code += `
search_results = dag.search(`;
  if (provider) {
    code += `
    provider="${provider}",`;
  }
  code += `
    productType="${productType}",`;
  if (geometryIsOk) {
    code += `
    geom=geometry,`;
  }
  if (start) {
    code += `
    start="${start}",`;
  }
  if (end) {
    code += `
    end="${end}",`;
  }
  if (id) {
    code += `
    id="${id}",`;
  }
  if (searchCount === true) {
    code += `
    count=True,`;
  }
  let filteredParameters: { name: string; value: string }[] = [];
  if (!isUndefined(additionalParameters)) {
    filteredParameters = additionalParameters.filter(
      ({ name, value }) => name && value && name !== '' && value !== ''
    );
  }

  const extraParamEntries = Object.entries(extraParams).filter(
    ([_, value]) => value !== undefined
  );

  if (filteredParameters.length > 0 || extraParamEntries.length > 0) {
    code += '\n' + tab + '**{\n';

    // Map additionalParameters
    code += filteredParameters
      .map(({ name, value }) => {
        const processedValue = Array.isArray(value)
          ? `[${value
              .map((item: any) =>
                typeof item === 'string' ? `"${item.trim()}"` : item
              )
              .join(', ')}]`
          : typeof value === 'string'
            ? `"${value.trim()}"`
            : value;
        return `${tab + tab}"${name}": ${processedValue},`;
      })
      .join('\n');

    // Map extra parameters dynamically
    if (extraParamEntries.length > 0) {
      if (filteredParameters.length > 0) {
        code += '\n';
      } // Separate sections
      code += extraParamEntries
        .map(([key, value]) => {
          const processedValue = Array.isArray(value)
            ? `[${value
                .map((item: any) =>
                  typeof item === 'string' ? `"${item.trim()}"` : item
                )
                .join(', ')}]`
            : typeof value === 'string'
              ? `"${value.trim()}"`
              : value;
          return `${tab + tab}"${key}": ${processedValue},`;
        })
        .join('\n');
    }

    code += '\n' + `${tab}}`; // Close dictionary
  }
  code += '\n)';
  code += '\nsearch_results';

  return code;
};
