// cell-types.js - Built-in cell type registry for table-ui

const cellTypes = {};

function registerCellType(name, config) {
  cellTypes[name] = config;
}

// text-overflow:ellipsis on a flex container doesn't reach text nodes —
// they become anonymous flex items that the container can't truncate.
// Wrapping in a <span> gives CSS a real element to target.
function _t(cell, text) {
  let s = cell.firstElementChild;
  if (!s || s.tagName !== 'SPAN') {
    cell.replaceChildren();
    s = cell.appendChild(document.createElement('span'));
  }
  s.textContent = text;
  cell.title = text;
}

// Sort functions
export const sortFns = {
  basic: (a, b) => (a < b ? -1 : a > b ? 1 : 0),
  alphanumeric: (a, b) =>
    String(a ?? '').localeCompare(String(b ?? ''), undefined, {
      numeric: true,
      sensitivity: 'base',
    }),
  numeric: (a, b) => (Number(a) || 0) - (Number(b) || 0),
  datetime: (a, b) =>
    new Date(a || 0).getTime() - new Date(b || 0).getTime(),
};

// 1. text (default)
registerCellType('text', {
  render(value, row, cell) {
    _t(cell, String(value ?? ''));
  },
  format(value) {
    return String(value ?? '');
  },
  align: 'left',
  sortFn: 'alphanumeric',
});

// 2. number
registerCellType('number', {
  render(value, row, cell) {
    _t(cell, value != null ? new Intl.NumberFormat().format(value) : '');
  },
  format(value) {
    return String(value ?? '');
  },
  align: 'right',
  sortFn: 'numeric',
});

// 3. currency
registerCellType('currency', {
  render(value, row, cell, meta) {
    _t(cell,
      value != null
        ? new Intl.NumberFormat('en-US', {
            style: 'currency',
            currency: meta?.currency || 'USD',
          }).format(value)
        : '');
  },
  format(value, row, meta) {
    return value != null
      ? new Intl.NumberFormat('en-US', {
          style: 'currency',
          currency: meta?.currency || 'USD',
        }).format(value)
      : '';
  },
  align: 'right',
  sortFn: 'numeric',
});

// 4. percent
registerCellType('percent', {
  render(value, row, cell) {
    _t(cell, value != null ? `${value}%` : '');
  },
  format(value) {
    return value != null ? `${value}%` : '';
  },
  align: 'right',
  sortFn: 'numeric',
});

// 5. date
const dateFmtOpts = { year: 'numeric', month: 'short', day: 'numeric' };

registerCellType('date', {
  render(value, row, cell) {
    _t(cell, value
      ? new Intl.DateTimeFormat('en-US', dateFmtOpts).format(new Date(value))
      : '');
  },
  format(value) {
    return value
      ? new Intl.DateTimeFormat('en-US', dateFmtOpts).format(new Date(value))
      : '';
  },
  align: 'left',
  sortFn: 'datetime',
});

// 6. datetime
const datetimeFmtOpts = {
  year: 'numeric',
  month: 'short',
  day: 'numeric',
  hour: 'numeric',
  minute: '2-digit',
};

registerCellType('datetime', {
  render(value, row, cell) {
    _t(cell, value
      ? new Intl.DateTimeFormat('en-US', datetimeFmtOpts).format(
          new Date(value)
        )
      : '');
  },
  format(value) {
    return value
      ? new Intl.DateTimeFormat('en-US', datetimeFmtOpts).format(
          new Date(value)
        )
      : '';
  },
  align: 'left',
  sortFn: 'datetime',
});

// 7. boolean
registerCellType('boolean', {
  render(value, row, cell) {
    let el = cell.querySelector('check-ui');
    if (!el) {
      cell.textContent = '';
      el = document.createElement('check-ui');
      el.setAttribute('disabled', '');
      cell.appendChild(el);
    }
    if (value) {
      el.setAttribute('checked', '');
    } else {
      el.removeAttribute('checked');
    }
  },
  format(value) {
    return value ? 'Yes' : 'No';
  },
  align: 'center',
  sortFn: 'basic',
});

