import { useMemo, useState } from "react";
import { useTranslation } from "react-i18next";
import {
  BookOpen,
  Calendar,
  ClipboardList,
  Headphones,
  Image as ImageIcon,
  Library,
  Link2,
  MessageSquare,
  Mic,
  Music,
  PenSquare,
  Sparkles,
  Type,
  Video,
  type LucideIcon,
} from "lucide-react";

import {
  Accordion,
  AccordionContent,
  AccordionItem,
  AccordionTrigger,
} from "@/components/ui/accordion";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
} from "@/components/ui/card";
import {
  HoverCard,
  HoverCardContent,
  HoverCardTrigger,
} from "@/components/ui/hover-card";
import { withAuthQuery } from "@/lib/api-client";
import MaterialBookView, {
  SkillBadge,
} from "@/components/coursePlan/MaterialBookView";
import type { WorkbookMode } from "@/components/coursePlan/InteractiveWorkbook";
import type {
  CoursePlan,
  CoursePlanMaterial,
  CoursePlanMedia,
  CoursePlanWeek,
} from "@/types";

const SKILL_ICONS: Record<string, LucideIcon> = {
  reading: BookOpen,
  writing: PenSquare,
  listening: Headphones,
  speaking: Mic,
  grammar: Type,
  vocabulary: Library,
  integrated: MessageSquare,
};

/**
 * Read-only renderer for a course plan that BOTH the student page and
 * the admin "View as Student" preview share. The only difference is
 * the workbook `mode`:
 *
 * - `mode="student"` → answers persist server-side (real attempts).
 * - `mode="preview"` → InteractiveWorkbook runs in preview mode (no
 *   persistence) and surfaces an "Show answer key" toggle so admins
 *   can verify the v2 generator's output.
 *
 * Materials are rendered through `MaterialBookView`, which dispatches
 * `interactive_workbook` materials into the live workbook component.
 */
export interface PlanReaderProps {
  plan: CoursePlan;
  mode?: WorkbookMode;
  /** Heading level for accessibility — admins use this inside their own
   *  Card; students use it as the page's main grid block. Defaults to 'h3'. */
  headingClassName?: string;
}

export default function PlanReader({ plan, mode = "student" }: PlanReaderProps) {
  const { t } = useTranslation();
  const materialsByWeek = useMemo(() => {
    const map = new Map<number, CoursePlanMaterial[]>();
    if (!plan.materials) return map;
    for (const m of plan.materials) {
      const list = map.get(m.week_number) ?? [];
      list.push(m);
      map.set(m.week_number, list);
    }
    return map;
  }, [plan.materials]);

  return (
    <div className="space-y-6">
      <Card>
        <CardHeader>
          <div className="flex items-start justify-between gap-3 flex-wrap">
            <div className="flex-1 min-w-0">
              <CardTitle className="text-2xl">{plan.name}</CardTitle>
              {plan.description && (
                <CardDescription className="max-w-3xl">
                  {plan.description}
                </CardDescription>
              )}
            </div>
            <div className="flex gap-2 flex-wrap">
              <Badge variant="secondary" className="uppercase">
                {plan.cefr_level}
              </Badge>
              <Badge variant="outline">
                {t("coursePlan.weeksCount", { count: plan.total_weeks })}
              </Badge>
              <Badge variant="outline">
                {t("coursePlan.hoursPerWeek", {
                  count: plan.contact_hours_per_week,
                })}
              </Badge>
            </div>
          </div>
          {plan.assignment && (
            <p className="text-xs text-muted-foreground flex items-center gap-1.5">
              <Calendar className="h-3.5 w-3.5" />
              {plan.assignment.due_date
                ? t("coursePlan.student.due", { date: plan.assignment.due_date })
                : t("coursePlan.student.noDue")}
              {plan.assignment.assigned_by_name && (
                <span>
                  ·{" "}
                  {t("coursePlan.student.assignedBy", {
                    name: plan.assignment.assigned_by_name,
                  })}
                </span>
              )}
            </p>
          )}
          {plan.assignment?.message && (
            <p className="text-sm bg-muted/40 rounded-md px-3 py-2 mt-2">
              {plan.assignment.message}
            </p>
          )}
        </CardHeader>
      </Card>

      {plan.objectives && plan.objectives.length > 0 && (
        <Card>
          <CardHeader>
            <CardTitle className="text-base flex items-center gap-2">
              <ClipboardList className="h-4 w-4 text-primary" />
              {t("coursePlan.sections.objectives")}
            </CardTitle>
          </CardHeader>
          <CardContent>
            <ol className="list-decimal list-inside space-y-1 text-sm">
              {plan.objectives.map((o, i) => (
                <li key={i}>{o}</li>
              ))}
            </ol>
          </CardContent>
        </Card>
      )}

      {plan.weeks && plan.weeks.length > 0 && (
        <Card>
          <CardHeader>
            <CardTitle className="text-base flex items-center gap-2">
              <Sparkles className="h-4 w-4 text-primary" />
              {t("coursePlan.sections.delivery")}
            </CardTitle>
            <CardDescription>{t("coursePlan.deliveryHint")}</CardDescription>
          </CardHeader>
          <CardContent>
            <Accordion type="multiple" className="w-full">
              {plan.weeks.map((w) => (
                <ReaderWeek
                  key={w.id}
                  week={w}
                  materials={materialsByWeek.get(w.week_number) ?? []}
                  mode={mode}
                />
              ))}
            </Accordion>
          </CardContent>
        </Card>
      )}
    </div>
  );
}

