import { Badge } from "@/components/ui/badge";
import { cn } from "@/lib/utils";
import type { CoursePlanMaterial, WorkbookBody } from "@/types";

import InteractiveWorkbook, { type WorkbookMode } from "./InteractiveWorkbook";

export const SKILL_STYLE: Record<string, string> = {
  reading: "bg-blue-100 text-blue-800 border-blue-200",
  writing: "bg-purple-100 text-purple-800 border-purple-200",
  listening: "bg-emerald-100 text-emerald-800 border-emerald-200",
  speaking: "bg-amber-100 text-amber-800 border-amber-200",
  grammar: "bg-rose-100 text-rose-800 border-rose-200",
  vocabulary: "bg-cyan-100 text-cyan-800 border-cyan-200",
  integrated: "bg-slate-100 text-slate-800 border-slate-200",
};

export function SkillBadge({ skill }: { skill: string }) {
  return (
    <Badge
      variant="outline"
      className={cn("capitalize border", SKILL_STYLE[skill] ?? SKILL_STYLE.integrated)}
    >
      {skill || "integrated"}
    </Badge>
  );
}

function renderAny(value: unknown): React.ReactNode {
  if (value == null) return null;
  if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
    return <p className="leading-7">{String(value)}</p>;
  }
  if (Array.isArray(value)) {
    if (value.length === 0) return null;
    return (
      <ul className="list-disc ps-5 space-y-1">
        {value.map((item, idx) => (
          <li key={idx}>{renderAny(item)}</li>
        ))}
      </ul>
    );
  }
  if (typeof value === "object") {
    const entries = Object.entries(value as Record<string, unknown>);
    return (
      <div className="space-y-3">
        {entries.map(([k, v]) => (
          <div key={k}>
            <h5 className="font-medium capitalize text-sm text-muted-foreground mb-1">
              {k.replace(/_/g, " ")}
            </h5>
            <div className="text-sm">{renderAny(v)}</div>
          </div>
        ))}
      </div>
    );
  }
  return null;
}

type MaterialForBook = Pick<
  CoursePlanMaterial,
  "id" | "plan_id" | "body" | "body_text" | "material_type" | "title" | "summary"
>;

export default function MaterialBookView({
  material,
  mode = "student",
}: {
  // The legacy callsites only pass body/body_text/material_type, so we
  // tolerate that by making id/plan_id optional in the prop type even
  // though the types/index file marks them as required. Required props
  // are validated at runtime when interactive_workbook is dispatched.
  material: Partial<MaterialForBook> &
    Pick<CoursePlanMaterial, "body" | "body_text" | "material_type">;
  mode?: WorkbookMode;
}) {
  const body = material.body ?? {};
  const hasStructured = Object.keys(body).length > 0;

  // Dispatch to the interactive renderer for workbook materials. The
  // skill-bodied workbooks (grammar/vocabulary that embed their own
  // `interactive_workbook` block) render via the generic walker AND
  // the embedded workbook below for the exercises portion.
  if (
    material.material_type === "interactive_workbook" &&
    typeof material.id === "number" &&
    typeof material.plan_id === "number"
  ) {
    return (
      <InteractiveWorkbook
        material={material as MaterialForBook}
        mode={mode}
      />
    );
  }

  // For grammar / vocabulary that embed an interactive workbook inside
  // their body, we render the prose first and then the workbook UI so
  // students can practise without leaving the lesson.
  const embeddedWorkbook = (body as { interactive_workbook?: WorkbookBody })
    .interactive_workbook;
  const hasEmbedded =
    embeddedWorkbook &&
    Array.isArray(embeddedWorkbook.exercises) &&
    embeddedWorkbook.exercises.length > 0 &&
    typeof material.id === "number" &&
    typeof material.plan_id === "number";

  return (
    <div className="rounded-lg border bg-background/70 p-4 space-y-4">
      {hasStructured ? (
        renderAny(stripEmbedded(body))
      ) : (
        <p className="text-sm whitespace-pre-wrap leading-7">
          {material.body_text || "No content available yet."}
        </p>
      )}

      {hasEmbedded && (
        <div className="border-t pt-3">
          <div className="text-sm font-medium mb-2">Practice</div>
          <InteractiveWorkbook
            material={material as MaterialForBook}
            bodyOverride={embeddedWorkbook!}
            mode={mode}
          />
        </div>
      )}
    </div>
  );
}

function stripEmbedded(body: Record<string, unknown>): Record<string, unknown> {
  if (!body || typeof body !== "object") return body;
  if (!("interactive_workbook" in body)) return body;
  const { interactive_workbook: _drop, ...rest } = body;
  return rest;
}
