import type { Meta, StoryObj } from '@storybook/react'
import { expect } from 'storybook/test'
import { SvgAdd1 } from '@chainlink/blocks-icons'
import { colors } from '../../theme/colors/colors'
import { Button } from '../Button'
import { DROPDOWN_SIZE_OPTIONS } from '../dropdownHeights'
import { typographyVariants } from '../Typography'
import {
  Select,
  SelectContent,
  SelectGroup,
  SelectIcon,
  SelectItem,
  SelectLabel,
  SelectSeparator,
  SelectTrigger,
  SelectValue,
} from './Select'

const meta: Meta<typeof Select> = {
  component: Select,
  title: 'Form/Select/Primitive',
  subcomponents: {
    SelectTrigger,
    SelectValue,
    SelectIcon,
    SelectContent,
    SelectItem,
    SelectGroup,
    SelectLabel,
    SelectSeparator,
  },
  argTypes: {
    size: {
      control: 'select',
      options: DROPDOWN_SIZE_OPTIONS,
    },
    clearable: {
      control: 'boolean',
      table: {
        type: { summary: 'boolean' },
        defaultValue: { summary: 'true' },
      },
    },
    onValueChange: { control: false },
  },
  args: {
    size: 'default',
    clearable: true,
  },
}

export default meta

type Story = StoryObj<typeof meta>

export const Default: Story = {
  render: (_args) => (
    <Select clearable size="default">
      <SelectTrigger className="w-56">
        <SelectValue placeholder="Select an option" />
      </SelectTrigger>
      <SelectContent>
        <SelectItem value="option1">Option 1</SelectItem>
        <SelectItem value="option2">Option 2</SelectItem>
        <SelectItem value="option3">Option 3</SelectItem>
      </SelectContent>
    </Select>
  ),
}

export const SmallSize: Story = {
  render: (_args) => (
    <Select clearable size="sm">
      <SelectTrigger className="w-56">
        <SelectValue placeholder="Select an option" />
      </SelectTrigger>
      <SelectContent>
        <SelectItem value="option1">Option 1</SelectItem>
        <SelectItem value="option2">Option 2</SelectItem>
        <SelectItem value="option3">Option 3</SelectItem>
      </SelectContent>
    </Select>
  ),
}

export const XsSize: Story = {
  render: (_args) => (
    <Select clearable size="xs">
      <SelectTrigger className="w-56">
        <SelectValue placeholder="Select an option" />
      </SelectTrigger>
      <SelectContent>
        <SelectItem value="option1">Option 1</SelectItem>
        <SelectItem value="option2">Option 2</SelectItem>
        <SelectItem value="option3">Option 3</SelectItem>
      </SelectContent>
    </Select>
  ),
}

export const OpenState: Story = {
  render: (_args, context) => {
    const openProp = context.viewMode === 'story' ? { defaultOpen: true } : {}

    return (
      <Select clearable size="default" {...openProp}>
        <SelectTrigger className="w-56">
          <SelectValue placeholder="Select an option" />
        </SelectTrigger>
        <SelectContent>
          <SelectItem value="option1">Option 1</SelectItem>
          <SelectItem value="option2">Option 2</SelectItem>
          <SelectItem value="option3">Option 3</SelectItem>
        </SelectContent>
      </Select>
    )
  },
  play: async ({ canvasElement }) => {
    // Find the select trigger
    const trigger = canvasElement.querySelector(
      '[data-slot="select-trigger"]',
    ) as HTMLElement
    await expect(trigger).toBeTruthy()

    // Find the caret SVG
    const caret = trigger.querySelector(
      'svg[data-slot="select-caret"]',
    ) as SVGSVGElement
    await expect(caret).toBeTruthy()

    // Check the caret color - it should use input-muted which maps to text-input-muted-foreground
    // The SVG uses currentColor, so we check the computed color
    // input-muted-foreground maps to gray-400 which is #9fa7b2
    const computedStyle = window.getComputedStyle(caret)
    const caretColor = computedStyle.color

    // Convert hex color to RGB values: #9fa7b2 -> (159, 167, 178)
    const hexColor = colors.gray[400].replace('#', '')
    const expectedR = parseInt(hexColor.substring(0, 2), 16)
    const expectedG = parseInt(hexColor.substring(2, 4), 16)
    const expectedB = parseInt(hexColor.substring(4, 6), 16)

    // Extract RGB values from computed color using a temporary canvas
    // This handles any color format the browser returns (rgb(), color(srgb ...), etc.)
    const canvas = document.createElement('canvas')
    const ctx = canvas.getContext('2d')
    if (!ctx) {
      throw new Error('Could not get canvas context')
    }
    ctx.fillStyle = caretColor
    ctx.fillRect(0, 0, 1, 1)
    const imageData = ctx.getImageData(0, 0, 1, 1)
    const [actualR, actualG, actualB] = imageData.data

    // Verify the caret color matches the expected input-muted-foreground color
    await expect(actualR).toBe(expectedR)
    await expect(actualG).toBe(expectedG)
    await expect(actualB).toBe(expectedB)

    // Check if the caret is rotated when select is open
    // The select is open in story mode (defaultOpen: true), so the caret should be rotated 180deg
    const transform = computedStyle.transform
    await expect(transform).toBeTruthy()
    // When rotated 180deg, the transform should not be 'none'
    // The transform will be a matrix or rotate value when rotated
    await expect(transform).not.toBe('none')

    // Verify the trigger is in open state
    const triggerState = trigger.getAttribute('data-state')
    await expect(triggerState).toBe('open')

    // Verify rotation is applied (transform should contain rotation)
    // A 180deg rotation will have a matrix like matrix(..., -1, ..., 1, ...) or rotate(180deg)
    await expect(
      transform.includes('rotate') || transform.includes('matrix'),
    ).toBe(true)
  },
}

