import type {
  BaseCard,
  EditConfig,
  ElementMetadata,
} from "@/definitions/shared/base"
import type {
  CreateConfig,
  DeleteConfig,
  UpdateConfig,
} from "@/definitions/shared/crud"
import type { RouteRef } from "@/definitions/shared/route"

/**
 * Built-in column types recognised by the table renderer.
 *
 * v1 also accepts custom strings (e.g. `"badges"`, `"external_link"`)
 * which the renderer resolves via its column-type registry. We model
 * those as `string` to keep the JSON schema permissive.
 */
export type TableColumnType =
  | "text"
  | "timestamp"
  | "laravel-timestamp"
  | "time_since"
  | "duration"
  | "boolean"
  | "status_circle"
  | "image"
  | "badge"
  | "badges"
  | "tags"
  | "translation"
  | "external_link"
  | "internal_link"
  | "export_button"
  | "download_button"
  | "markdown"
  | "action"
  | "_select"

/**
 * A single column header definition.
 *
 * `format`, `formatHtml`, `condition`, `transform`, `url`, `icon`,
 * `classList`, `statusText`, etc. are typed as `unknown` (not as
 * functions) so JSON definitions deserialise cleanly. The runtime
 * engine resolves named formatter strings via a registry, or invokes
 * the function directly when authored in TypeScript.
 */
export interface DataTableColumn {
  /** Data field key. Supports dot notation: `"user.name"`. */
  key: string
  /** Display title. */
  title?: string
  /** `"start" | "center" | "end"`. */
  align?: "start" | "center" | "end" | "left" | "right"
  /** Enable click-to-sort on this column. */
  sortable?: boolean
  /** Fixed column width (e.g. `"120px"`, `"10%"`). */
  width?: string
  /** Show or hide this column. */
  visible?: boolean
  /** Whether the column can be hidden via the column selector. */
  hideable?: boolean
  /**
   * Built-in column type or a custom-registered renderer name.
   * Omit (or use `"text"`) for plain text columns.
   */
  type?: TableColumnType | string
  /**
   * Value formatter. Accepts a function-name string (resolved via the
   * formatter registry) or a function reference when authored in TS.
   * Stored as `unknown` because functions are not JSON-serialisable.
   */
  format?: string | unknown
  /** HTML formatter; output is rendered raw. Same resolution as `format`. */
  formatHtml?: string | unknown
  /** Text prepended to the rendered value. */
  prepend?: string
  /** Text appended to the rendered value. */
  append?: string
  /** Static or dynamic icon. */
  icon?: string | unknown
  iconOptions?: {
    classList?: string[] | string
  }
  /** Per-row class list (string, array, or resolver). */
  classList?: string[] | string | unknown
  /** Class list applied to the header cell. */
  headerClassList?: string[] | string
  /** Class applied to data cells. */
  class?: string
  /** For `image` columns: URL transformer. */
  url?: string | unknown
  /** For `image` columns: inline CSS for the rendered image. */
  imageStyle?: Record<string, string | number>
  /** For `image` columns: field path used for the caption. */
  captionField?: string
  /** For `image` columns: format applied to the caption value. */
  captionFieldType?: string
  /** For `image` columns: render as a sprite asset. */
  sprite?: boolean
  /** For `status_circle` columns: resolver for the status text. */
  statusText?: string | unknown
  /** For `external_link` / `internal_link` columns: route resolver. */
  route?: string | unknown
  /** For `external_link` columns: anchor target. */
  target?: string
  /** For link/button columns: label resolver. */
  label?: string | unknown
  /** For `badge` columns: color resolver. */
  color?: string | unknown
  /** Visibility predicate. */
  condition?: string | unknown
  /** For `tags` / `badges` columns: per-item transform. */
  transform?: string | unknown
  /** For `translation` columns: path to the translations map. */
  translationLocation?: string
  /** For `action` columns / inline-update fields. */
  field?: Record<string, unknown>
  /** Additional implementation-specific props. */
  [key: string]: unknown
}

/**
 * Export button definition rendered in the table toolbar.
 */
export interface ExportConfig {
  /** Laravel-named route or URL. Can also be a resolver function (registry-resolved). */
  route: string | unknown
  /** Route params. */
  params?: Record<string, unknown> | Array<{ name: string; key?: string; value?: unknown }>
  /** Button label. */
  label?: string
  /** When true, only export the selected rows. */
  selected?: boolean
  /** When true, apply the current filter set to the export query. */
  applyFilters?: boolean
}

/**
 * A per-row or bulk action button (icon + tooltip + handler).
 *
 * The v1 schema mixes simple buttons (icon + tooltip + emitted event)
 * with full sub-types (`external_link`, `boolean_icon`, `form-modal`,
 * `download_button`). We keep the surface permissive with an index
 * signature.
 */