function ReaderWeek({
  week,
  materials,
  mode,
}: {
  week: CoursePlanWeek;
  materials: CoursePlanMaterial[];
  mode: WorkbookMode;
}) {
  const { t } = useTranslation();
  const [skillFilter, setSkillFilter] = useState<string>("all");
  const skills = useMemo(
    () => Array.from(new Set(materials.map((m) => m.skill))).sort(),
    [materials],
  );
  const filteredMaterials = useMemo(
    () =>
      materials.filter(
        (m) => skillFilter === "all" || m.skill === skillFilter,
      ),
    [materials, skillFilter],
  );
  return (
    <AccordionItem value={String(week.week_number)}>
      <AccordionTrigger className="text-left">
        <div className="flex-1 flex items-center gap-3 min-w-0">
          <Badge variant="outline" className="shrink-0">
            {t("coursePlan.weekN", { n: week.week_number })}
          </Badge>
          <div className="flex-1 min-w-0">
            <div className="font-medium truncate">
              {week.focus || week.unit || "—"}
            </div>
            {week.date_label && (
              <div className="text-xs text-muted-foreground truncate">
                {week.date_label}
              </div>
            )}
          </div>
        </div>
      </AccordionTrigger>
      <AccordionContent className="space-y-3">
        {skills.length > 0 && (
          <div className="flex items-center gap-1 flex-wrap">
            <Button
              size="sm"
              variant={skillFilter === "all" ? "default" : "outline"}
              onClick={() => setSkillFilter("all")}
            >
              {t("common.all", "All")}
            </Button>
            {skills.map((s) => (
              <Button
                key={s}
                size="sm"
                variant={skillFilter === s ? "default" : "outline"}
                onClick={() => setSkillFilter(s)}
                className="capitalize"
              >
                {s}
              </Button>
            ))}
          </div>
        )}
        {materials.length === 0 && (
          <p className="text-sm italic text-muted-foreground">
            {t("coursePlan.media.noMedia")}
          </p>
        )}
        {filteredMaterials.map((m) => (
          <ReaderMaterial key={m.id} material={m} mode={mode} />
        ))}
      </AccordionContent>
    </AccordionItem>
  );
}

