import * as fs from 'fs'
import * as path from 'path'
import { parseRUMObjectTo022FormatString } from '../utils'
import { isRumObjectsLinkedToYear } from '../utils/rum'
import { mapGroupingError } from './error-management'
import { GroupingInput } from './types'

const tryPath = (...parts: string[]) => {
  const fullPath = path.resolve(...parts)
  if (!fs.existsSync(fullPath)) {
    throw new Error(`Native module not found at ${fullPath}`)
  }
  return fullPath
}

const grp2025Path = tryPath(__dirname, '..', '..', 'build', 'Release', 'grp2025.node')

if (!fs.existsSync(grp2025Path)) {
  throw new Error(`Native module not found 2 at ${grp2025Path}`)
}

const grp2025Native = require(grp2025Path)
// const grp2025Native = require('bindings')('grp2025')
const grp2024Native = require('bindings')('grp2024')
const ficumNative = require('bindings')('ficum')

// Resolve paths relative to this package, not the consuming project
const getTablePath = (version: string): string => {
  try {
    // Find the package root by looking for package.json
    const packageJsonPath = require.resolve('@beparallel/grouping/package.json')
    const packageRoot = path.dirname(packageJsonPath)
    return path.join(packageRoot, 'tables', version) + path.sep
  } catch (error) {
    // Fallback for development or when require.resolve fails
    const packageRoot = path.resolve(__dirname, '../../')
    return path.join(packageRoot, 'tables', version) + path.sep
  }
}

// Wrapper for ficum with automatic table path resolution
const createFicumWrapper = () => {
  return {
    main: (
      ficuminPath: string,
      ficumoutPath: string,
      version: '2024' | '2025',
      log?: number,
      gestionPortee?: number,
      finessGeo?: number
    ) => {
      const dirtables = getTablePath(`V${version}`)
      return ficumNative.main(ficuminPath, ficumoutPath, dirtables, log ?? 0, gestionPortee ?? 1, finessGeo ?? 1)
    }
  }
}

// Extract the actual wrapper functions from the native modules
const grp2025 = (input: GroupingInput) => {
  const rumStrings = input.rumObjects.map((rumObject) => parseRUMObjectTo022FormatString(rumObject))
  const dirtab = getTablePath('V2025')
  const ns = rumStrings.length

  const result = grp2025Native.grp_2025_wrapper(rumStrings, dirtab, ns, input.typeEtab)
  const mappedError = mapGroupingError(result.returnCode)

  return {
    ...result,
    returnError: mappedError
  }
}

const grp2024 = (input: GroupingInput) => {
  const rumStrings = input.rumObjects.map((rumObject) => parseRUMObjectTo022FormatString(rumObject))
  const dirtab = getTablePath('V2024')
  const ns = rumStrings.length

  const result = grp2024Native.grp_2024_wrapper(rumStrings, dirtab, ns, input.typeEtab)
  const mappedError = mapGroupingError(result.returnCode)

  return {
    ...result,
    returnError: mappedError
  }
}

const ficum = createFicumWrapper()

const grp = (input: GroupingInput) => {
  const rumObjects = input.rumObjects
  if (isRumObjectsLinkedToYear(rumObjects, 2025)) {
    return grp2025(input)
  } else if (isRumObjectsLinkedToYear(rumObjects, 2024)) {
    return grp2024(input)
  }
  console.warn('No year found in rumObjects, using 2025 version')
  return grp2025(input)
}

export { grp, grp2024, grp2025 }
