import { render } from '@testing-library/react';
import React from 'react';
import { describe, expect, it } from 'vitest';
import { Column } from '../..';
import { Data } from '../../../..';
import { ListRowCell } from './ListRowCell';

interface TestData extends Data {
  id: string;
  name: string;
  age: number;
  date: Date;
}

const mockData: TestData = {
  id: '123',
  name: 'Test User',
  age: 30,
  date: new Date('2023-01-15T10:30:00'),
};

const dateFormatter = new Intl.DateTimeFormat('en-US', {
  year: 'numeric',
  month: 'numeric',
  day: 'numeric',
  hour: 'numeric',
  minute: 'numeric',
  second: 'numeric',
});

const numberFormatter = new Intl.NumberFormat('en-US');

describe('ListRowCell', () => {
  it('renders the component without crashing', () => {
    const column: Column<TestData> = {
      propertyName: 'name',
      label: 'Name',
    };

    const { container } = render(
      <ListRowCell
        column={column}
        data={mockData}
        dateFormatter={dateFormatter}
        numberFormatter={numberFormatter}
      />,
    );

    expect(container).toBeTruthy();
  });

  it('renders a string value correctly', () => {
    const column: Column<TestData> = {
      propertyName: 'name',
      label: 'Name',
    };

    const { container } = render(
      <ListRowCell
        column={column}
        data={mockData}
        dateFormatter={dateFormatter}
        numberFormatter={numberFormatter}
      />,
    );

    expect(container.textContent).toBe('Test User');
  });

  it('renders a number value with number formatter', () => {
    const column: Column<TestData> = {
      propertyName: 'age',
      label: 'Age',
    };

    const { container } = render(
      <ListRowCell
        column={column}
        data={mockData}
        dateFormatter={dateFormatter}
        numberFormatter={numberFormatter}
      />,
    );

    expect(container.textContent).toBe(numberFormatter.format(30));
  });

  it('renders a date value with date formatter', () => {
    const column: Column<TestData> = {
      propertyName: 'date',
      label: 'Date',
    };

    const { container } = render(
      <ListRowCell
        column={column}
        data={mockData}
        dateFormatter={dateFormatter}
        numberFormatter={numberFormatter}
      />,
    );

    expect(container.textContent).toBe(dateFormatter.format(mockData.date));
  });

  it('uses custom renderer when provided', () => {
    const column: Column<TestData> = {
      propertyName: 'name',
      label: 'Name',
      render: (value) => `Custom: ${value}`,
    };

    const { container } = render(
      <ListRowCell
        column={column}
        data={mockData}
        dateFormatter={dateFormatter}
        numberFormatter={numberFormatter}
      />,
    );

    expect(container.textContent).toBe('Custom: Test User');
  });

  it('handles null values', () => {
    const nullData = { ...mockData, name: null as unknown as string };
    const column: Column<TestData> = {
      propertyName: 'name',
      label: 'Name',
    };

    const { container } = render(
      <ListRowCell
        column={column}
        data={nullData}
        dateFormatter={dateFormatter}
        numberFormatter={numberFormatter}
      />,
    );

    expect(container.textContent).toBe('');
  });

  it('handles undefined values', () => {
    const undefinedData = { ...mockData, name: undefined as unknown as string };
    const column: Column<TestData> = {
      propertyName: 'name',
      label: 'Name',
    };

    const { container } = render(
      <ListRowCell
        column={column}
        data={undefinedData}
        dateFormatter={dateFormatter}
        numberFormatter={numberFormatter}
      />,
    );

    expect(container.textContent).toBe('');
  });

  it('renders tooltip with column text by default', () => {
    const column: Column<TestData> = {
      propertyName: 'name',
      label: 'Name',
    };

    const { container } = render(
      <ListRowCell
        column={column}
        data={mockData}
        dateFormatter={dateFormatter}
        numberFormatter={numberFormatter}
      />,
    );

    const cell = container.querySelector('.cell')!;
    expect(cell).toHaveAttribute('title', 'Test User');
  });

  it('does not render tooltip when column.tooltip is false', () => {
    const column: Column<TestData> = {
      propertyName: 'name',
      label: 'Name',
      tooltip: false,
    };

    const { container } = render(
      <ListRowCell
        column={column}
        data={mockData}
        dateFormatter={dateFormatter}
        numberFormatter={numberFormatter}
      />,
    );

    const cell = container.querySelector('.cell')!;
    expect(cell).not.toHaveAttribute('title');
  });

  describe('text alignment', () => {
    it('applies default horizontal text alignment (left)', () => {
      const column: Column<TestData> = {
        propertyName: 'name',
        label: 'Name',
      };

      const { container } = render(
        <ListRowCell
          column={column}
          data={mockData}
          dateFormatter={dateFormatter}
          numberFormatter={numberFormatter}
        />,
      );

      const cell = container.querySelector('.cell')!;
      expect(cell).toHaveStyle({ textAlign: 'left' });
    });

    it('applies custom horizontal text alignment', () => {
      const column: Column<TestData> = {
        propertyName: 'name',
        label: 'Name',
      };

      const { container } = render(
        <ListRowCell
          column={column}
          data={mockData}
          horizontalTextAlign="right"
          dateFormatter={dateFormatter}
          numberFormatter={numberFormatter}
        />,
      );

      const cell = container.querySelector('.cell')!;
      expect(cell).toHaveStyle({ textAlign: 'right' });
    });

    it('applies default vertical text alignment (center)', () => {
      const column: Column<TestData> = {
        propertyName: 'name',
        label: 'Name',
      };

      const { container } = render(
        <ListRowCell
          column={column}
          data={mockData}
          dateFormatter={dateFormatter}
          numberFormatter={numberFormatter}
        />,
      );

      const cell = container.querySelector('.cell')!;
      expect(cell).toHaveStyle({ alignSelf: 'center' });
    });

    it('applies custom vertical text alignment', () => {
      const column: Column<TestData> = {
        propertyName: 'name',
        label: 'Name',
      };

      const { container } = render(
        <ListRowCell
          column={column}
          data={mockData}
          verticalTextAlign="start"
          dateFormatter={dateFormatter}
          numberFormatter={numberFormatter}
        />,
      );

      const cell = container.querySelector('.cell')!;
      expect(cell).toHaveStyle({ alignSelf: 'start' });
    });

    it('applies horizontal column alignment from column config', () => {
      const column: Column<TestData> = {
        propertyName: 'name',
        label: 'Name',
        horizontalColumnAlign: 'right',
      };

      const { container } = render(
        <ListRowCell
          column={column}
          data={mockData}
          dateFormatter={dateFormatter}
          numberFormatter={numberFormatter}
        />,
      );

      const cell = container.querySelector('.cell')!;
      expect(cell).toHaveStyle({ justifySelf: 'right' });
    });
  });

  describe('text wrapping', () => {
    it('applies nowrap class by default (textWrap = false)', () => {
      const column: Column<TestData> = {
        propertyName: 'name',
        label: 'Name',
      };

      const { container } = render(
        <ListRowCell
          column={column}
          data={mockData}
          dateFormatter={dateFormatter}
          numberFormatter={numberFormatter}
        />,
      );

      const cell = container.querySelector('.cell')!;
      expect(cell).toHaveClass('nowrap');
    });

    it('does not apply nowrap class when textWrap is true', () => {
      const column: Column<TestData> = {
        propertyName: 'name',
        label: 'Name',
      };

      const { container } = render(
        <ListRowCell
          column={column}
          data={mockData}
          textWrap={true}
          dateFormatter={dateFormatter}
          numberFormatter={numberFormatter}
        />,
      );

      const cell = container.querySelector('.cell')!;
      expect(cell).not.toHaveClass('nowrap');
    });
  });

  describe('data-test-id', () => {
    it('sets data-test-id based on propertyName when render returns a string', () => {
      const column: Column<TestData> = {
        propertyName: 'name',
        label: 'Name',
        render: (value) => `Custom: ${value}`,
      };

      const { container } = render(
        <ListRowCell
          column={column}
          data={mockData}
          dateFormatter={dateFormatter}
          numberFormatter={numberFormatter}
        />,
      );

      const cell = container.querySelector('.cell')!;
      expect(cell).not.toHaveAttribute('data-test-id');
    });

    it('sets data-test-id on inner span for standard values', () => {
      const column: Column<TestData> = {
        propertyName: 'name',
        label: 'Name',
      };

      const { container, getByTestId } = render(
        <ListRowCell
          column={column}
          data={mockData}
          dateFormatter={dateFormatter}
          numberFormatter={numberFormatter}
        />,
      );

      // For standard values, data-test-id is on the inner span, not the cell div
      const cell = container.querySelector('.cell')!;
      expect(cell).not.toHaveAttribute('data-test-id');

      // Check that the span inside has the data-test-id
      expect(getByTestId('list-entry-property:name')).toBeInTheDocument();
    });

    it('sets data-test-id on cell when custom renderer returns JSX', () => {
      const column: Column<TestData> = {
        propertyName: 'name',
        label: 'Name',
        render: (value) => <div className="custom-render">{value}</div>,
      };

      const { container } = render(
        <ListRowCell
          column={column}
          data={mockData}
          dateFormatter={dateFormatter}
          numberFormatter={numberFormatter}
        />,
      );

      // For custom JSX renderers, data-test-id is on the cell div
      const cell = container.querySelector('.cell')!;
      expect(cell).toHaveAttribute('data-test-id', 'list-entry-property:name');
    });
  });

  describe('unbound columns (no propertyName)', () => {
    it('renders custom renderer for unbound column', () => {
      const column: Column<TestData> = {
        key: 'actions',
        label: 'Actions',
        render: (_value, data) => <button>Edit {data.name}</button>,
      };

      const { getByRole } = render(
        <ListRowCell
          column={column}
          data={mockData}
          dateFormatter={dateFormatter}
          numberFormatter={numberFormatter}
        />,
      );

      expect(getByRole('button').textContent).toBe('Edit Test User');
    });

    it('handles unbound column with string render result', () => {
      const column: Column<TestData> = {
        key: 'status',
        label: 'Status',
        render: () => 'Active',
      };

      const { container } = render(
        <ListRowCell
          column={column}
          data={mockData}
          dateFormatter={dateFormatter}
          numberFormatter={numberFormatter}
        />,
      );

      expect(container.textContent).toBe('Active');
    });
  });
});