// 8. badge
registerCellType('badge', {
  render(value, row, cell, meta) {
    let el = cell.querySelector('badge-ui');
    if (!el) {
      cell.textContent = '';
      el = document.createElement('badge-ui');
      cell.appendChild(el);
    }
    el.setAttribute('text', String(value ?? ''));
    const variants = meta?.variants || {};
    el.setAttribute('variant', variants[value] || 'neutral');
  },
  format(value) {
    return String(value ?? '');
  },
  align: 'left',
  sortFn: 'alphanumeric',
});

// 9. avatar
registerCellType('avatar', {
  render(value, row, cell) {
    let wrapper = cell.querySelector('row-ui');
    if (!wrapper) {
      cell.textContent = '';
      wrapper = document.createElement('row-ui');
      wrapper.setAttribute('gap', '2');
      wrapper.setAttribute('align', 'center');
      const av = document.createElement('avatar-ui');
      av.setAttribute('size', 'sm');
      const span = document.createElement('span');
      wrapper.appendChild(av);
      wrapper.appendChild(span);
      cell.appendChild(wrapper);
    }
    const av = wrapper.querySelector('avatar-ui');
    const span = wrapper.querySelector('span');
    av.setAttribute('text', String(value ?? ''));
    span.textContent = String(value ?? '');
    cell.title = String(value ?? '');
  },
  format(value) {
    return String(value ?? '');
  },
  align: 'left',
  sortFn: 'alphanumeric',
});

// 10. link
registerCellType('link', {
  render(value, row, cell, meta) {
    let el = cell.querySelector('a');
    if (!el) {
      cell.textContent = '';
      el = document.createElement('a');
      el.style.color = 'var(--table-accent, var(--a-primary))';
      el.style.textDecoration = 'none';
      cell.appendChild(el);
    }
    const str = String(value ?? '');
    // Auto-detect email: add mailto: href but show clean text
    const isEmail = str.includes('@') && !str.startsWith('http');
    el.href = isEmail ? `mailto:${str}` : str;
    el.textContent = meta?.label ?? str;
  },
  format(value) {
    return String(value ?? '');
  },
  align: 'left',
  sortFn: 'alphanumeric',
});

// 11. progress
registerCellType('progress', {
  render(value, row, cell) {
    let wrapper = cell.querySelector('row-ui');
    if (!wrapper) {
      cell.textContent = '';
      wrapper = document.createElement('row-ui');
      wrapper.setAttribute('gap', '2');
      wrapper.setAttribute('align', 'center');
      const prog = document.createElement('progress-ui');
      prog.setAttribute('size', 'sm');
      prog.style.flex = '1';
      const span = document.createElement('span');
      wrapper.appendChild(prog);
      wrapper.appendChild(span);
      cell.appendChild(wrapper);
    }
    const prog = wrapper.querySelector('progress-ui');
    const span = wrapper.querySelector('span');
    prog.setAttribute('value', value != null ? String(value) : '0');
    span.textContent = value != null ? `${value}%` : '';
  },
  format(value) {
    return value != null ? `${value}%` : '';
  },
  align: 'left',
  sortFn: 'numeric',
});

// 12. actions
registerCellType('actions', {
  render(value, row, cell, meta) {
    const actions = meta?.actions || [];
    let wrapper = cell.querySelector('row-ui');

    // Rebuild if action count changed
    if (wrapper && wrapper.children.length !== actions.length) {
      wrapper.remove();
      wrapper = null;
    }

    if (!wrapper) {
      cell.textContent = '';
      wrapper = document.createElement('row-ui');
      wrapper.setAttribute('gap', '1');

      for (const action of actions) {
        const btn = document.createElement('button-ui');
        btn.setAttribute('icon', action.icon || '');
        btn.setAttribute('variant', 'ghost');
        btn.setAttribute('size', 'sm');
        btn.setAttribute('aria-label', action.label || '');
        btn.addEventListener('click', () => {
          btn.dispatchEvent(
            new CustomEvent(action.event, {
              bubbles: true,
              detail: { row },
            })
          );
        });
        wrapper.appendChild(btn);
      }

      cell.appendChild(wrapper);
    }
  },
  format() {
    return '';
  },
  align: 'center',
  sortFn: null,
});

export { cellTypes, registerCellType };
