/**
 * Dynamic Select Field Component
 *
 * Renders a dropdown select with dynamically loaded options from an API endpoint.
 * Supports dependent fields (e.g., load list after selecting a workspace).
 * Includes a toggle to switch to variable input mode for dynamic values.
 * Supports optional description, icon, disabled state, and grouping.
 */

import { memo, useState, useEffect, useMemo } from 'react';
import { Loader2, Zap, ChevronDown } from 'lucide-react';
import { Label } from '../ui/label';
import {
  Select,
  SelectContent,
  SelectGroup,
  SelectItem,
  SelectLabel,
  SelectTrigger,
  SelectValue,
} from '../ui/select';
import { VariableInput } from '../VariableInput';
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '../ui/tooltip';
import { ActionField, ActionFieldOption } from '../../types/action';
import { AvailableContext } from '../../hooks/useAvailableContext';
import { resolveIcon } from '../../lib/icon-resolver';

interface DynamicSelectFieldProps {
  fieldName: string;
  field: ActionField;
  value: string;
  options: ActionFieldOption[];
  isLoading: boolean;
  onChange: (value: string) => void;
  error?: string;
  fieldError?: string;
  dependencyMet: boolean;
  dependencyLabel?: string;
  availableContext?: AvailableContext;
}

/** Check if a value contains a variable reference */
function isVariableValue(value: string): boolean {
  return typeof value === 'string' && value.includes('{{');
}

/** Group options by their group property. Ungrouped options use '' as key. */
function groupOptions(options: ActionFieldOption[]): Map<string, ActionFieldOption[]> {
  const groups = new Map<string, ActionFieldOption[]>();
  for (const option of options) {
    const key = option.group ?? '';
    const list = groups.get(key);
    if (list) {
      list.push(option);
    } else {
      groups.set(key, [option]);
    }
  }
  return groups;
}

function OptionContent({ option }: { option: ActionFieldOption }) {
  const Icon = resolveIcon(option.icon);

  if (!Icon && !option.description) {
    return <>{option.label}</>;
  }

  return (
    <div className="flex flex-col gap-0.5">
      <span className="flex items-center gap-1.5">
        {Icon && <Icon className="h-3.5 w-3.5 shrink-0 text-slate-500" />}
        {option.label}
      </span>
      {option.description && (
        <span className="text-[11px] text-slate-400 leading-tight">{option.description}</span>
      )}
    </div>
  );
}

export const DynamicSelectField = memo(function DynamicSelectField({
  fieldName,
  field,
  value,
  options,
  isLoading,
  onChange,
  error,
  fieldError,
  dependencyMet,
  dependencyLabel,
  availableContext,
}: DynamicSelectFieldProps) {
  const [variableMode, setVariableMode] = useState(() => isVariableValue(value || ''));

  // If the value changes externally and contains a variable, switch to variable mode
  useEffect(() => {
    if (value && isVariableValue(value)) {
      setVariableMode(true);
    }
  }, [value]);

  const handleToggle = () => {
    if (variableMode) {
      // Switching from variable → select: clear value if it was a variable
      if (value && isVariableValue(value)) {
        onChange('');
      }
    }
    setVariableMode((prev) => !prev);
  };

  const hasContext = availableContext && availableContext.groups.length > 0;
  const hasGroups = options.some((opt) => opt.group);
  const grouped = useMemo(
    () => (hasGroups ? groupOptions(options) : null),
    [options, hasGroups],
  );

  const renderOptions = () => {
    if (grouped) {
      return Array.from(grouped.entries()).map(([groupName, groupOpts]) => (
        <SelectGroup key={groupName}>
          {groupName && <SelectLabel>{groupName}</SelectLabel>}
          {groupOpts.map((option) => (
            <SelectItem
              key={option.value}
              value={option.value}
              className="text-[13px]"
              disabled={option.disabled}
            >
              <OptionContent option={option} />
            </SelectItem>
          ))}
        </SelectGroup>
      ));
    }

    return options.map((option) => (
      <SelectItem
        key={option.value}
        value={option.value}
        className="text-[13px]"
        disabled={option.disabled}
      >
        <OptionContent option={option} />
      </SelectItem>
    ));
  };

  return (
    <div className="space-y-2">
      <div className="flex items-center justify-between">
        <Label htmlFor={fieldName} className="text-[13px] font-medium text-slate-700 tracking-tight">
          {field.label}
          {field.required && <span className="text-rose-500 ml-0.5">*</span>}
        </Label>

        {hasContext && (
          <TooltipProvider>
            <Tooltip>
              <TooltipTrigger asChild>
                <button
                  type="button"
                  onClick={handleToggle}
                  className={`p-1 rounded transition-colors ${
                    variableMode
                      ? 'text-cyan-600 bg-cyan-50 hover:bg-cyan-100'
                      : 'text-slate-400 hover:text-cyan-600 hover:bg-slate-100'
                  }`}
                >
                  {variableMode ? (
                    <ChevronDown className="w-3.5 h-3.5" />
                  ) : (
                    <Zap className="w-3.5 h-3.5" />
                  )}
                </button>
              </TooltipTrigger>
              <TooltipContent side="left">
                {variableMode ? 'Switch to dropdown' : 'Use dynamic variable'}
              </TooltipContent>
            </Tooltip>
          </TooltipProvider>
        )}
      </div>

      {variableMode && availableContext ? (
        <VariableInput
          value={value || ''}
          onChange={onChange}
          availableContext={availableContext}
          placeholder={`e.g. {{Trigger.user_id}}`}
        />
      ) : !dependencyMet ? (
        <div className="flex items-center gap-2 h-10 px-3 rounded-lg border border-slate-200 bg-slate-50/50">
          <span className="text-[13px] text-slate-400">
            Select {dependencyLabel || field.depends_on?.replace('_', ' ')} first.
          </span>
        </div>
      ) : isLoading ? (
        <div className="flex items-center gap-2.5 h-10 px-3 rounded-lg border border-slate-200 bg-slate-50/50">
          <Loader2 className="w-4 h-4 animate-spin text-slate-400" />
          <span className="text-[13px] text-slate-400">Loading options...</span>
        </div>
      ) : fieldError ? (
        <div className="flex items-start gap-2 rounded-lg bg-rose-50 border border-rose-100 px-3 py-2.5">
          <span className="text-[13px] text-rose-700 leading-snug">{fieldError}</span>
        </div>
      ) : (
        <Select value={value} onValueChange={onChange} disabled={options.length === 0}>
          <SelectTrigger
            id={fieldName}
            className="h-10 text-[13px] border-slate-200 hover:border-slate-300 focus:ring-2 focus:ring-cyan-500/20 focus:border-cyan-500 transition-colors duration-150 disabled:bg-slate-50/50 disabled:cursor-not-allowed"
          >
            <SelectValue
              placeholder={
                options.length === 0
                  ? `No ${field.label?.toLowerCase() || 'options'} available`
                  : `Select ${field.label?.toLowerCase() || 'an option'}`
              }
            />
          </SelectTrigger>
          <SelectContent>{renderOptions()}</SelectContent>
        </Select>
      )}

      <p className="text-[12px] text-slate-400 leading-relaxed">{field.description}</p>
      {error && (
        <div className="flex items-start gap-2 rounded-lg bg-rose-50 border border-rose-100 px-3 py-2.5">
          <span className="text-[13px] text-rose-700 leading-snug">{error}</span>
        </div>
      )}
    </div>
  );
});
