import { useState, type FormEvent, type KeyboardEvent } from "react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import {
  faCircleNotch,
  faWandMagicSparkles,
  faFire,
  faMicrophone,
  faMusic,
} from "@fortawesome/free-solid-svg-icons";
import type { InputValues, Language, Vocals } from "../lib/types";
import { formatElapsed, useElapsed } from "../lib/useElapsed";
import { randomStyle } from "../lib/llm";
import { useI18n } from "../lib/i18n";

export type { InputValues };

const LANGUAGES: { value: Language; label: string }[] = [
  { value: "English",    label: "English" },
  { value: "Deutsch",   label: "Deutsch" },
  { value: "Español",   label: "Español" },
  { value: "Français",  label: "Français" },
  { value: "Italiano",  label: "Italiano" },
  { value: "Português", label: "Português" },
  { value: "Polski",    label: "Polski" },
  { value: "Czech",     label: "Čeština" },
  { value: "Other",     label: "Other…" },
];

// Curated "Surprise me" pairs — coherent idea + matching style
const SURPRISE_PAIRS: { idea: string; style: string; mood: string; vocals: Vocals }[] = [
  { idea: "A melancholic lo-fi house beat for a rainy Sunday morning", style: "lo-fi, downtempo, warm vinyl crackle, 85 BPM", mood: "melancholic", vocals: "instrumental" },
  { idea: "An epic orchestral fantasy theme for a dragon rider", style: "cinematic orchestra, soaring strings, choir, 120 BPM", mood: "epic", vocals: "instrumental" },
  { idea: "A dreamy synthwave love song about neon city nights", style: "synthwave, retro arpeggios, lush reverb, 100 BPM", mood: "dreamy", vocals: "vocals" },
  { idea: "A summer beach pop anthem with a massive singalong chorus", style: "upbeat pop, electric guitar, catchy hooks, 128 BPM", mood: "euphoric", vocals: "vocals" },
  { idea: "A tense cinematic underscore for a space station emergency", style: "dark ambient, pulsing synths, tension pads, 90 BPM", mood: "tense", vocals: "instrumental" },
  { idea: "A jazzy bossa nova track about sipping coffee in Paris", style: "bossa nova, acoustic guitar, warm brass, 110 BPM", mood: "relaxed", vocals: "vocals" },
  { idea: "A dark folk ballad about a lighthouse keeper lost at sea", style: "dark folk, acoustic guitar, haunting vocals, 72 BPM", mood: "longing", vocals: "vocals" },
  { idea: "A bouncy chiptune adventure theme for a retro platformer", style: "chiptune, 8-bit, NES style, upbeat, 140 BPM", mood: "playful", vocals: "instrumental" },
];

// Curated "Go crazy" pairs — wild, absurd, unexpected combos
const CRAZY_PAIRS: { idea: string; style: string; mood: string; vocals: Vocals }[] = [
  { idea: "A death metal ode to a sentient washing machine who dreams of becoming a DJ", style: "death metal, heavy blast beats, distorted guitar, 180 BPM", mood: "aggressive", vocals: "vocals" },
  { idea: "An operatic trap banger about a medieval wizard discovering TikTok", style: "operatic trap, 808s, harpsichord, 140 BPM", mood: "chaotic", vocals: "vocals" },
  { idea: "A romantic waltz between a robot and a cactus on Mars", style: "classical waltz, electronic glitch, orchestral, 90 BPM", mood: "bittersweet", vocals: "instrumental" },
  { idea: "A gospel choir celebrating the invention of bubble wrap", style: "gospel, full choir, claps, euphoric brass, 120 BPM", mood: "joyful", vocals: "vocals" },
  { idea: "An avant-garde jazz piece where all instruments are kitchen utensils", style: "experimental jazz, freeform, atonal, 0 BPM (undefined)", mood: "chaotic", vocals: "instrumental" },
  { idea: "A synthpop ballad about a time-traveling accountant in ancient Rome", style: "80s synthpop, catchy arpeggios, reverb, 118 BPM", mood: "quirky", vocals: "vocals" },
  { idea: "A Viking drinking song remixed by an alien DJ", style: "folk metal, hypnotic alien synths, epic choir, 160 BPM", mood: "wild", vocals: "vocals" },
  { idea: "A lullaby for a grumpy dragon who cannot fall asleep", style: "ambient lullaby, gentle bells, warm pads, 60 BPM", mood: "tender", vocals: "vocals" },
];

interface InputPanelProps {
  values: InputValues;
  onChange: (next: InputValues) => void;
  onSubmit: () => void;
  loading: boolean;
  disabled?: boolean;
  cancelButton?: React.ReactNode;
}