function ReaderMaterial({
  material,
  mode,
}: {
  material: CoursePlanMaterial;
  mode: WorkbookMode;
}) {
  const { t } = useTranslation();
  const Icon = SKILL_ICONS[material.skill] ?? ClipboardList;
  return (
    <Card>
      <CardHeader className="pb-2">
        <div className="flex items-center gap-2 flex-wrap">
          <Icon className="h-4 w-4 text-primary" />
          <CardTitle className="text-base flex-1 min-w-0">
            {material.title}
          </CardTitle>
          <Badge variant="outline" className="text-[10px]">
            {t(
              `coursePlan.materialType.${material.material_type}`,
              material.material_type,
            )}
          </Badge>
          <SkillBadge skill={material.skill} />
          <GroundingBadge material={material} />
        </div>
        {material.summary && (
          <CardDescription>{material.summary}</CardDescription>
        )}
        {material.share_date && (
          <CardDescription>
            {t("coursePlan.shareDate", "Share date")}: {material.share_date}
          </CardDescription>
        )}
      </CardHeader>
      <CardContent className="space-y-3">
        {(material.media ?? []).map((m) => (
          <ReaderMediaTile key={m.id} media={m} />
        ))}
        <MaterialBookView material={material} mode={mode} />
      </CardContent>
    </Card>
  );
}

function ReaderMediaTile({ media }: { media: CoursePlanMedia }) {
  const url = withAuthQuery(media.preview_url || media.download_url || "");
  if (!url) return null;
  return (
    <div className="rounded-md border bg-muted/20 p-2 space-y-2">
      <div className="flex items-center gap-2">
        {media.kind === "audio" && <Music className="h-4 w-4" />}
        {media.kind === "image" && <ImageIcon className="h-4 w-4" />}
        {media.kind === "video" && <Video className="h-4 w-4" />}
        <span className="capitalize text-xs text-muted-foreground">
          {media.kind}
        </span>
      </div>
      {media.kind === "audio" && <audio src={url} controls className="w-full" />}
      {media.kind === "image" && (
        <img
          src={url}
          alt={media.title}
          className="w-full rounded-md max-h-72 object-contain bg-muted/30"
        />
      )}
      {media.kind === "video" && (
        <video src={url} controls className="w-full rounded-md max-h-72" />
      )}
    </div>
  );
}

/** Pill that surfaces RAG / extraction provenance for one material. */
export function GroundingBadge({ material }: { material: CoursePlanMaterial }) {
  const grounded = material.grounded_on ?? [];
  const extracted = material.extracted_from ?? null;
  if (!grounded.length && !extracted) return null;
  const total =
    grounded.reduce((acc, g) => acc + (g.chunks_used || 0), 0) +
    (extracted ? 1 : 0);
  return (
    <HoverCard openDelay={150}>
      <HoverCardTrigger asChild>
        <Badge variant="secondary" className="cursor-help">
          <Link2 className="mr-1 h-3 w-3" />
          Grounded on {total} reference{total === 1 ? "" : "s"}
        </Badge>
      </HoverCardTrigger>
      <HoverCardContent className="w-72 text-xs">
        {grounded.length > 0 && (
          <div className="space-y-1">
            <div className="font-medium text-sm">RAG sources</div>
            <ul className="space-y-1">
              {grounded.map((g) => (
                <li key={g.source_id} className="flex justify-between gap-2">
                  <span className="truncate">{g.title || `Source #${g.source_id}`}</span>
                  <span className="text-muted-foreground">{g.chunks_used} chunk(s)</span>
                </li>
              ))}
            </ul>
          </div>
        )}
        {extracted && (
          <div className={grounded.length ? "mt-3 border-t pt-2" : ""}>
            <div className="font-medium text-sm">Extracted from</div>
            <div className="text-muted-foreground">
              {extracted.source_title || `Source #${extracted.source_id}`}
              {extracted.page_hint ? ` · ${extracted.page_hint}` : ""}
            </div>
            {extracted.topic_keywords && extracted.topic_keywords.length > 0 && (
              <div className="mt-1 text-muted-foreground">
                Topics: {extracted.topic_keywords.slice(0, 5).join(", ")}
              </div>
            )}
          </div>
        )}
      </HoverCardContent>
    </HoverCard>
  );
}
