import * as React from "react"
import * as LucideIcons from "lucide-react"

import { Input } from "@/components/ui/input"
import { KeyValueEditor } from "@/components/ui/key-value-editor"
import { Label } from "@/components/ui/label"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
import { Slider } from "@/components/ui/slider"
import { Switch } from "@/components/ui/switch"
import { Textarea } from "@/components/ui/textarea"
import {
  Tooltip,
  TooltipContent,
  TooltipProvider,
  TooltipTrigger,
} from "@/components/ui/tooltip"
import { cn } from "@/lib/utils"
import type { FieldSchema } from "@/types/config-schema"

export interface DynamicFieldProps {
  schema: FieldSchema
  value: unknown
  onChange: (value: unknown) => void
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
  fieldPath?: string // 用于 Hook 系统（未来使用）
}

/**
 * DynamicField - 根据字段类型和 x-widget 渲染对应的 shadcn/ui 组件
 * 
 * 渲染逻辑：
 * 1. x-widget 优先：如果 schema 有 x-widget，使用对应组件
 * 2. type 回退：如果没有 x-widget，根据 type 选择默认组件
 */
export const DynamicField: React.FC<DynamicFieldProps> = ({
  schema,
  value,
  onChange,
}) => {
  const isNumericField = schema.type === 'integer' || schema.type === 'number'

  const parseNumericValue = (rawValue: unknown, fallbackValue: unknown = 0) => {
    if (typeof rawValue === 'number' && Number.isFinite(rawValue)) {
      return rawValue
    }

    if (typeof rawValue === 'string') {
      const parsedValue = parseFloat(rawValue)
      if (Number.isFinite(parsedValue)) {
        return schema.type === 'integer' ? Math.trunc(parsedValue) : parsedValue
      }
    }

    if (fallbackValue !== rawValue) {
      return parseNumericValue(fallbackValue, 0)
    }

    return 0
  }

  const renderPrimitiveArrayEditor = () => {
    const itemType = schema.items?.type ?? 'string'
    const arrayValue = Array.isArray(value)
      ? value
      : Array.isArray(schema.default)
        ? schema.default
        : []

    const textareaValue = arrayValue.map((item) => String(item ?? '')).join('\n')

    return (
      <Textarea
        value={textareaValue}
        onChange={(e) => {
          const nextItems = e.target.value
            .split('\n')
            .map((line) => line.trim())
            .filter((line) => line.length > 0)
            .map((line) => {
              if (itemType === 'integer') {
                return parseInt(line, 10) || 0
              }
              if (itemType === 'number') {
                return parseFloat(line) || 0
              }
              if (itemType === 'boolean') {
                return line === 'true'
              }
              return line
            })
          onChange(nextItems)
        }}
        rows={Math.max(4, arrayValue.length || 4)}
      />
    )
  }

  const renderObjectEditor = () => {
    const objectValue =
      value && typeof value === 'object' && !Array.isArray(value)
        ? (value as Record<string, unknown>)
        : {}

    return (
      <KeyValueEditor
        value={objectValue}
        onChange={onChange}
      />
    )
  }

  /**
   * 渲染字段图标
   */
  const renderIcon = () => {
    if (!schema['x-icon']) return null
    
    const IconComponent = LucideIcons[schema['x-icon'] as keyof typeof LucideIcons] as React.ComponentType<{ className?: string }> | undefined
    if (!IconComponent) return null
    
    return <IconComponent className="h-4 w-4" />
  }

  const optionDescriptions = schema['x-option-descriptions'] ?? {}
  const hasOptionDescriptions = Object.keys(optionDescriptions).length > 0
  const inlineDescription = hasOptionDescriptions ? '' : schema.description

  const renderFieldHeader = () => (
    <div className="flex flex-wrap items-center gap-x-2 gap-y-1">
      <Label
        className={cn(
          "inline-flex min-h-7 items-center gap-1.5 rounded-md border px-2 py-1 text-sm font-medium shadow-sm",
          schema.advanced
            ? "border-amber-300 bg-amber-50 text-amber-950 dark:border-amber-500/60 dark:bg-amber-500/15 dark:text-amber-100"
            : "bg-muted/60 text-foreground",
        )}
      >
        {renderIcon()}
        <span className="break-all">{schema.label}</span>
        {schema.required && <span className="text-destructive">*</span>}
      </Label>
      {inlineDescription && (
        <span className="text-[13px] leading-6 text-muted-foreground whitespace-pre-line">
          {inlineDescription}
        </span>
      )}
    </div>
  )

  /**
   * 根据 x-widget 或 type 选择并渲染对应的输入组件
   */
  const renderInputComponent = () => {
    const widget = schema['x-widget']
    const type = schema.type
    const resolvedWidget =
      isNumericField && (widget === 'input' || widget === 'number' || !widget)
        ? 'number'
        : widget

    // x-widget 优先
    if (resolvedWidget) {
      switch (resolvedWidget) {
        case 'slider':
          return renderSlider()
        case 'input':
          return renderTextInput()
        case 'number':
          return renderNumberInput()
        case 'password':
          return renderTextInput('password')
        case 'switch':
          return renderSwitch()
        case 'textarea':
          return renderTextarea()
        case 'select':
          return renderSelect()
        case 'custom':
          if (type === 'array' && schema.items && schema.items.type !== 'object') {
            return renderPrimitiveArrayEditor()
          }
          if (type === 'object') {
            return renderObjectEditor()
          }
          return (
            <div className="rounded-md border border-dashed border-muted-foreground/25 bg-muted/10 p-4 text-center text-sm text-muted-foreground">
              Custom field requires Hook
            </div>
          )
        default:
          // 未知的 x-widget，回退到 type
          break
      }
    }

    // type 回退
    switch (type) {
      case 'boolean':
        return renderSwitch()
      case 'number':
      case 'integer':
        return renderNumberInput()
      case 'string':
        return renderTextInput()
      case 'select':
        return renderSelect()
      case 'array':
        if (!schema.items || schema.items.type === 'object') {
          return (
            <div className="rounded-md border border-dashed border-muted-foreground/25 bg-muted/10 p-4 text-center text-sm text-muted-foreground">
              Complex array requires Hook
            </div>
          )
        }
        return renderPrimitiveArrayEditor()
      case 'object':
        return renderObjectEditor()
      case 'textarea':
        return renderTextarea()
      default:
        return (
          <div className="rounded-md border border-dashed border-muted-foreground/25 bg-muted/10 p-4 text-center text-sm text-muted-foreground">
            Unknown field type: {type}
          </div>
        )
    }
  }

  /**
   * 渲染 Switch 组件（用于 boolean 类型）
   * 使用水平布局：标签+描述在左，开关在右
   */
  const renderSwitch = () => {
    const checked = Boolean(value)
    return (
      <div className="flex items-center justify-between gap-4 py-2">
        <div className="pr-4">
          {renderFieldHeader()}
        </div>
        <Switch
          checked={checked}
          onCheckedChange={(checked) => onChange(checked)}
        />
      </div>
    )
  }

  /**
   * 渲染 Slider 组件（用于 number 类型 + x-widget: slider）
   */
  const renderSlider = () => {
    const numValue = parseNumericValue(value, schema.default)
    const min = schema.minValue ?? 0
    const max = schema.maxValue ?? 100
    const step = schema.step ?? 1

    return (
      <div className="space-y-2">
        <Slider
          value={[numValue]}
          onValueChange={(values) => onChange(values[0])}
          min={min}
          max={max}
          step={step}
        />
        <div className="flex justify-between text-xs text-muted-foreground">
          <span>{min}</span>
          <span className="font-medium text-foreground">{numValue}</span>
          <span>{max}</span>
        </div>
      </div>
    )
  }

  /**
   * 渲染 Input[type="number"] 组件（用于 number/integer 类型）
   */
  const renderNumberInput = () => {
    const numValue = parseNumericValue(value, schema.default)
    const min = schema.minValue
    const max = schema.maxValue
    const step = schema.step ?? (schema.type === 'integer' ? 1 : 0.1)

    return (
      <Input
        type="number"
        value={numValue}
        onChange={(e) => {
          const nextValue = schema.type === 'integer'
            ? parseInt(e.target.value, 10)
            : parseFloat(e.target.value)
          onChange(Number.isFinite(nextValue) ? nextValue : 0)
        }}
        min={min}
        max={max}
        step={step}
      />
    )
  }

  /**
   * 渲染 Input[type="text"] 组件（用于 string 类型）
   */
  const renderTextInput = (type: 'password' | 'text' = 'text') => {
    const strValue =
      typeof value === 'string'
        ? value
        : value === null || value === undefined
          ? String(schema.default ?? '')
          : String(value)
    return (
      <Input
        type={type}
        value={strValue}
        onChange={(e) => onChange(e.target.value)}
      />
    )
  }

  /**
   * 渲染 Textarea 组件（用于 textarea 类型或 x-widget: textarea）
   */
  const renderTextarea = () => {
    const strValue = typeof value === 'string' ? value : (schema.default as string ?? '')
    const minHeight = typeof schema['x-textarea-min-height'] === 'number'
      ? schema['x-textarea-min-height']
      : undefined
    const rows = typeof schema['x-textarea-rows'] === 'number'
      ? schema['x-textarea-rows']
      : 4

    return (
      <Textarea
        value={strValue}
        onChange={(e) => onChange(e.target.value)}
        rows={rows}
        minHeight={minHeight}
      />
    )
  }

  /**
   * 渲染 Select 组件（用于 select 类型或 x-widget: select）
   */
  const renderSelect = () => {
    const strValue = typeof value === 'string' ? value : (schema.default as string ?? '')
    const options = schema.options ?? []

    if (options.length === 0) {
      return (
        <div className="rounded-md border border-dashed border-muted-foreground/25 bg-muted/10 p-4 text-center text-sm text-muted-foreground">
          No options available for select
        </div>
      )
    }

    return (
      <Select value={strValue} onValueChange={(val) => onChange(val)}>
        <SelectTrigger>
          <SelectValue placeholder={`Select ${schema.label}`} />
        </SelectTrigger>
        <SelectContent>
          {hasOptionDescriptions ? (
            <TooltipProvider delayDuration={150}>
              {options.map((option) => {
                const description = optionDescriptions[option]
                return description ? (
                  <Tooltip key={option}>
                    <TooltipTrigger asChild>
                      <SelectItem value={option} title={description}>
                        {option}
                      </SelectItem>
                    </TooltipTrigger>
                    <TooltipContent
                      side="right"
                      align="center"
                      className="max-w-72 bg-background text-foreground border shadow-lg"
                    >
                      {description}
                    </TooltipContent>
                  </Tooltip>
                ) : (
                  <SelectItem key={option} value={option}>
                    {option}
                  </SelectItem>
                )
              })}
            </TooltipProvider>
          ) : (
            options.map((option) => (
              <SelectItem key={option} value={option}>
                {option}
              </SelectItem>
            ))
          )}
        </SelectContent>
      </Select>
    )
  }

  // 判断当前字段是否为 Switch/Boolean 类型（独立处理布局）
  const isBoolean =
    schema['x-widget'] === 'switch' ||
    (!schema['x-widget'] && schema.type === 'boolean')
  const supportsInlineRight =
    schema['x-layout'] === 'inline-right' &&
    ['input', 'number', 'password', 'select', undefined].includes(schema['x-widget']) &&
    ['string', 'number', 'integer', 'select'].includes(schema.type)

  // Switch/Boolean 字段自带完整布局，直接返回
  if (isBoolean) {
    return renderInputComponent()
  }

  if (supportsInlineRight) {
    return (
      <div
        className="flex flex-col gap-2 py-2 sm:flex-row sm:items-center sm:justify-between"
        style={{ '--field-input-width': schema['x-input-width'] ?? '12rem' } as React.CSSProperties}
      >
        <div className="min-w-0 flex-1">
          {renderFieldHeader()}
        </div>
        <div className="w-full shrink-0 sm:w-[var(--field-input-width)]">
          {renderInputComponent()}
        </div>
      </div>
    )
  }

  return (
    <div className="space-y-2">
      {renderFieldHeader()}

      {/* Input component */}
      {renderInputComponent()}
    </div>
  )
}
