<template>
  <div class="space-y-3">
    <UTable :data="tableData" :columns="tableColumns" class="w-full">
      <template v-for="col in dataColumns" :key="col.key" #[`${col.key}-cell`]="slotProps">
        <UInput
          :model-value="getCellValue(slotProps.row as TableRow<TableRowData>, col.key)"
          :disabled="disabled"
          class="w-full min-w-32"
          @update:model-value="
            (val: string | number) => updateCell((slotProps.row as TableRow<TableRowData>).index, col.key, String(val))
          "
        />
      </template>
      <template #actions-cell="{ row }">
        <UButton
          v-if="!disabled"
          icon="i-lucide-trash-2"
          color="error"
          variant="ghost"
          size="xs"
          :aria-label="$t('applicationForms.formElements.table.removeRow')"
          @click="removeRow(row.index)"
        />
      </template>
    </UTable>

    <div v-if="tableData.length === 0" class="text-center text-dimmed py-4">
      {{ $t('applicationForms.formElements.table.noData') }}
    </div>

    <UButton v-if="!disabled" variant="outline" size="sm" leading-icon="i-lucide-plus" @click="addRow">
      {{ $t('applicationForms.formElements.table.addRow') }}
    </UButton>
  </div>
</template>

<script setup lang="ts">
import type { FormOptionDto } from '~~/.api-client'
import type { TableColumn, TableRow } from '@nuxt/ui'

const props = defineProps<{
  formOptions: FormOptionDto[]
  disabled?: boolean
}>()

const emit = defineEmits<{
  (e: 'update:formOptions', value: FormOptionDto[]): void
}>()

type TableRowData = Record<string, string>

interface DataColumn {
  key: string
  colIndex: number
}

const dataColumns = computed<DataColumn[]>(() =>
  props.formOptions.map((_, index) => ({
    key: `col_${index}`,
    colIndex: index
  }))
)

const tableColumns = computed<TableColumn<TableRowData>[]>(() => {
  const columns: TableColumn<TableRowData>[] = props.formOptions.map((option, index) => ({
    accessorKey: `col_${index}`,
    header: option.label || ''
  }))

  if (!props.disabled) {
    columns.push({
      id: 'actions',
      header: ''
    })
  }

  return columns
})

const tableData = computed<TableRowData[]>(() => {
  if (props.formOptions.length === 0) return []

  const columnData: string[][] = props.formOptions.map((option) => {
    try {
      const parsed = JSON.parse(option.value || '[]')
      return Array.isArray(parsed) ? parsed : []
    } catch {
      return []
    }
  })

  const rowCount = Math.max(...columnData.map((col) => col.length), 0)

  const rows: TableRowData[] = []
  for (let rowIndex = 0; rowIndex < rowCount; rowIndex++) {
    const row: TableRowData = {}
    props.formOptions.forEach((_, colIndex) => {
      row[`col_${colIndex}`] = columnData[colIndex]?.[rowIndex] ?? ''
    })
    rows.push(row)
  }

  return rows
})

function getCellValue(row: TableRow<TableRowData>, columnKey: string): string {
  return row.original[columnKey] ?? ''
}

function updateCell(rowIndex: number, columnKey: string, value: string) {
  const colIndex = parseInt(columnKey.replace('col_', ''), 10)

  const updatedOptions = props.formOptions.map((option, index) => {
    if (index !== colIndex) return option

    let columnValues: string[]
    try {
      columnValues = JSON.parse(option.value || '[]')
      if (!Array.isArray(columnValues)) columnValues = []
    } catch {
      columnValues = []
    }

    while (columnValues.length <= rowIndex) {
      columnValues.push('')
    }
    columnValues[rowIndex] = value

    return { ...option, value: JSON.stringify(columnValues) }
  })

  emit('update:formOptions', updatedOptions)
}

function addRow() {
  const updatedOptions = props.formOptions.map((option) => {
    let columnValues: string[]
    try {
      columnValues = JSON.parse(option.value || '[]')
      if (!Array.isArray(columnValues)) columnValues = []
    } catch {
      columnValues = []
    }

    columnValues.push('')

    return { ...option, value: JSON.stringify(columnValues) }
  })

  emit('update:formOptions', updatedOptions)
}

function removeRow(rowIndex: number) {
  const updatedOptions = props.formOptions.map((option) => {
    let columnValues: string[]
    try {
      columnValues = JSON.parse(option.value || '[]')
      if (!Array.isArray(columnValues)) columnValues = []
    } catch {
      columnValues = []
    }

    columnValues.splice(rowIndex, 1)

    return { ...option, value: JSON.stringify(columnValues) }
  })

  emit('update:formOptions', updatedOptions)
}
</script>
