import type { Context } from '@bamboocss/core'
import type { ConditionQuery } from '@bamboocss/types'
import outdent from 'outdent'

function formatConditionJsDoc(raw: ConditionQuery | undefined): string {
  if (!raw) return ''
  if (typeof raw === 'string') return `/** \`${raw}\` */\n`
  if (Array.isArray(raw)) return `/** \`${raw.join(' ')}\` */\n`
  // Object condition (multi-block) - display a compact representation
  return `/** Multi-block condition */\n`
}

export function generateConditions(ctx: Context) {
  const keys = Object.keys(ctx.conditions.values).concat('base')
  return {
    js: outdent`
    ${ctx.file.import('withoutSpace', '../helpers')}

    const conditionsStr = "${keys.join(',')}"
    const conditions = new Set(conditionsStr.split(','))

    const conditionRegex = /^@|&|&$/

    export function isCondition(value){
      return conditions.has(value) || conditionRegex.test(value)
    }

    const underscoreRegex = /^_/
    const conditionsSelectorRegex = /&|@/

    export function finalizeConditions(paths){
      return paths.map((path) => {
        if (conditions.has(path)){
          return path.replace(underscoreRegex, '')
        }

        if (conditionsSelectorRegex.test(path)){
          return \`[\${withoutSpace(path.trim())}]\`
        }

        return path
      })}

      export function sortConditions(paths){
        return paths.sort((a, b) => {
          const aa = isCondition(a)
          const bb = isCondition(b)
          if (aa && !bb) return 1
          if (!aa && bb) return -1
          return 0
        })
      }
      `,
    dts: outdent`
    ${ctx.file.importType('AnySelector, Selectors', './selectors')}

    export interface Conditions {
    ${keys
      .map(
        (key) =>
          `\t${
            key === 'base'
              ? `/** The base (=no conditions) styles to apply  */\n`
              : formatConditionJsDoc(ctx.conditions.get(key))
          }\t${JSON.stringify(key)}: string`,
      )
      .join('\n')}
    }

    export type ConditionalValue<V> =
      | V
      | Array<V | null>
      | {
          [K in keyof Conditions]?: ConditionalValue<V>
        }

    export type Nested<P> = P & {
      [K in Selectors]?: Nested<P>
    } & {
      [K in AnySelector]?: Nested<P>
    } & {
      [K in keyof Conditions]?: Nested<P>
    }

  `,
  }
}