export const EmptyStates: Story = {
  render: (_args, context) => {
    const openProp = context.viewMode === 'story' ? { defaultOpen: true } : {}

    return (
      <div className="flex items-start gap-8">
        <Select clearable size="default" {...openProp}>
          <SelectTrigger className="w-56">
            <SelectValue placeholder="Default" />
          </SelectTrigger>
          <SelectContent>
            <div className="flex items-center justify-center py-6 text-sm text-input-muted-foreground">
              No options available.
            </div>
          </SelectContent>
        </Select>

        <Select clearable size="sm" {...openProp}>
          <SelectTrigger className="w-56">
            <SelectValue placeholder="Small" />
          </SelectTrigger>
          <SelectContent>
            <div className="flex items-center justify-center py-5 text-xs text-input-muted-foreground">
              No options available.
            </div>
          </SelectContent>
        </Select>

        <Select clearable size="xs" {...openProp}>
          <SelectTrigger className="w-56">
            <SelectValue placeholder="Extra small" />
          </SelectTrigger>
          <SelectContent>
            <div className="flex items-center justify-center py-4 text-xs text-input-muted-foreground">
              No options available.
            </div>
          </SelectContent>
        </Select>
      </div>
    )
  },
  parameters: {
    docs: {
      description: {
        story:
          'Use an empty state inside SelectContent when the option list can be empty after filtering or loading.',
      },
    },
  },
}

export const ItemsWithIcons: Story = {
  render: (_args, context) => {
    const openProp = context.viewMode === 'story' ? { defaultOpen: true } : {}

    return (
      <Select clearable size="default" {...openProp}>
        <SelectTrigger className="w-56">
          <SelectValue placeholder="Select an option" />
        </SelectTrigger>
        <SelectContent>
          <SelectItem Icon={<SvgAdd1 />} value="option1">
            Option 1
          </SelectItem>
          <SelectItem Icon={<SvgAdd1 />} value="option2">
            Option 2
          </SelectItem>
          <SelectItem Icon={<SvgAdd1 />} value="option3">
            Option 3
          </SelectItem>
        </SelectContent>
      </Select>
    )
  },
}

export const Clearable: Story = {
  render: (_args, context) => {
    const openProp = context.viewMode === 'story' ? { defaultOpen: true } : {}

    return (
      <Select clearable defaultValue="option2" size="default" {...openProp}>
        <SelectTrigger className="w-56">
          <SelectValue placeholder="Select an option" />
        </SelectTrigger>
        <SelectContent>
          <SelectItem value="option1">Option 1</SelectItem>
          <SelectItem value="option2">Option 2</SelectItem>
          <SelectItem value="option3">Option 3</SelectItem>
        </SelectContent>
      </Select>
    )
  },
}

