Source: utils/utils.js

export const severityLevels = {
  notice: 'notice',
  informational: 'info',
  warning: 'warning',
  error: 'error'
}

export const dataSubjects = {
  'article-4-direction': {
    available: true,
    dataSets: [
      {
        value: 'article-4-direction',
        text: 'Article 4 direction',
        available: true
      },
      {
        value: 'article-4-direction-area',
        text: 'Article 4 direction area',
        available: true
      }
    ]
  },
  'brownfield-land': {
    available: true,
    dataSets: [
      {
        value: 'brownfield-land',
        text: 'Brownfield land',
        available: true
      },
      {
        value: 'brownfield-site',
        text: 'Brownfield site',
        available: false
      }
    ]
  },
  'conservation-area': {
    available: true,
    dataSets: [
      {
        value: 'conservation-area',
        text: 'Conservation area',
        available: true
      },
      {
        value: 'conservation-area-document',
        text: 'Conservation area document',
        available: true
      }
    ]
  },
  'listed-building': {
    available: true,
    dataSets: [
      {
        value: 'listed-building',
        text: 'Listed building',
        available: false
      },
      {
        value: 'listed-building-grade',
        text: 'Listed building grade',
        available: false
      },
      {
        value: 'listed-building-outline',
        text: 'Listed building outline',
        available: true
      }
    ]
  },
  'tree-preservation-order': {
    available: true,
    dataSets: [
      {
        value: 'tree',
        text: 'Tree',
        available: true,
        requiresGeometryTypeSelection: true
      },
      {
        value: 'tree-preservation-order',
        text: 'Tree preservation order',
        available: true
      },
      {
        value: 'tree-preservation-zone',
        text: 'Tree preservation zone',
        available: true
      }
    ]
  }
}

export const entryIssueGroups = [
  {
    type: 'missing value',
    field: 'reference'
  },
  {
    type: 'reference values are not unique',
    field: 'reference'
  },
  {
    type: 'unknown entity - missing reference',
    field: 'entity'
  }
]

export function makeDatasetsLookup (dataSubjects) {
  const lookup = new Map()
  for (const [key, dataSubject] of Object.entries(dataSubjects)) {
    for (const dataSet of dataSubject.dataSets) {
      lookup.set(dataSet.value, { ...dataSet, dataSubject: key })
    }
  }

  return lookup
}

/**
 * @typedef {Object} Dataset
 * @property {string} value - Dataset value/identifier
 * @property {string} text - Display text for the dataset
 * @property {boolean} available - Whether the dataset is available
 * @property {string} dataSubject - The data subject this dataset belongs to
 * @property {boolean} [requiresGeometryTypeSelection] - Whether geometry type selection is required
 */

/**
 * Map of dataset identifiers to their configuration objects
 * @type {Map<string, Dataset>}
 */
export const datasets = makeDatasetsLookup(dataSubjects)

/**
 * Gets the list of available datasets sorted by display text
 *
 * @param {Object} dataSubjects - Data subjects configuration object
 * @returns {Dataset[]} Array of available datasets sorted by text property
 */
export function availableDatasets (dataSubjects) {
  const availableDataSubjects = Object.values(dataSubjects).filter(dataSubject => dataSubject.available)
  const dataSets = Object.values(availableDataSubjects).map(dataSubject => dataSubject.dataSets).flat()
  const availableDatasets = dataSets.filter(dataSet => dataSet.available)
  availableDatasets.sort((a, b) => a.text.localeCompare(b.text))
  return availableDatasets
}

export const finishedProcessingStatuses = [
  'COMPLETE',
  'FAILED'
]

export const allowedFileTypes = {
  csv: ['text/csv', 'text/plain', 'application/octet-stream', 'binary/octet-stream'],
  xls: ['application/vnd.ms-excel', 'application/octet-stream', 'binary/octet-stream'],
  xlsx: ['application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'application/octet-stream', 'binary/octet-stream'],
  xml: ['application/xml', 'text/xml'],
  json: ['application/json', 'application/octet-stream', 'binary/octet-stream'],
  geojson: ['application/vnd.geo+json', 'application/octet-stream', 'binary/octet-stream', 'application/geo+json'],
  gml: ['application/gml+xml', 'application/octet-stream', 'binary/octet-stream'],
  gpkg: ['application/gpkg', 'application/octet-stream', 'binary/octet-stream'],
  sqlite: ['application/geopackage+sqlite3', 'application/octet-stream', 'binary/octet-stream'],
  zip: ['application/zip', 'application/octet-stream', 'binary/octet-stream']

}

/**
 * @typedef {Object} RequiredDataset
 * @property {string} dataset - The dataset identifier
 * @property {string} deadline - The deadline pattern in ISO format with YYYY placeholder
 * @property {number} noticePeriod - Number of months before deadline to show notice
 */

/** @type {RequiredDataset[]} */
export const requiredDatasets = [
  {
    dataset: 'brownfield-land',
    deadline: 'YYYY-12-31T23:59:59.000Z',
    noticePeriod: 4 // months
  }
]

/**
 * Calculates the deadline date and its historical dates (last year's deadline, two years ago's deadline)
 * based on the provided deadline string.
 *
 * @param {string} deadline - The deadline date string in the format 'YYYY-MM-DDTHH:MM:SSZ'
 * @returns {object} An object containing the calculated deadline dates:
 *   - deadlineDate: The calculated deadline date
 *   - lastYearDeadline: The deadline date one year ago from the calculated deadline date
 *   - twoYearsAgoDeadline: The deadline date two years ago from the calculated deadline date
 *
 * @example
 * const deadline = 'XXXX-03-15T14:30:00Z';
 * const deadlines = getDeadlineHistory(deadline);
 * console.log(deadlines);
 * // Output:
 * // {
 * //   deadlineDate: <Date>,
 * //   lastYearDeadline: <Date>,
 * //   twoYearsAgoDeadline: <Date>
 * // }
 */
export const getDeadlineHistory = (deadline) => {
  const deadlineRegex = /^.{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12]\d|3[01])T(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d{1,3})?Z$/

  if (!deadlineRegex.test(deadline)) {
    throw new Error(`Invalid deadline format. Expected 'YYYY-MM-DDTHH:MM:SSSZ', got '${deadline}'`)
  }

  const deadlineParts = deadline.split(/[-T:.Z]/)
  const currentDate = new Date()

  const deadlineDate = new Date(
    currentDate.getFullYear(), // year
    parseInt(deadlineParts[1], 10) - 1, // month (0-based)
    deadlineParts[2], // day
    deadlineParts[3], // hour
    deadlineParts[4], // minute
    deadlineParts[5] // second
  )

  const isDeadlineThisYear = deadlineDate <= currentDate

  if (isDeadlineThisYear) {
    deadlineDate.setFullYear(currentDate.getFullYear() + 1)
  }

  const lastYearDeadline = new Date(deadlineDate.getTime())
  lastYearDeadline.setFullYear(deadlineDate.getFullYear() - 1)

  const twoYearsAgoDeadline = new Date(lastYearDeadline.getTime())
  twoYearsAgoDeadline.setFullYear(lastYearDeadline.getFullYear() - 1)

  return {
    deadlineDate,
    lastYearDeadline,
    twoYearsAgoDeadline
  }
}

export const issueErrorMessageHtml = (errorMessage, issue) =>
  `${issue && issue.value ? issue.value : (issue && issue.length ? issue : '')}<p class="govuk-error-message">${errorMessage}</p>`