"use client";

import { useEffect, useMemo, useState } from "react";
import { useRouter } from "next/navigation";
import { GitBranch, SkipForward, Sparkles } from "lucide-react";
import { cn } from "@/lib/utils/cn";
import { Button } from "@/components/ui/Button";
import { Input } from "@/components/ui/Input";
import { Card, CardHeader, CardTitle } from "@/components/ui/Card";
import { EmptyState } from "@/components/shared/EmptyState";
import {
  skipDomesticQuestion,
  submitDomesticAnswer,
} from "@/lib/actions/domestic-feed";
import { FEED_WINDOW, ratingRange } from "@/lib/domestic/rules";
import { swalToast } from "@/lib/utils/swal";
import type { FeedItemView } from "@/lib/queries/participant-queries";

interface DomesticFeedProps {
  items: FeedItemView[];
  completedCount: number;
}

function newKey() {
  return typeof crypto !== "undefined" && "randomUUID" in crypto
    ? crypto.randomUUID()
    : `${Date.now()}-${Math.random().toString(36).slice(2)}`;
}

function AnswerInput({
  item,
  value,
  onChange,
}: {
  item: FeedItemView;
  value: unknown;
  onChange: (v: unknown) => void;
}) {
  const optionBtn = (selected: boolean) =>
    cn(
      "w-full rounded-lg border px-4 py-3 text-left text-sm font-semibold transition-colors",
      selected
        ? "border-primary bg-[#EFF6FF] text-primary"
        : "border-border bg-white text-text hover:border-primary/40"
    );

  switch (item.type) {
    case "yes_no":
      return (
        <div className="grid grid-cols-2 gap-2.5">
          {[
            { value: "yes", label: "Yes" },
            { value: "no", label: "No" },
          ].map((o) => (
            <button
              key={o.value}
              type="button"
              className={optionBtn(value === o.value)}
              onClick={() => onChange(o.value)}
            >
              {o.label}
            </button>
          ))}
        </div>
      );
    case "single_choice":
      return (
        <div className="space-y-2">
          {(item.optionsConfig?.options ?? []).map((o) => (
            <button
              key={o.value}
              type="button"
              className={optionBtn(value === o.value)}
              onClick={() => onChange(o.value)}
            >
              {o.label}
            </button>
          ))}
        </div>
      );
    case "multi_choice": {
      const selected = Array.isArray(value) ? (value as string[]) : [];
      return (
        <div className="space-y-2">
          <p className="text-[12px] text-muted">Select all that apply.</p>
          {(item.optionsConfig?.options ?? []).map((o) => {
            const on = selected.includes(o.value);
            return (
              <button
                key={o.value}
                type="button"
                className={optionBtn(on)}
                onClick={() =>
                  onChange(
                    on
                      ? selected.filter((v) => v !== o.value)
                      : [...selected, o.value]
                  )
                }
              >
                {o.label}
              </button>
            );
          })}
        </div>
      );
    }
    case "rating": {
      const { min, max } = ratingRange(item.optionsConfig);
      const steps = Array.from({ length: max - min + 1 }, (_, i) => min + i);
      return (
        <div>
          <div className="flex flex-wrap gap-2">
            {steps.map((n) => (
              <button
                key={n}
                type="button"
                onClick={() => onChange(n)}
                className={cn(
                  "h-11 w-11 rounded-lg border text-sm font-bold transition-colors",
                  value === n
                    ? "border-primary bg-primary text-white"
                    : "border-border bg-white hover:border-primary/40"
                )}
              >
                {n}
              </button>
            ))}
          </div>
          {(item.optionsConfig?.minLabel || item.optionsConfig?.maxLabel) && (
            <div className="mt-2 flex justify-between text-[11.5px] text-muted">
              <span>{item.optionsConfig?.minLabel}</span>
              <span>{item.optionsConfig?.maxLabel}</span>
            </div>
          )}
        </div>
      );
    }
    case "number":
      return (
        <Input
          type="number"
          inputMode="decimal"
          className="max-w-[220px]"
          value={value == null ? "" : String(value)}
          min={item.optionsConfig?.min}
          max={item.optionsConfig?.max}
          onChange={(e) =>
            onChange(e.target.value === "" ? null : Number(e.target.value))
          }
        />
      );
    case "short_text":
      return (
        <Input
          maxLength={500}
          placeholder="Type your answer"
          value={typeof value === "string" ? value : ""}
          onChange={(e) => onChange(e.target.value)}
        />
      );
    default:
      return null;
  }
}

function hasValue(item: FeedItemView, value: unknown) {
  if (value == null || value === "") return false;
  if (item.type === "multi_choice") return Array.isArray(value) && value.length > 0;
  if (item.type === "short_text") return typeof value === "string" && value.trim() !== "";
  return true;
}

