"use client";

import { useMemo, useState } from "react";
import { useRouter } from "next/navigation";
import { ArrowLeft, ArrowRight, Loader2, Sparkles, User } from "lucide-react";
import { toast } from "sonner";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Textarea } from "@/components/ui/textarea";
import { Card, CardContent } from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import { cn } from "@/lib/utils";
import { TONES, FORMATS, LANGUAGES, LENGTH_OPTIONS, FORMAT_SPEAKERS } from "@/lib/episodes/options";
import { VOICE_CATALOG, DEFAULT_VOICE_IDS } from "@/lib/ai/voices";
import { createEpisodeAction, type CreateEpisodeInput } from "@/app/(app)/episodes/actions";

type Format = "SOLO" | "INTERVIEW" | "MULTI_HOST";
interface SpeakerState {
  speakerKey: string;
  displayName: string;
  elevenVoiceId: string;
}

function defaultSpeakers(format: Format): SpeakerState[] {
  return FORMAT_SPEAKERS[format].map((s, i) => ({
    speakerKey: s.speakerKey,
    displayName: s.defaultName,
    elevenVoiceId:
      DEFAULT_VOICE_IDS[s.speakerKey] ?? VOICE_CATALOG[i % VOICE_CATALOG.length].id,
  }));
}

export function EpisodeWizard({ maxMinutes }: { maxMinutes: number }) {
  const router = useRouter();
  const [step, setStep] = useState(1);
  const [submitting, setSubmitting] = useState(false);

  const [title, setTitle] = useState("");
  const [topic, setTopic] = useState("");
  const [tone, setTone] = useState<string>(TONES[0]);
  const [format, setFormat] = useState<Format>("SOLO");
  const [language, setLanguage] = useState("en");
  const [length, setLength] = useState(5);
  const [audience, setAudience] = useState("");
  const [speakers, setSpeakers] = useState<SpeakerState[]>(defaultSpeakers("SOLO"));

  const lengths = useMemo(() => LENGTH_OPTIONS.filter((l) => l <= maxMinutes), [maxMinutes]);

  function changeFormat(f: Format) {
    setFormat(f);
    setSpeakers(defaultSpeakers(f));
  }

  function updateSpeaker(idx: number, patch: Partial<SpeakerState>) {
    setSpeakers((prev) => prev.map((s, i) => (i === idx ? { ...s, ...patch } : s)));
  }

  function next() {
    if (step === 1 && topic.trim().length < 10) {
      toast.error("Please describe your topic in a bit more detail.");
      return;
    }
    setStep((s) => Math.min(3, s + 1));
  }

  async function submit() {
    setSubmitting(true);
    const input: CreateEpisodeInput = {
      title: title.trim() || undefined,
      topic: topic.trim(),
      tone,
      format,
      language,
      targetLengthMin: length,
      audience: audience.trim() || undefined,
      speakers,
    };
    const res = await createEpisodeAction(input);
    if (!res.ok) {
      toast.error(res.error);
      setSubmitting(false);
      return;
    }
    toast.success("Generating your episode…");
    router.push(`/episodes/${res.episodeId}`);
  }

  return (
    <div className="mx-auto max-w-2xl">
      <Stepper step={step} />

      <Card className="mt-6">
        <CardContent className="space-y-6 p-6">
          {step === 1 && (
            <>
              <Field label="What's your episode about?" htmlFor="topic">
                <Textarea
                  id="topic"
                  rows={4}
                  placeholder="e.g. The surprising history of coffee and how it shaped global trade…"
                  value={topic}
                  onChange={(e) => setTopic(e.target.value)}
                />
              </Field>
              <Field label="Episode title (optional)" htmlFor="title">
                <Input
                  id="title"
                  placeholder="Leave blank to auto-generate"
                  value={title}
                  onChange={(e) => setTitle(e.target.value)}
                />
              </Field>
              <div className="grid gap-4 sm:grid-cols-2">
                <Field label="Tone">
                  <SimpleSelect value={tone} onChange={setTone} options={TONES.map((t) => ({ value: t, label: t }))} />
                </Field>
                <Field label="Language">
                  <SimpleSelect
                    value={language}
                    onChange={setLanguage}
                    options={LANGUAGES.map((l) => ({ value: l.code, label: l.label }))}
                  />
                </Field>
                <Field label="Length">
                  <SimpleSelect
                    value={String(length)}
                    onChange={(v) => setLength(Number(v))}
                    options={lengths.map((l) => ({ value: String(l), label: `${l} minutes` }))}
                  />
                </Field>
                <Field label="Audience (optional)" htmlFor="audience">
                  <Input
                    id="audience"
                    placeholder="e.g. busy professionals"
                    value={audience}
                    onChange={(e) => setAudience(e.target.value)}
                  />
                </Field>
              </div>
              <Field label="Format">
                <div className="grid gap-3 sm:grid-cols-3">
                  {FORMATS.map((f) => (
                    <button
                      key={f.value}
                      type="button"
                      onClick={() => changeFormat(f.value)}
                      className={cn(
                        "rounded-2xl border p-4 text-left transition-colors",
                        format === f.value
                          ? "border-brand bg-brand/5 ring-1 ring-brand"
                          : "border-border hover:bg-secondary"
                      )}
                    >
                      <p className="text-sm font-semibold">{f.label}</p>
                      <p className="mt-1 text-xs text-muted-foreground">{f.description}</p>
                    </button>
                  ))}
                </div>
              </Field>
            </>
          )}

          {step === 2 && (
            <>
              <div>
                <h2 className="text-lg font-semibold">Cast your voices</h2>
                <p className="text-sm text-muted-foreground">
                  Assign a realistic AI voice to each speaker.
                </p>
              </div>
              <div className="space-y-4">
                {speakers.map((sp, idx) => (
                  <div key={sp.speakerKey} className="rounded-2xl border border-border p-4">
                    <div className="mb-3 flex items-center gap-2">
                      <span className="flex h-8 w-8 items-center justify-center rounded-xl bg-brand/10 text-brand">
                        <User className="h-4 w-4" />
                      </span>
                      <span className="text-sm font-medium capitalize">{sp.speakerKey}</span>
                    </div>
                    <div className="grid gap-3 sm:grid-cols-2">
                      <Field label="Display name">
                        <Input
                          value={sp.displayName}
                          onChange={(e) => updateSpeaker(idx, { displayName: e.target.value })}
                        />
                      </Field>
                      <Field label="Voice">
                        <SimpleSelect
                          value={sp.elevenVoiceId}
                          onChange={(v) => updateSpeaker(idx, { elevenVoiceId: v })}
                          options={VOICE_CATALOG.map((v) => ({
                            value: v.id,
                            label: `${v.name} · ${v.gender} · ${v.accent}`,
                          }))}
                        />
                      </Field>
                    </div>
                  </div>
                ))}
              </div>
            </>
          )}

          {step === 3 && (
            <>
              <div>
                <h2 className="text-lg font-semibold">Review &amp; generate</h2>
                <p className="text-sm text-muted-foreground">
                  We&apos;ll write the script, record the audio, and design the cover art.
                </p>
              </div>
              <dl className="grid grid-cols-2 gap-3 text-sm">
                <Summary label="Title" value={title || "Auto-generated"} />
                <Summary label="Format" value={FORMATS.find((f) => f.value === format)?.label ?? format} />
                <Summary label="Tone" value={tone} />
                <Summary label="Length" value={`${length} min`} />
                <Summary label="Language" value={LANGUAGES.find((l) => l.code === language)?.label ?? language} />
                <Summary label="Voices" value={speakers.map((s) => s.displayName).join(", ")} />
              </dl>
              <div className="flex items-center gap-2 rounded-2xl border border-border bg-secondary p-4 text-sm text-muted-foreground">
                <Badge variant="brand">Heads up</Badge>
                Generating uses 1 script + 1 audio credit from your monthly plan.
              </div>
            </>
          )}

          <div className="flex items-center justify-between pt-2">
            <Button
              variant="ghost"
              onClick={() => setStep((s) => Math.max(1, s - 1))}
              disabled={step === 1 || submitting}
            >
              <ArrowLeft className="h-4 w-4" /> Back
            </Button>
            {step < 3 ? (
              <Button onClick={next}>
                Continue <ArrowRight className="h-4 w-4" />
              </Button>
            ) : (
              <Button onClick={submit} disabled={submitting}>
                {submitting ? <Loader2 className="h-4 w-4 animate-spin" /> : <Sparkles className="h-4 w-4" />}
                Generate episode
              </Button>
            )}
          </div>
        </CardContent>
      </Card>
    </div>
  );
}