export const NotClearable: Story = {
  render: (_args, context) => {
    const openProp = context.viewMode === 'story' ? { defaultOpen: true } : {}

    return (
      <Select
        clearable={false}
        defaultValue="option2"
        size="default"
        {...openProp}
      >
        <SelectTrigger className="w-56">
          <SelectValue placeholder="Select an option" />
        </SelectTrigger>
        <SelectContent>
          <SelectItem value="option1">Option 1</SelectItem>
          <SelectItem value="option2">Option 2</SelectItem>
          <SelectItem value="option3">Option 3</SelectItem>
        </SelectContent>
      </Select>
    )
  },
  play: async ({ canvasElement }) => {
    const trigger = canvasElement.querySelector(
      '[data-slot="select-trigger"]',
    ) as HTMLElement
    await expect(trigger.querySelector('[data-slot="select-clear"]')).toBeNull()
  },
}

export const ContentWiderThanTrigger: Story = {
  render: (_args, context) => {
    const openProp = context.viewMode === 'story' ? { defaultOpen: true } : {}

    return (
      <Select clearable size="default" {...openProp}>
        <SelectTrigger className="w-40">
          <SelectValue placeholder="Select a wallet" />
        </SelectTrigger>
        <SelectContent className="min-w-[320px]">
          <SelectItem Icon={<SvgAdd1 />} value="option1">
            A much wider content area than the trigger
          </SelectItem>
          <SelectItem value="option2">
            0x1234567890abcdef1234567890abcdef12345678
          </SelectItem>
          <SelectItem value="option3">Option 3</SelectItem>
        </SelectContent>
      </Select>
    )
  },
  parameters: {
    docs: {
      description: {
        story:
          'Use a wider content panel when option labels or addresses need more room than the trigger.',
      },
    },
  },
  play: async ({ canvasElement }) => {
    const trigger = canvasElement.querySelector(
      '[data-slot="select-trigger"]',
    ) as HTMLElement
    await expect(trigger).toBeTruthy()

    const content = document.querySelector(
      '[data-slot="select-content"]',
    ) as HTMLElement
    await expect(content).toBeTruthy()

    const triggerWidth = trigger.getBoundingClientRect().width
    const contentWidth = content.getBoundingClientRect().width

    await expect(contentWidth).toBeGreaterThan(triggerWidth)
  },
}

export const ButtonCustomTrigger: Story = {
  render: (_args, context) => {
    const openProp = context.viewMode === 'story' ? { defaultOpen: true } : {}

    return (
      <Select clearable size="default" {...openProp}>
        <SelectTrigger asChild>
          <Button width="hug" className="w-56">
            <SelectValue placeholder="Select an option" />
            <SelectIcon />
          </Button>
        </SelectTrigger>
        <SelectContent>
          <SelectItem Icon={<SvgAdd1 />} value="option1">
            Option 1
          </SelectItem>
          <SelectItem Icon={<SvgAdd1 />} value="option2">
            Option 2
          </SelectItem>
          <SelectItem Icon={<SvgAdd1 />} value="option3">
            Option 3
          </SelectItem>
        </SelectContent>
      </Select>
    )
  },
  parameters: {
    docs: {
      description: {
        story:
          'Use asChild on SelectTrigger when the trigger should look like another Blocks component.',
      },
    },
  },
}

export const TextCustomTrigger: Story = {
  render: (_args, context) => {
    const openProp = context.viewMode === 'story' ? { defaultOpen: true } : {}

    return (
      <Select clearable size="default" {...openProp}>
        <SelectTrigger asChild>
          <button
            className={typographyVariants({
              variant: 'h5',
              className:
                'flex w-56 items-center justify-between rounded focus-visible:border-solid focus-visible:border-ring focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',
            })}
          >
            <SelectValue placeholder="Select an option" />
            <SelectIcon color="foreground" />
          </button>
        </SelectTrigger>
        <SelectContent>
          <SelectItem value="option1">Option 1</SelectItem>
          <SelectItem value="option2">Option 2</SelectItem>
          <SelectItem value="option3">Option 3</SelectItem>
        </SelectContent>
      </Select>
    )
  },
  parameters: {
    docs: {
      description: {
        story:
          'Use a custom trigger when the selected value must appear inside non-standard text or heading UI.',
      },
    },
  },
}