export interface TableAction {
  /** Identifier emitted with the click event. */
  slug?: string
  /** Button label. */
  label?: string
  /** Sub-type when this action renders something other than a plain button. */
  type?:
    | "external_link"
    | "boolean_icon"
    | "form-modal"
    | "download_button"
    | string
  /** Icon name. */
  icon?: string
  /** Tooltip text — or a resolver name for the table view. */
  tooltip?: string | unknown
  /** Themed colour (`"primary"`, `"danger"`, …). */
  color?: string
  /** Extra classes on the button. */
  classList?: string[] | string
  /** Visibility predicate (function-name string or resolver). */
  condition?: string | unknown
  /** Declarative visibility predicates. */
  conditionParams?: Array<{ name: string; logic: string; value?: unknown }>
  /** Route reference for link / API actions. */
  route?: RouteRef | string | unknown
  /** Confirmation modal copy for actions that mutate data. */
  bodyText?: string
  buttonText?: string
  confirmButtonColor?: string
  successMessage?: string
  errorMessage?: string
  /** For `form-modal` actions: nested cards rendered in the modal. */
  cards?: unknown[]
  /** Additional implementation-specific props. */
  [key: string]: unknown
}

/**
 * Field definition for the advanced search builder.
 */
export interface AdvancedSearchField {
  name: string
  label?: string
  /** Field input type (`"text"`, `"date"`, `"select"`, …). */
  type?: string
  /** Whitelist of operators offered for this field. */
  operators?: string[]
  /** For `select` fields: option list. */
  options?: Array<{ text?: string; label?: string; value: unknown }>
}

/**
 * Filter dialog field definition. Mirrors a CardElement schema closely
 * enough that we keep it as a loose record; the renderer narrows.
 */
export type FilterField = Record<string, unknown>

/**
 * The full options object accepted by the DataTable renderer. Every
 * property is optional — the renderer falls back to sensible defaults.
 */
export interface DataTableOptions {
  /** Unique id used for localStorage style/filter persistence. */
  id?: string
  /** Search / data-fetch route. */
  searchRoute?: RouteRef & {
    /** Hide the search input. */
    hide?: boolean
    /** Use project-scoped plugin routing. */
    projectPlugin?: boolean
    /** Skip the on-mount fetch; wait for an external event. */
    waitForFetchEvent?: boolean
  }
  /** Default sort column key. */
  defaultSortBy?: string
  /** Default sort direction. */
  defaultSortDirection?: "asc" | "desc"
  /** Hide the pagination controls. */
  hidePagination?: boolean
  /** Default page size. */
  defaultItemsPerPage?: number
  /** Alias for `defaultItemsPerPage` accepted by some callers. */
  perPage?: number
  /** Max page-button count. */
  paginationMaxSize?: number
  /** Enable pagination. */
  paginated?: boolean
  /** Max table height (enables vertical scroll). */
  tableMaxHeight?: string
  /** Hide the entire toolbar. */
  hideToolbar?: boolean
  /** Banner copy rendered above the table. */
  infoBanner?: string
  /** Empty-state message. */
  emptyText?: string
  /** Key used to extract the data array from the response object. */
  listKey?: string
  /** Default display style. */
  style?: "table_view" | "card_view" | string
  tableDefaultStyle?: "table_view" | "card_view" | string
  tableStyleKey?: string
  tableStyleDisabled?: boolean
  /** Row class — string or a resolver name. */
  itemClass?: string | unknown
  /** Enable row selection. */
  selectable?: boolean
  allowSelectAll?: boolean
  hideSelectAllLabel?: boolean
  includeSelectedInDataModel?: boolean
  maxSelection?: {
    count: number
    showSelectionCount?: boolean
    selectionCountClassList?: string[] | string
  }
  /** Enable drag-to-reorder rows. */
  draggable?: boolean
  /** Allow column reordering via drag. */
  draggableHeaders?: boolean
  /** Identifier delivered to drop handlers when rows are dragged out. */
  dragTargetData?: string
  /** Column visibility selector. */
  visibleColumns?: {
    defaultHeaders?: string[]
  }
  /** Sync the current filter set with the URL query string. */
  applyFiltersFromUrl?: boolean
  /** Filters always applied to the query. */
  defaultFilters?: Array<{
    field: string
    operator?: string
    value?: unknown
  }>
  /** Edit-action shortcut (renders a per-row pencil). */
  edit?: RouteRef & {
    key?: string
    icon?: string
    tooltip?: string
    color?: string
    hideOnCard?: boolean
  }
  /** Delete-action shortcut. */
  delete?: RouteRef & {
    key?: string
    disabled?: boolean
    condition?: string | unknown
    title?: string
    bodyText?: string
    buttonText?: string
    successMessage?: string
    errorMessage?: string
    bodyTextClassList?: string[] | string
    confirmText?: string | unknown
    hideOnCard?: boolean
    tooltipClass?: string[] | string
    onSuccess?: unknown
  }
  /** Bulk-delete action. */
  bulkDelete?: RouteRef & {
    onSuccess?: unknown
  }
  deleteAll?: boolean
  requireInputConfirmation?: boolean
  /** Generic bulk action shortcut. */
  bulkAction?: RouteRef & { label?: string }
  /** Inline update route. */
  update?: RouteRef & {
    key?: string
    projectPlugin?: boolean
    onInlineUpdateSuccess?: unknown
  }
  /** Reorder route. */
  reorder?: RouteRef & {
    key?: string
    transform?: unknown
  }
  /** Expandable row modal. */
  expandable?: {
    cards?: unknown[]
    updateConfig?: {
      update: RouteRef & {
        key?: string
        icon?: string
        classList?: string[] | string
        tooltip?: string
      }
    }
    tooltipClass?: string[] | string
  }
  /** Custom row click handler (resolver name). */
  rowClickAction?: string | unknown
  /** Extra row-level action buttons. */
  additionalActions?: TableAction[]
  /** Export buttons rendered in the toolbar. */
  exports?: ExportConfig[]
  /** Buttons that appear when items are selected. */
  selectionActions?: TableAction[]
  /** Filter dialog config. */
  filter?: {
    hide?: boolean
    cards?: unknown[]
    fields?: FilterField[]
    filterStructure?: Array<{
      field: string
      operator?: string
      condition?: string | unknown
    }>
    filterParameterName?: string
    showFilterCount?: boolean
    clearButton?: {
      hide?: boolean
      position?: string
      text?: string
      classList?: string[] | string
    }
    buttonOpenColor?: string
    buttonClosedColor?: string
    eventBusRemap?: Record<string, unknown>
  }
  /** Inline toolbar filters. */
  inlineFilters?: {
    storeKey?: string
    filters: Array<{
      field: string
      label?: string
      type: "switch" | "select" | "multi-select" | "radio"
      operator?: string
      value?: unknown
      options?: Array<{ text?: string; label?: string; value: unknown }>
      default?: unknown
    }>
  }
  /** Advanced search builder. */
  advancedSearch?: {
    fields: AdvancedSearchField[]
    model?: string
    allowToggleBasicSearch?: boolean
    defaultEnabled?: boolean
    showBuilder?: boolean
    savedSearches?: unknown[]
  }
  /** Lifecycle hooks (resolver names). */
  onMounted?: string | unknown
  onUnmounted?: string | unknown
  /** Card view layout (when style is `card_view`). */
  cardLayout?: Record<string, unknown>
  /** Rows to exclude. */
  excludeRows?: { name: string }
  /** Required permission for the entire table. */
  permissionRequired?: string
  /** Required feature flag. */
  featureRequired?: string
  /** Additional implementation-specific options. */
  [key: string]: unknown
}

