/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

/**
 * Tailwind catalyst component
 */
'use client';

import { clsx } from 'clsx';
import type React from 'react';
import { createContext, useContext, useState } from 'react';
import { Link } from './link';

const TableContext = createContext<{
  bleed: boolean;
  dense: number; // 0 is not dense, 1 is dense, 2 is very dense
  grid: boolean;
  striped: boolean;
}>({
  bleed: false,
  dense: 0,
  grid: false,
  striped: false
});

export function Table({
  bleed = false,
  dense = 0,
  grid = false,
  striped = false,
  className,
  children,
  ...props
}: {
  bleed?: boolean;
  dense?: number;
  grid?: boolean;
  striped?: boolean;
} & React.ComponentPropsWithoutRef<'div'>) {
  return (
    <TableContext.Provider
      value={{ bleed, dense, grid, striped } as React.ContextType<typeof TableContext>}
    >
      <div className="flow-root">
        <div
          {...props}
          // TODO - this is currently hidden cause of weird stuff, but we really shouldn't be, we should figure out why it's overflowing
          className={clsx(className, '-mx-[--gutter] overflow-x-hidden whitespace-nowrap')}
        >
          <div
            className={clsx('inline-block min-w-full align-middle', !bleed && 'sm:px-[--gutter]')}
          >
            <table className="min-w-full text-left text-sm/6">{children}</table>
          </div>
        </div>
      </div>
    </TableContext.Provider>
  );
}

export function TableHead({ className, ...props }: React.ComponentPropsWithoutRef<'thead'>) {
  return <thead className={clsx(className, 'text-zinc-500 dark:text-zinc-400')} {...props} />;
}

export function TableBody(props: React.ComponentPropsWithoutRef<'tbody'>) {
  return <tbody {...props} />;
}

const TableRowContext = createContext<{ href?: string; target?: string; title?: string }>({
  href: undefined,
  target: undefined,
  title: undefined
});

export function TableRow({
  href,
  target,
  title,
  className,
  children,
  ...props
}: { href?: string; target?: string; title?: string } & React.ComponentPropsWithoutRef<'tr'>) {
  const { striped } = useContext(TableContext);

  return (
    <TableRowContext.Provider
      value={{ href, target, title } as React.ContextType<typeof TableRowContext>}
    >
      <tr
        {...props}
        className={clsx(
          className,
          href &&
            'has-[[data-row-link][data-focus]]:outline has-[[data-row-link][data-focus]]:outline-2 has-[[data-row-link][data-focus]]:-outline-offset-2 has-[[data-row-link][data-focus]]:outline-blue-500 dark:focus-within:bg-white/[2.5%]',
          striped && 'even:bg-zinc-950/[2.5%] dark:even:bg-white/[2.5%]',
          href && striped && 'hover:bg-zinc-950/5 dark:hover:bg-white/5',
          href && !striped && 'hover:bg-zinc-950/[2.5%] dark:hover:bg-white/[2.5%]'
        )}
      >
        {children}
      </tr>
    </TableRowContext.Provider>
  );
}

export function TableHeader({ className, ...props }: React.ComponentPropsWithoutRef<'th'>) {
  const { bleed, grid } = useContext(TableContext);

  return (
    <th
      {...props}
      className={clsx(
        className,
        'border-b border-b-zinc-950/10 px-4 py-2 font-medium first:pl-[var(--gutter,theme(spacing.2))] last:pr-[var(--gutter,theme(spacing.2))] dark:border-b-white/10',
        grid && 'border-l border-l-zinc-950/5 first:border-l-0 dark:border-l-white/5',
        !bleed && 'sm:first:pl-2 sm:last:pr-2'
      )}
    />
  );
}

export function TableCell({ className, children, ...props }: React.ComponentPropsWithoutRef<'td'>) {
  const { bleed, dense, grid, striped } = useContext(TableContext);
  const { href, target, title } = useContext(TableRowContext);
  const [cellRef, setCellRef] = useState<HTMLElement | null>(null);

  return (
    <td
      ref={href ? setCellRef : undefined}
      {...props}
      className={clsx(
        className,
        'relative px-4 first:pl-[var(--gutter,theme(spacing.2))] last:pr-[var(--gutter,theme(spacing.2))]',
        !striped && 'border-b border-zinc-950/5 dark:border-white/5',
        grid && 'border-l border-l-zinc-950/5 first:border-l-0 dark:border-l-white/5',
        dense === 0 ? 'py-4' : dense === 1 ? 'py-2.5' : dense === 2 ? 'py-1' : 'py-0.2', //'py-2.5' : 'py-4',
        !bleed && 'sm:first:pl-2 sm:last:pr-2'
      )}
    >
      {href && (
        <Link
          data-row-link
          href={href}
          target={target}
          aria-label={title}
          tabIndex={cellRef?.previousElementSibling === null ? 0 : -1}
          className="absolute inset-0 focus:outline-none"
        />
      )}
      {children}
    </td>
  );
}
