"use client";

import { useMemo, useState } from "react";
import { useRouter } from "next/navigation";
import Link from "next/link";
import { ArrowRight, Trash2 } from "lucide-react";
import { cn } from "@/lib/utils/cn";
import { Button } from "@/components/ui/Button";
import { Input } from "@/components/ui/Input";
import { Select } from "@/components/ui/Select";
import { Card, CardHeader, CardTitle, Field, Label } from "@/components/ui/Card";
import { addDomesticEdge, removeDomesticEdge } from "@/lib/actions/admin-domestic";
import {
  CONDITION_LABELS,
  EDGE_TYPE_LABELS,
  conditionsForType,
  formatDomesticAnswer,
} from "@/lib/domestic/rules";
import { DOMESTIC_EDGE_TYPES } from "@/lib/validation/domestic";
import { swalConfirm, swalToast } from "@/lib/utils/swal";
import type { DomesticEdgeView } from "@/lib/queries/domestic-admin-queries";
import type {
  DomesticConditionType,
  DomesticEdgeType,
  DomesticOptionsConfig,
  DomesticQuestionType,
} from "@/types/participant";

interface DomesticEdgesPanelProps {
  questionId: string;
  sourceType: DomesticQuestionType;
  sourceOptions: DomesticOptionsConfig | null;
  edges: DomesticEdgeView[];
  targets: Array<{ id: string; code: string; prompt: string; status: string }>;
  disabled?: boolean;
}

function choiceOptions(type: DomesticQuestionType, config: DomesticOptionsConfig | null) {
  if (type === "yes_no") {
    return [
      { value: "yes", label: "Yes" },
      { value: "no", label: "No" },
    ];
  }
  return config?.options ?? [];
}

