import { useState, type FormEvent } from 'react';
import { useUpdateWeights } from '../../hooks/useScores';

interface WeightsFormProps {
  weights: Record<string, number>;
}

const SENTIMENT = 'sentiment';

export function WeightsForm({ weights }: WeightsFormProps) {
  // API decimal weights (0-1) → 0-100 integer sliders. For the base dimensions
  // that's their share of the weighted average; for sentiment it's the ± points
  // it can move the composite (MAX_ADJ), decoupled from the base mix.
  const [sliderValues, setSliderValues] = useState<Record<string, number>>(() =>
    Object.fromEntries(
      Object.entries(weights).map(([key, w]) => [key, Math.round(w * 100)])
    )
  );
  const updateWeights = useUpdateWeights();

  const baseKeys = Object.keys(weights).filter((k) => k !== SENTIMENT);
  const hasSentiment = SENTIMENT in weights;
  const baseTotal = baseKeys.reduce((sum, k) => sum + (sliderValues[k] ?? 0), 0);
  const sentimentPts = sliderValues[SENTIMENT] ?? 0;

  const handleChange = (key: string, value: string) => {
    const num = parseInt(value, 10);
    if (!isNaN(num)) setSliderValues((prev) => ({ ...prev, [key]: num }));
  };

  const handleSubmit = (e: FormEvent) => {
    e.preventDefault();
    if (baseTotal === 0) return;

    // Base dimensions normalize among themselves; sentiment passes through raw
    // (slider value / 100) so it stays independent of the base.
    const payload: Record<string, number> = Object.fromEntries(
      baseKeys.map((key) => [key, (sliderValues[key] ?? 0) / baseTotal])
    );
    if (hasSentiment) payload[SENTIMENT] = sentimentPts / 100;
    updateWeights.mutate(payload);
  };

  return (
    <form onSubmit={handleSubmit} className="glass p-5">
      <h3 className="mb-1 text-xs font-semibold uppercase tracking-widest text-gray-500">
        Scoring Weights
      </h3>
      <p className="mb-4 text-[11px] text-gray-500">
        The base dimensions are a weighted average (shares normalize to 100%). Sentiment is applied
        separately as a signed adjustment on top.
      </p>
      <div className="grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-3">
        {baseKeys.map((key) => (
          <label key={key} className="flex flex-col gap-1.5">
            <span className="text-xs text-gray-400 capitalize">
              {key.replace(/_/g, ' ')}
              <span className="ml-1 text-gray-600">
                · {baseTotal > 0 ? Math.round(((sliderValues[key] ?? 0) / baseTotal) * 100) : 0}%
              </span>
            </span>
            <div className="flex items-center gap-2">
              <input
                type="range"
                min={0}
                max={100}
                step={1}
                value={sliderValues[key] ?? 0}
                onChange={(e) => handleChange(key, e.target.value)}
                className="h-2 w-full cursor-pointer appearance-none rounded-lg bg-gray-700 accent-blue-500"
              />
              <span className="min-w-[2ch] text-right text-sm font-medium text-gray-300">
                {sliderValues[key] ?? 0}
              </span>
            </div>
          </label>
        ))}
      </div>

      {hasSentiment && (
        <div className="mt-4 border-t border-white/[0.06] pt-4">
          <label className="flex flex-col gap-1.5">
            <span className="text-xs text-gray-400">Sentiment influence (± points)</span>
            <div className="flex items-center gap-2 sm:max-w-sm">
              <input
                type="range"
                min={0}
                max={30}
                step={1}
                value={sentimentPts}
                onChange={(e) => handleChange(SENTIMENT, e.target.value)}
                className="h-2 w-full cursor-pointer appearance-none rounded-lg bg-gray-700 accent-blue-500"
              />
              <span className="min-w-[3ch] text-right text-sm font-medium text-gray-300">
                ±{sentimentPts}
              </span>
            </div>
            <span className="text-[11px] text-gray-600">
              Max points a bullish (or bearish) read moves the composite, scaled by confidence.
              Doesn&rsquo;t change the base mix. 0 = ignore sentiment.
            </span>
          </label>
        </div>
      )}

      {baseTotal === 0 && (
        <p className="mt-3 text-xs text-red-400">At least one base weight must be greater than zero</p>
      )}
      <button
        type="submit"
        disabled={updateWeights.isPending || baseTotal === 0}
        className="mt-4 btn-primary px-4 py-2 text-sm disabled:opacity-50"
      >
        <span>{updateWeights.isPending ? 'Updating…' : 'Update Weights'}</span>
      </button>
    </form>
  );
}
