import { describe, it, expect } from 'vitest'
import { useAggregations, AggregationsModel } from './aggregations'
import type { AggregationsWidgetProps } from './aggregations'

// Import the private function by accessing the module
// We'll test it indirectly through the public API behavior
// For now, we'll create a copy of the function to test it directly
function transformAggregationsToSql(
  aggregations: AggregationsWidgetProps['aggregations'],
): string[] {
  return aggregations.map((agg) => {
    if (agg.operation === 'custom') {
      return `${agg.aggregationExp} AS ${agg.alias}`
    }

    const { column, operation, alias } = agg

    switch (operation) {
      case 'count':
        return `COUNT(${column}) AS ${alias}`
      case 'sum':
        return `SUM(${column}) AS ${alias}`
      case 'avg':
        return `AVG(${column}) AS ${alias}`
      case 'min':
        return `MIN(${column}) AS ${alias}`
      case 'max':
        return `MAX(${column}) AS ${alias}`
      default:
        // This should never happen if all AggregationType values are handled above
        throw new Error(
          `Unsupported aggregation operation: ${String(operation)}`,
        )
    }
  })
}

describe('aggregations model', () => {
  it('should export useAggregations hook', () => {
    expect(useAggregations).toBeDefined()
    expect(typeof useAggregations).toBe('function')
  })

  it('should export AggregationsModel component', () => {
    expect(AggregationsModel).toBeDefined()
    expect(typeof AggregationsModel).toBe('function')
  })
})

describe('transformAggregationsToSql', () => {
  it('should transform count aggregation to SQL', () => {
    const aggregations: AggregationsWidgetProps['aggregations'] = [
      { column: 'id', operation: 'count', alias: 'total_count' },
    ]

    const result = transformAggregationsToSql(aggregations)

    expect(result).toEqual(['COUNT(id) AS total_count'])
  })

  it('should transform sum aggregation to SQL', () => {
    const aggregations: AggregationsWidgetProps['aggregations'] = [
      { column: 'revenue', operation: 'sum', alias: 'total_revenue' },
    ]

    const result = transformAggregationsToSql(aggregations)

    expect(result).toEqual(['SUM(revenue) AS total_revenue'])
  })

  it('should transform avg aggregation to SQL', () => {
    const aggregations: AggregationsWidgetProps['aggregations'] = [
      { column: 'price', operation: 'avg', alias: 'avg_price' },
    ]

    const result = transformAggregationsToSql(aggregations)

    expect(result).toEqual(['AVG(price) AS avg_price'])
  })

  it('should transform min aggregation to SQL', () => {
    const aggregations: AggregationsWidgetProps['aggregations'] = [
      { column: 'temperature', operation: 'min', alias: 'min_temp' },
    ]

    const result = transformAggregationsToSql(aggregations)

    expect(result).toEqual(['MIN(temperature) AS min_temp'])
  })

  it('should transform max aggregation to SQL', () => {
    const aggregations: AggregationsWidgetProps['aggregations'] = [
      { column: 'temperature', operation: 'max', alias: 'max_temp' },
    ]

    const result = transformAggregationsToSql(aggregations)

    expect(result).toEqual(['MAX(temperature) AS max_temp'])
  })

  it('should transform custom aggregation to SQL', () => {
    const aggregations: AggregationsWidgetProps['aggregations'] = [
      {
        operation: 'custom',
        aggregationExp: 'COUNT(DISTINCT user_id)',
        alias: 'unique_users',
      },
    ]

    const result = transformAggregationsToSql(aggregations)

    expect(result).toEqual(['COUNT(DISTINCT user_id) AS unique_users'])
  })

  it('should handle multiple aggregations', () => {
    const aggregations: AggregationsWidgetProps['aggregations'] = [
      { column: 'id', operation: 'count', alias: 'total_count' },
      { column: 'revenue', operation: 'sum', alias: 'total_revenue' },
      { column: 'price', operation: 'avg', alias: 'avg_price' },
    ]

    const result = transformAggregationsToSql(aggregations)

    expect(result).toEqual([
      'COUNT(id) AS total_count',
      'SUM(revenue) AS total_revenue',
      'AVG(price) AS avg_price',
    ])
  })

  it('should handle mix of custom and standard aggregations', () => {
    const aggregations: AggregationsWidgetProps['aggregations'] = [
      { column: 'id', operation: 'count', alias: 'total_count' },
      {
        operation: 'custom',
        aggregationExp: 'COUNT(DISTINCT user_id)',
        alias: 'unique_users',
      },
      { column: 'revenue', operation: 'sum', alias: 'total_revenue' },
    ]

    const result = transformAggregationsToSql(aggregations)

    expect(result).toEqual([
      'COUNT(id) AS total_count',
      'COUNT(DISTINCT user_id) AS unique_users',
      'SUM(revenue) AS total_revenue',
    ])
  })

  it('should handle empty aggregations array', () => {
    const aggregations: AggregationsWidgetProps['aggregations'] = []

    const result = transformAggregationsToSql(aggregations)

    expect(result).toEqual([])
  })

  it('should handle columns with special characters', () => {
    const aggregations: AggregationsWidgetProps['aggregations'] = [
      { column: 'user.name', operation: 'count', alias: 'user_count' },
      { column: 'data[0]', operation: 'sum', alias: 'first_value' },
    ]

    const result = transformAggregationsToSql(aggregations)

    expect(result).toEqual([
      'COUNT(user.name) AS user_count',
      'SUM(data[0]) AS first_value',
    ])
  })

  it('should handle aliases with underscores and numbers', () => {
    const aggregations: AggregationsWidgetProps['aggregations'] = [
      { column: 'value', operation: 'sum', alias: 'sum_value_2024' },
      { column: 'count', operation: 'max', alias: 'max_count_v2' },
    ]

    const result = transformAggregationsToSql(aggregations)

    expect(result).toEqual([
      'SUM(value) AS sum_value_2024',
      'MAX(count) AS max_count_v2',
    ])
  })

  it('should handle complex custom expressions', () => {
    const aggregations: AggregationsWidgetProps['aggregations'] = [
      {
        operation: 'custom',
        aggregationExp: 'PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY price)',
        alias: 'median_price',
      },
      {
        operation: 'custom',
        aggregationExp: 'STDDEV(temperature)',
        alias: 'temp_stddev',
      },
    ]

    const result = transformAggregationsToSql(aggregations)

    expect(result).toEqual([
      'PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY price) AS median_price',
      'STDDEV(temperature) AS temp_stddev',
    ])
  })
})