export function DomesticEdgesPanel({
  questionId,
  sourceType,
  sourceOptions,
  edges,
  targets,
  disabled,
}: DomesticEdgesPanelProps) {
  const router = useRouter();
  const conditions = conditionsForType(sourceType);
  const options = choiceOptions(sourceType, sourceOptions);
  const hasChoices = options.length > 0;

  const nextPriority = useMemo(
    () => (edges.length ? Math.max(...edges.map((e) => e.priority)) + 10 : 10),
    [edges]
  );

  const [conditionType, setConditionType] = useState<DomesticConditionType>(
    conditions.includes("equals") ? "equals" : conditions[0]
  );
  const [conditionValue, setConditionValue] = useState(options[0]?.value ?? "");
  const [conditionValues, setConditionValues] = useState<string[]>([]);
  const [edgeType, setEdgeType] = useState<DomesticEdgeType>("unlock");
  const [toQuestionId, setToQuestionId] = useState(targets[0]?.id ?? "");
  const [priority, setPriority] = useState(String(nextPriority));
  const [busy, setBusy] = useState<string | null>(null);
  const [error, setError] = useState<string | null>(null);

  function describeCondition(e: DomesticEdgeView) {
    if (e.conditionType === "always") return "Always";
    if (e.conditionType === "any_of") {
      return `${CONDITION_LABELS.any_of} ${(e.conditionConfig?.values ?? [])
        .map((v) => formatDomesticAnswer(sourceType, sourceOptions, v))
        .join(", ")}`;
    }
    return `${CONDITION_LABELS[e.conditionType]} ${formatDomesticAnswer(
      sourceType,
      sourceOptions,
      e.conditionConfig?.value
    )}`;
  }

  async function handleAdd() {
    setBusy("add");
    setError(null);
    const numeric = sourceType === "rating" || sourceType === "number";
    const result = await addDomesticEdge({
      questionId,
      conditionType,
      conditionValue:
        conditionType === "always" || conditionType === "any_of"
          ? undefined
          : numeric
            ? Number(conditionValue)
            : conditionValue,
      conditionValues: conditionType === "any_of" ? conditionValues : undefined,
      toQuestionId: edgeType === "terminate" && !toQuestionId ? null : toQuestionId || null,
      edgeType,
      priority: Number(priority) || 0,
    });
    setBusy(null);
    if (!result.success) {
      setError(result.error);
      return;
    }
    void swalToast.fire({ icon: "success", title: "Branch rule added" });
    setPriority(String(Number(priority) + 10));
    router.refresh();
  }

  async function handleRemove(edgeId: string) {
    const ok = await swalConfirm({
      title: "Remove this branch rule?",
      text: "It stops applying to new answers immediately.",
      confirmText: "Remove",
      danger: true,
    });
    if (!ok) return;
    setBusy(edgeId);
    const result = await removeDomesticEdge(edgeId);
    setBusy(null);
    if (!result.success) {
      void swalToast.fire({ icon: "error", title: result.error });
      return;
    }
    router.refresh();
  }

  return (
    <Card>
      <CardHeader>
        <CardTitle>Branch rules</CardTitle>
        <span className="text-[11.5px] font-semibold text-muted">
          Evaluated in priority order
        </span>
      </CardHeader>

      {edges.length === 0 ? (
        <p className="px-5 py-4 text-[13px] text-muted">
          No rules yet. Add one to unlock a follow-up question based on the answer.
        </p>
      ) : (
        <ul className="divide-y divide-border">
          {edges.map((e) => (
            <li key={e.id} className="flex items-start gap-3 px-5 py-3 text-[13px]">
              <span className="mt-0.5 rounded bg-[#F1F5F9] px-1.5 py-0.5 font-mono text-[11px] font-bold text-muted">
                {e.priority}
              </span>
              <div className="min-w-0 flex-1">
                <div className="font-semibold">{describeCondition(e)}</div>
                <div className="mt-0.5 flex flex-wrap items-center gap-1.5 text-muted">
                  <ArrowRight className="h-3.5 w-3.5" />
                  <span
                    className={cn(
                      "font-semibold",
                      e.edgeType === "unlock" && "text-success",
                      (e.edgeType === "suppress" || e.edgeType === "terminate") &&
                        "text-danger"
                    )}
                  >
                    {EDGE_TYPE_LABELS[e.edgeType]}
                  </span>
                  {e.toQuestionId && (
                    <Link
                      href={`/admin/domestic/questions/${e.toQuestionId}`}
                      className="truncate text-primary hover:underline"
                    >
                      #{e.toCode} {e.toPrompt}
                    </Link>
                  )}
                </div>
              </div>
              <Button
                type="button"
                variant="icon"
                size="row"
                disabled={disabled || busy === e.id}
                onClick={() => handleRemove(e.id)}
                aria-label="Remove rule"
              >
                <Trash2 className="h-3.5 w-3.5" />
              </Button>
            </li>
          ))}
        </ul>
      )}

      {!disabled && (
        <div className="border-t border-border p-5">
          <div className="mb-3 text-[12.5px] font-bold uppercase tracking-wide text-muted">
            Add rule
          </div>
          <div className="grid grid-cols-1 gap-x-4 sm:grid-cols-2">
            <Field>
              <Label htmlFor="edge-condition">When</Label>
              <Select
                id="edge-condition"
                value={conditionType}
                onChange={(e) => setConditionType(e.target.value as DomesticConditionType)}
              >
                {conditions.map((c) => (
                  <option key={c} value={c}>
                    {CONDITION_LABELS[c]}
                  </option>
                ))}
              </Select>
            </Field>

            {conditionType !== "always" && conditionType !== "any_of" && (
              <Field>
                <Label htmlFor="edge-value">Answer</Label>
                {hasChoices ? (
                  <Select
                    id="edge-value"
                    value={conditionValue}
                    onChange={(e) => setConditionValue(e.target.value)}
                  >
                    {options.map((o) => (
                      <option key={o.value} value={o.value}>
                        {o.label}
                      </option>
                    ))}
                  </Select>
                ) : (
                  <Input
                    id="edge-value"
                    type="number"
                    value={conditionValue}
                    onChange={(e) => setConditionValue(e.target.value)}
                  />
                )}
              </Field>
            )}

            {conditionType === "any_of" && (
              <Field className="sm:col-span-2">
                <Label>Answers</Label>
                <div className="flex flex-wrap gap-2">
                  {options.map((o) => {
                    const on = conditionValues.includes(o.value);
                    return (
                      <button
                        key={o.value}
                        type="button"
                        onClick={() =>
                          setConditionValues((prev) =>
                            on ? prev.filter((v) => v !== o.value) : [...prev, o.value]
                          )
                        }
                        className={cn(
                          "rounded-full border px-3 py-1.5 text-[12.5px] font-semibold",
                          on
                            ? "border-primary bg-[#EFF6FF] text-primary"
                            : "border-border text-muted"
                        )}
                      >
                        {o.label}
                      </button>
                    );
                  })}
                </div>
              </Field>
            )}

            <Field>
              <Label htmlFor="edge-type">Then</Label>
              <Select
                id="edge-type"
                value={edgeType}
                onChange={(e) => setEdgeType(e.target.value as DomesticEdgeType)}
              >
                {DOMESTIC_EDGE_TYPES.map((t) => (
                  <option key={t} value={t}>
                    {EDGE_TYPE_LABELS[t]}
                  </option>
                ))}
              </Select>
            </Field>

            <Field>
              <Label htmlFor="edge-target">
                Question{edgeType === "terminate" ? " (optional)" : ""}
              </Label>
              <Select
                id="edge-target"
                value={toQuestionId}
                onChange={(e) => setToQuestionId(e.target.value)}
              >
                {edgeType === "terminate" && <option value="">— none —</option>}
                {targets.map((t) => (
                  <option key={t.id} value={t.id}>
                    #{t.code} {t.prompt.slice(0, 60)}
                    {t.status !== "published" ? ` (${t.status})` : ""}
                  </option>
                ))}
              </Select>
            </Field>

            <Field>
              <Label htmlFor="edge-priority">Priority</Label>
              <Input
                id="edge-priority"
                type="number"
                min={0}
                value={priority}
                onChange={(e) => setPriority(e.target.value)}
              />
            </Field>
          </div>

          {error && <p className="mb-3 text-sm text-danger">{error}</p>}

          <Button
            type="button"
            size="sm"
            loading={busy === "add"}
            disabled={edgeType !== "terminate" && !toQuestionId}
            onClick={handleAdd}
          >
            Add rule
          </Button>
        </div>
      )}
    </Card>
  );
}