/**
 * `datatable` card — tabular data with sortable columns, pagination,
 * filtering, search, exports, and CRUD actions.
 */
export interface DataTableCard extends BaseCard<"datatable"> {
  cardType: "datatable"
  /** Display title rendered above the table. */
  tableTitle?: string
  /** Column definitions. */
  headers: DataTableColumn[]
  /** Sub-array path on the row item when rendering nested tables. */
  listKey?: string
  /** Behaviour and toolbar configuration. */
  options?: DataTableOptions
  /** Static (non-paginated) row source. */
  listData?: unknown[]
  /** Create-modal configuration. */
  createConfig?: CreateConfig
  /** Inline update configuration. */
  updateConfig?: UpdateConfig
  /** Delete configuration. */
  deleteConfig?: DeleteConfig
  /** Per-row action buttons (shortcut for `options.additionalActions`). */
  actions?: TableAction[]
  /** Enable row selection (shortcut for `options.selectable`). */
  selectable?: boolean
  /** Bulk action buttons (shortcut for `options.selectionActions`). */
  bulkActions?: TableAction[]
  /** Empty-state message (shortcut for `options.emptyText`). */
  emptyMessage?: string
}

export const DataTableCardDefaults = {
  cardType: "datatable",
  headers: [],
  showCard: true,
  columns: 12,
  columnsSm: 12,
  columnsMd: 12,
  columnsLg: 12,
  columnsXl: 12,
  selectable: false,
  options: {
    paginated: true,
    defaultItemsPerPage: 10,
    defaultSortDirection: "desc",
  },
} as const satisfies Partial<DataTableCard>

export const DataTableCardMetadata = {
  icon: "table",
  displayLabel: "Data Table",
  elementCategory: "display",
  description:
    "A table that displays data in a grid format with sorting, pagination, filtering, and CRUD actions.",
} as const satisfies ElementMetadata

export const DataTableCardEditConfig = {
  title: {
    type: "input.text",
    label: "Title",
    columns: 12,
    section: "configuration",
  },
  tableTitle: {
    type: "input.text",
    label: "Table Title",
    columns: 12,
    section: "configuration",
  },
  emptyMessage: {
    type: "input.text",
    label: "Empty-state Message",
    columns: 12,
    section: "configuration",
  },
  selectable: {
    type: "boolean.switch",
    defaultValue: false,
    label: "Enable Row Selection",
    columns: 6,
    section: "configuration",
  },
  listKey: {
    type: "input.text",
    label: "List Key (for nested data)",
    columns: 6,
    section: "configuration",
  },
  showCard: {
    type: "boolean.switch",
    defaultValue: true,
    label: "Show Card Chrome",
    columns: 12,
    section: "layout",
  },
} as const satisfies EditConfig