export function DomesticFeed({ items, completedCount }: DomesticFeedProps) {
  const router = useRouter();
  const current = items[0];
  const [value, setValue] = useState<unknown>(null);
  const [submitting, setSubmitting] = useState<"answer" | "skip" | null>(null);
  const [error, setError] = useState<string | null>(null);

  // One idempotency key per served item, reused on retries.
  const idempotencyKey = useMemo(() => newKey(), [current?.queueItemId]); // eslint-disable-line react-hooks/exhaustive-deps

  useEffect(() => {
    setValue(null);
    setError(null);
  }, [current?.queueItemId]);

  if (!current) {
    return (
      <Card>
        <EmptyState
          icon={<Sparkles className="h-8 w-8 text-accent" />}
          title="You're all caught up"
          description={
            completedCount > 0
              ? "You've answered every question available right now. New questions are added regularly — check back soon."
              : "There are no questions available yet. Check back soon."
          }
        />
      </Card>
    );
  }

  async function handleSubmit() {
    if (!current) return;
    setSubmitting("answer");
    setError(null);
    const result = await submitDomesticAnswer({
      queueItemId: current.queueItemId,
      idempotencyKey,
      value,
    });
    setSubmitting(null);
    if (!result.success) {
      setError(result.error);
      return;
    }
    if (result.data && result.data.unlocked > 0) {
      void swalToast.fire({
        icon: "success",
        title:
          result.data.unlocked === 1
            ? "Follow-up question unlocked"
            : `${result.data.unlocked} follow-up questions unlocked`,
      });
    }
    router.refresh();
  }

  async function handleSkip() {
    if (!current) return;
    setSubmitting("skip");
    setError(null);
    const result = await skipDomesticQuestion({ queueItemId: current.queueItemId });
    setSubmitting(null);
    if (!result.success) {
      setError(result.error);
      return;
    }
    router.refresh();
  }

  return (
    <div className="grid grid-cols-1 gap-4 lg:grid-cols-[minmax(0,1fr)_300px]">
      <Card className="p-6 sm:p-8">
        <div className="mb-4 flex flex-wrap items-center gap-2 text-[11.5px] font-bold">
          <span className="rounded-full bg-[#F1F5F9] px-2.5 py-1 font-mono text-muted">
            #{current.code}
          </span>
          {current.categoryName && (
            <span className="rounded-full bg-[#EFF6FF] px-2.5 py-1 text-primary">
              {current.categoryName}
            </span>
          )}
          {current.reason === "branch" && (
            <span className="inline-flex items-center gap-1 rounded-full bg-[#FDF4FF] px-2.5 py-1 text-[#A21CAF]">
              <GitBranch className="h-3 w-3" />
              Follow-up
            </span>
          )}
        </div>

        <h2 className="text-xl font-extrabold leading-snug">{current.prompt}</h2>
        {current.helpText && (
          <p className="mt-1.5 text-[13px] text-muted">{current.helpText}</p>
        )}

        <div className="mt-6">
          <AnswerInput item={current} value={value} onChange={setValue} />
        </div>

        {error && <p className="mt-4 text-sm text-danger">{error}</p>}

        <div className="mt-6 flex flex-wrap items-center gap-2.5">
          <Button
            type="button"
            disabled={!hasValue(current, value) || Boolean(submitting)}
            loading={submitting === "answer"}
            onClick={handleSubmit}
          >
            Submit answer
          </Button>
          <Button
            type="button"
            variant="outline"
            disabled={Boolean(submitting)}
            loading={submitting === "skip"}
            onClick={handleSkip}
          >
            <SkipForward className="h-4 w-4" />
            Skip
          </Button>
        </div>
      </Card>

      <Card>
        <CardHeader>
          <CardTitle>Up next</CardTitle>
          <span className="text-[11.5px] font-semibold text-muted">
            {items.length}/{FEED_WINDOW} slots
          </span>
        </CardHeader>
        <ol className="divide-y divide-border">
          {items.map((item, i) => (
            <li
              key={item.queueItemId}
              className={cn(
                "flex items-start gap-3 px-5 py-3",
                i === 0 && "bg-[#F8FAFC]"
              )}
            >
              <span
                className={cn(
                  "mt-0.5 flex h-6 w-6 shrink-0 items-center justify-center rounded-full text-[11px] font-bold",
                  i === 0 ? "bg-primary text-white" : "bg-[#F1F5F9] text-muted"
                )}
              >
                {i + 1}
              </span>
              <div className="min-w-0">
                <div className="flex items-center gap-1.5 text-[11px] font-bold text-muted">
                  <span className="font-mono">#{item.code}</span>
                  {item.reason === "branch" && (
                    <GitBranch className="h-3 w-3 text-[#A21CAF]" />
                  )}
                </div>
                <p className="line-clamp-2 text-[12.5px] text-text">{item.prompt}</p>
              </div>
            </li>
          ))}
        </ol>
      </Card>
    </div>
  );
}
