import { useMemo, type ChangeEvent } from 'react'
import type { WorkflowNodeDefinition, WorkflowNodeFieldDefinition, WorkflowParams } from '../../api/workflows'
import {
  FAMILY_FILTER_LABELS,
  FAMILY_FILTER_STYLES,
  getDefinitionFamily,
  getDefinitionModuleLabel,
  groupDefinitionsForStepSelect,
  isDefinitionAllowedForGraphFamily,
  type WorkflowGraphFamily,
} from './workflowNodeLibrary'
import { WorkflowNodeContractCard } from './WorkflowNodeContractCard'

function groupFieldsBySection(fields: WorkflowNodeFieldDefinition[]) {
  return fields.reduce<Record<string, WorkflowNodeFieldDefinition[]>>((sections, field) => {
    const section = field.section || 'General'
    sections[section] = [...(sections[section] ?? []), field]
    return sections
  }, {})
}

function getContractValues(contract: Record<string, unknown> | undefined, key: string): string[] {
  const value = contract?.[key]
  if (!Array.isArray(value)) return []
  return value.filter((entry): entry is string => typeof entry === 'string' && entry.trim().length > 0)
}

function getContractContextLabel(contract: Record<string, unknown> | undefined): string | null {
  const value = contract?.context
  if (value !== 'cad_file' && value !== 'order_line') return null
  return value === 'cad_file' ? 'CAD File' : 'Order Line'
}

type WorkflowNodeInspectorProps = {
  params: WorkflowParams
  onChange: (params: WorkflowParams) => void
  nodeDefinition?: WorkflowNodeDefinition
  step?: string
  onStepChange?: (step: string) => void
  nodeDefinitions: WorkflowNodeDefinition[]
  graphFamily: WorkflowGraphFamily
}