function Stepper({ step }: { step: number }) {
  const labels = ["Configure", "Voices", "Review"];
  return (
    <div className="flex items-center justify-center gap-2">
      {labels.map((label, i) => {
        const n = i + 1;
        const active = step === n;
        const done = step > n;
        return (
          <div key={label} className="flex items-center gap-2">
            <span
              className={cn(
                "flex h-8 w-8 items-center justify-center rounded-full text-xs font-semibold transition-colors",
                active || done ? "bg-brand text-brand-foreground" : "bg-secondary text-muted-foreground"
              )}
            >
              {n}
            </span>
            <span className={cn("text-sm", active ? "font-medium" : "text-muted-foreground")}>{label}</span>
            {i < labels.length - 1 && <span className="mx-1 h-px w-6 bg-border" />}
          </div>
        );
      })}
    </div>
  );
}

function Field({
  label,
  htmlFor,
  children,
}: {
  label: string;
  htmlFor?: string;
  children: React.ReactNode;
}) {
  return (
    <div className="space-y-2">
      <Label htmlFor={htmlFor}>{label}</Label>
      {children}
    </div>
  );
}

function SimpleSelect({
  value,
  onChange,
  options,
}: {
  value: string;
  onChange: (v: string) => void;
  options: { value: string; label: string }[];
}) {
  return (
    <Select value={value} onValueChange={onChange}>
      <SelectTrigger>
        <SelectValue />
      </SelectTrigger>
      <SelectContent>
        {options.map((o) => (
          <SelectItem key={o.value} value={o.value}>
            {o.label}
          </SelectItem>
        ))}
      </SelectContent>
    </Select>
  );
}

function Summary({ label, value }: { label: string; value: string }) {
  return (
    <div className="rounded-xl border border-border p-3">
      <dt className="text-xs text-muted-foreground">{label}</dt>
      <dd className="mt-0.5 font-medium">{value}</dd>
    </div>
  );
}