export function InputPanel({
  values,
  onChange,
  onSubmit,
  loading,
  disabled,
  cancelButton,
}: InputPanelProps) {
  const [styleLoading, setStyleLoading] = useState<null | "normal" | "crazy">(null);
  const elapsed = useElapsed(loading);
  const { t } = useI18n();

  const set = <K extends keyof InputValues>(key: K, value: InputValues[K]) =>
    onChange({ ...values, [key]: value });

  const canSubmit = !loading && !disabled && values.idea.trim().length > 0;

  const submit = (e?: FormEvent) => {
    e?.preventDefault();
    if (canSubmit) onSubmit();
  };

  const onCmdEnter = (e: KeyboardEvent<HTMLInputElement | HTMLTextAreaElement>) => {
    if ((e.metaKey || e.ctrlKey) && e.key === "Enter") {
      e.preventDefault();
      submit();
    }
  };

  // "Surprise me" fills style. If idea is empty, fills a random idea too.
  const handleSurpriseMe = async () => {
    if (styleLoading) return;
    const hasIdea = values.idea.trim().length > 0;
    const ex = SURPRISE_PAIRS[Math.floor(Math.random() * SURPRISE_PAIRS.length)];
    const ideaToUse = hasIdea ? values.idea : ex.idea;
    
    const ctrl = new AbortController();
    setStyleLoading("normal");
    try {
      const style = await randomStyle("normal", ctrl.signal, ideaToUse);
      onChange({ 
        ...values, 
        idea: ideaToUse, 
        style_hint: style, 
        mood: hasIdea ? values.mood : ex.mood, 
        vocals: hasIdea ? values.vocals : ex.vocals 
      });
    } catch (err) {
      if (err instanceof DOMException && err.name === "AbortError") return;
      onChange({ 
        ...values, 
        idea: ideaToUse, 
        style_hint: hasIdea ? values.style_hint : ex.style, 
        mood: hasIdea ? values.mood : ex.mood, 
        vocals: hasIdea ? values.vocals : ex.vocals 
      });
    } finally {
      setStyleLoading((curr) => (curr === "normal" ? null : curr));
    }
  };

  // "Go crazy" fills style wildly. If idea is empty, fills a wild idea too.
  const handleGoCrazy = async () => {
    if (styleLoading) return;
    const hasIdea = values.idea.trim().length > 0;
    const ex = CRAZY_PAIRS[Math.floor(Math.random() * CRAZY_PAIRS.length)];
    const ideaToUse = hasIdea ? values.idea : ex.idea;
    
    const ctrl = new AbortController();
    setStyleLoading("crazy");
    try {
      const style = await randomStyle("crazy", ctrl.signal, ideaToUse);
      onChange({ 
        ...values, 
        idea: ideaToUse, 
        style_hint: style, 
        mood: hasIdea ? values.mood : ex.mood, 
        vocals: hasIdea ? values.vocals : ex.vocals 
      });
    } catch (err) {
      if (err instanceof DOMException && err.name === "AbortError") return;
      onChange({ 
        ...values, 
        idea: ideaToUse, 
        style_hint: hasIdea ? values.style_hint : ex.style, 
        mood: hasIdea ? values.mood : ex.mood, 
        vocals: hasIdea ? values.vocals : ex.vocals 
      });
    } finally {
      setStyleLoading((curr) => (curr === "crazy" ? null : curr));
    }
  };

  const anyLoading = styleLoading !== null;

  return (
    <form onSubmit={submit} className="flex flex-col gap-4 h-full">
      {/* Music Idea */}
      <div className="flex flex-col gap-1.5">
        <label htmlFor="idea" className="text-xs font-bold uppercase tracking-wider text-fg-muted">
          {t.musicIdea}
        </label>
        <textarea
          id="idea"
          value={values.idea}
          onChange={(e) => set("idea", e.target.value)}
          onKeyDown={onCmdEnter}
          placeholder={t.placeholderIdea}
          className="textarea text-[14px] leading-relaxed scrollbar-thin"
          style={{ minHeight: 90, resize: "vertical" }}
          required
        />
        {/* Example / Surprise / Crazy buttons */}
        <div className="flex flex-wrap gap-2 pt-0.5">
          {/* Removed Try an Example button */}
          <button
            type="button"
            onClick={handleSurpriseMe}
            disabled={anyLoading}
            className="btn-fun border-accent-secondary/50 text-accent-secondary hover:bg-accent-secondary/10 bg-accent-secondary/5"
          >
            {styleLoading === "normal"
              ? <FontAwesomeIcon icon={faCircleNotch} spin className="w-3 h-3" />
              : <FontAwesomeIcon icon={faWandMagicSparkles} className="w-3 h-3" />}
            {t.surpriseMe}
          </button>
          <button
            type="button"
            onClick={handleGoCrazy}
            disabled={anyLoading}
            className="btn-fun border-rose-500/50 text-rose-400 hover:bg-rose-500/10 bg-rose-500/5"
          >
            {styleLoading === "crazy"
              ? <FontAwesomeIcon icon={faCircleNotch} spin className="w-3 h-3" />
              : <FontAwesomeIcon icon={faFire} className="w-3 h-3" />}
            {t.goCrazy}
          </button>
        </div>
      </div>

      {/* Divider */}
      <div className="border-t border-border" />

      {/* Options Grid */}
      <div className="grid grid-cols-2 gap-3">
        {/* Language */}
        <div className="flex flex-col gap-1.5">
          <label htmlFor="language" className="text-xs font-bold uppercase tracking-wider text-fg-muted">
            {t.language}
          </label>
          <select
            id="language"
            value={values.language}
            onChange={(e) => set("language", e.target.value as Language)}
            className="input h-[36px] py-0 text-sm"
          >
            {LANGUAGES.map((l) => (
              <option key={l.value} value={l.value}>{l.label}</option>
            ))}
          </select>
          {values.language === "Other" && (
            <input
              type="text"
              className="input h-[36px] text-sm"
              placeholder="e.g. 日本語"
              value={values.customLanguage}
              onChange={(e) => set("customLanguage", e.target.value)}
            />
          )}
        </div>

        {/* Mood */}
        <div className="flex flex-col gap-1.5">
          <label htmlFor="mood" className="text-xs font-bold uppercase tracking-wider text-fg-muted">
            {t.mood} <span className="normal-case font-normal opacity-60 text-[10px]">{t.optional}</span>
          </label>
          <input
            id="mood"
            type="text"
            placeholder={t.placeholderMood}
            value={values.mood}
            onChange={(e) => set("mood", e.target.value)}
            className="input h-[36px] text-sm"
          />
        </div>
      </div>

      {/* Style */}
      <div className="flex flex-col gap-1.5">
        <label htmlFor="style_hint" className="text-xs font-bold uppercase tracking-wider text-fg-muted">
          {t.musicStyle} <span className="normal-case font-normal opacity-60 text-[10px]">{t.optional}</span>
        </label>
        <input
          id="style_hint"
          type="text"
          placeholder={t.placeholderStyle}
          value={values.style_hint}
          onChange={(e) => set("style_hint", e.target.value)}
          onKeyDown={onCmdEnter}
          className="input h-[36px] text-sm"
        />
      </div>

      {/* Vocals Toggle */}
      <div className="flex flex-col gap-1.5">
        <label className="text-xs font-bold uppercase tracking-wider text-fg-muted">{t.vocals}</label>
        <div className="inline-flex rounded-xl border border-border bg-bg h-[36px] p-0.5 w-full">
          <button
            type="button"
            onClick={() => set("vocals", "vocals")}
            className={`flex-1 flex items-center justify-center gap-2 rounded-lg text-xs font-bold transition-all duration-150 ${
              values.vocals === "vocals"
                ? "gradient-bg text-white shadow-md"
                : "text-fg-muted hover:text-fg"
            }`}
            title={t.vocalsOption}
          >
            <FontAwesomeIcon icon={faMicrophone} />
            <span>{t.vocalsOption}</span>
          </button>
          <button
            type="button"
            onClick={() => set("vocals", "instrumental")}
            className={`flex-1 flex items-center justify-center gap-2 rounded-lg text-xs font-bold transition-all duration-150 ${
              values.vocals === "instrumental"
                ? "gradient-bg text-white shadow-md"
                : "text-fg-muted hover:text-fg"
            }`}
            title={t.instrumentalOption}
          >
            <FontAwesomeIcon icon={faMusic} />
            <span>{t.instrumentalOption}</span>
          </button>
        </div>
      </div>

      {/* Spacer to push generate button down */}
      <div className="flex-1" />

      {/* Generate Button */}
      <div className="flex flex-col gap-2">
        <button
          type="submit"
          disabled={!canSubmit}
          className="w-full h-[46px] rounded-xl text-sm font-bold text-white shadow-lg transition-all duration-150
            disabled:opacity-40 disabled:cursor-not-allowed disabled:shadow-none
            flex items-center justify-center gap-2 gradient-bg hover:brightness-110 hover:-translate-y-0.5
            active:brightness-95 active:translate-y-0"
        >
          {loading ? (
            <>
              <FontAwesomeIcon icon={faCircleNotch} spin className="w-4 h-4" />
              {t.generating} {formatElapsed(elapsed)}
            </>
          ) : (
            <>
              <FontAwesomeIcon icon={faWandMagicSparkles} className="w-4 h-4" />
              {t.generateAssets}
            </>
          )}
        </button>
        {loading && cancelButton}
      </div>
    </form>
  );
}