export function WorkflowNodeInspector({
  params,
  onChange,
  nodeDefinition,
  step,
  onStepChange,
  nodeDefinitions,
  graphFamily,
}: WorkflowNodeInspectorProps) {
  const customRenderSettingsEnabled = Boolean(params.use_custom_render_settings)
  const selectableNodeDefinitions = useMemo(
    () =>
      nodeDefinitions.filter(definition =>
        isDefinitionAllowedForGraphFamily(definition, graphFamily),
      ),
    [graphFamily, nodeDefinitions],
  )
  const nodeSelectionGroups = groupDefinitionsForStepSelect(selectableNodeDefinitions)

  const updateField = (field: WorkflowNodeFieldDefinition, value: unknown) => {
    onChange({
      ...params,
      [field.key]: value,
    })
  }

  const handleNumberChange = (field: WorkflowNodeFieldDefinition, event: ChangeEvent<HTMLInputElement>) => {
    const rawValue = event.target.value
    if (rawValue === '') {
      const nextParams = { ...params }
      delete nextParams[field.key]
      onChange(nextParams)
      return
    }
    updateField(field, Number(rawValue))
  }

  const fieldsBySection = groupFieldsBySection(nodeDefinition?.fields ?? [])
  const inputContextLabel = getContractContextLabel(nodeDefinition?.input_contract as Record<string, unknown> | undefined)
  const outputContextLabel = getContractContextLabel(nodeDefinition?.output_contract as Record<string, unknown> | undefined)
  const requiredInputs = getContractValues(nodeDefinition?.input_contract as Record<string, unknown> | undefined, 'requires')
  const providedOutputs = getContractValues(nodeDefinition?.output_contract as Record<string, unknown> | undefined, 'provides')
  const consumedArtifacts = nodeDefinition?.artifact_roles_consumed ?? []
  const producedArtifacts = nodeDefinition?.artifact_roles_produced ?? []

  return (
    <div className="space-y-5">
      <h3 className="font-semibold text-content">Node Configuration</h3>

      {nodeDefinitions.length > 0 && onStepChange && (
        <div>
          <label className="text-sm text-content-secondary mb-2 block">Workflow Node</label>
          <select
            value={step ?? ''}
            onChange={event => onStepChange(event.target.value)}
            className="w-full border border-border-default rounded-lg px-3 py-2 text-sm bg-surface text-content focus:outline-none focus:ring-2 focus:ring-accent"
          >
            {nodeSelectionGroups.map(group => (
              <optgroup key={group.label} label={group.label}>
                {group.options.map(definition => (
                  <option key={definition.step} value={definition.step}>
                    {definition.label}
                  </option>
                ))}
              </optgroup>
            ))}
          </select>
          {nodeDefinition && (
            <div className="mt-2 space-y-1">
              <p className="text-xs text-content-muted">{nodeDefinition.description}</p>
              {graphFamily !== 'mixed' && (
                <p className="text-xs text-content-muted">
                  Step selection is scoped to {FAMILY_FILTER_LABELS[graphFamily]} nodes for this workflow.
                </p>
              )}
              <span
                className={`inline-flex items-center rounded-full px-2 py-0.5 text-[11px] font-medium ${
                  nodeDefinition.execution_kind === 'bridge'
                    ? 'bg-amber-100 text-amber-700 dark:bg-amber-900/40 dark:text-amber-300'
                    : 'bg-green-100 text-green-700 dark:bg-green-900/40 dark:text-green-300'
                }`}
              >
                {nodeDefinition.execution_kind === 'bridge' ? 'Legacy Bridge' : 'Native Node'}
              </span>
            </div>
          )}
        </div>
      )}

      {nodeDefinition && (
        <WorkflowNodeContractCard
          moduleLabel={getDefinitionModuleLabel(nodeDefinition)}
          moduleKey={nodeDefinition.module_key}
          familyLabel={FAMILY_FILTER_LABELS[getDefinitionFamily(nodeDefinition)]}
          familyClassName={FAMILY_FILTER_STYLES[getDefinitionFamily(nodeDefinition)]}
          runtimeLabel={nodeDefinition.execution_kind === 'bridge' ? 'Bridge Runtime' : 'Graph Runtime'}
          runtimeClassName={
            nodeDefinition.execution_kind === 'bridge'
              ? 'bg-amber-100 text-amber-700 dark:bg-amber-900/40 dark:text-amber-300'
              : 'bg-green-100 text-green-700 dark:bg-green-900/40 dark:text-green-300'
          }
          legacyCompatible={nodeDefinition.legacy_compatible}
          legacySource={nodeDefinition.legacy_source}
          inputContextLabel={inputContextLabel}
          outputContextLabel={outputContextLabel}
          requiredInputs={requiredInputs}
          consumedArtifacts={consumedArtifacts}
          providedOutputs={providedOutputs}
          producedArtifacts={producedArtifacts}
        />
      )}

      {Object.keys(fieldsBySection).length === 0 && (
        <p className="text-sm text-content-muted">
          This node currently has no configurable settings in the editor.
        </p>
      )}

      {Object.entries(fieldsBySection).map(([section, fields]) => (
        <div key={section} className="space-y-3">
          <h4 className="text-xs font-semibold uppercase tracking-wide text-content-secondary">
            {section}
          </h4>
          {fields.map(field => {
            const rawValue = params[field.key]
            const value = rawValue ?? field.default
            const disableRenderOverrideField =
              (step === 'blender_still' || step === 'blender_turntable') &&
              !customRenderSettingsEnabled &&
              field.key !== 'use_custom_render_settings' &&
              (field.section === 'Render' || field.section === 'Output')

            return (
              <div key={field.key}>
                <label className="text-sm text-content-secondary mb-1 block">
                  {field.label}
                  {field.unit ? ` (${field.unit})` : ''}
                </label>
                {field.type === 'select' && (
                  <select
                    value={String(value ?? '')}
                    onChange={event => updateField(field, event.target.value)}
                    disabled={disableRenderOverrideField}
                    className="w-full border border-border-default rounded-lg px-3 py-2 text-sm bg-surface text-content focus:outline-none focus:ring-2 focus:ring-accent"
                  >
                    {field.options.map(option => (
                      <option key={String(option.value)} value={String(option.value)}>
                        {option.label}
                      </option>
                    ))}
                  </select>
                )}
                {field.type === 'number' && (
                  <input
                    type="number"
                    min={field.min ?? undefined}
                    max={field.max ?? undefined}
                    step={field.step ?? undefined}
                    value={typeof value === 'number' ? value : value == null ? '' : Number(value)}
                    onChange={event => handleNumberChange(field, event)}
                    disabled={disableRenderOverrideField}
                    className="w-full border border-border-default rounded-lg px-3 py-2 text-sm bg-surface text-content focus:outline-none focus:ring-2 focus:ring-accent"
                  />
                )}
                {field.type === 'boolean' && (
                  <label className="flex items-center gap-2 rounded-lg border border-border-default px-3 py-2 text-sm text-content">
                    <input
                      type="checkbox"
                      checked={Boolean(value)}
                      onChange={event => updateField(field, event.target.checked)}
                      disabled={disableRenderOverrideField}
                      className="accent-accent"
                    />
                    <span>{Boolean(value) ? 'Enabled' : 'Disabled'}</span>
                  </label>
                )}
                {field.type === 'text' && (
                  <input
                    type="text"
                    value={value == null ? '' : String(value)}
                    onChange={event => updateField(field, event.target.value)}
                    disabled={disableRenderOverrideField}
                    className="w-full border border-border-default rounded-lg px-3 py-2 text-sm bg-surface text-content focus:outline-none focus:ring-2 focus:ring-accent"
                  />
                )}
                {field.description && (
                  <p className="mt-1 text-xs text-content-muted">{field.description}</p>
                )}
                {disableRenderOverrideField && (
                  <p className="mt-1 text-xs text-content-muted">
                    In Graph/Shadow mode this field inherits from Output Type and Template until
                    Custom Render Settings is enabled.
                  </p>
                )}
              </div>
            )
          })}
        </div>
      ))}
    </div>
  )
}
