// ============================================================
// LEARNING HUB — pediatric education, pearls, and self-assessment
// quizzes. Minimum-viable port:
//
//   • Search box (keyword, posts to /api/learning/search)
//   • Category pills (/api/learning/categories) filter the feed
//   • Feed list (/api/learning/feed or /category/:slug depending on filter)
//   • Viewer (body rendered as pre-wrap text for now — rich HTML via
//     DOMPurify / Markdown lands as a follow-up; presentations link to
//     the legacy /#learning/:slug view since Marp rendering is its own port)
//   • Quiz (single / multi / true_false) + results with explanations
//   • Per-user progress list (last 5 attempts)
//
// Endpoints all live in src/routes/learningHub.ts at /api/learning/*.
// ============================================================

import { useState } from 'react';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { api } from '@/lib/api';
import type {
  LearningCategoriesOk,
  LearningCategory,
  LearningFeedListOk,
  LearningFeedRow,
  LearningContentOk,
  LearningContentFull,
  LearningQuestion,
  QuizAnswer,
  QuizSubmitOk,
} from '@/shared/types';

const card = 'rounded-lg border border-border bg-card p-5 space-y-3';
const pill = 'px-3 py-1 rounded-full text-xs font-medium border transition-colors cursor-pointer';
const input = 'w-full rounded-md border border-input bg-background px-3 py-2 text-sm';
const btnPrimary = 'rounded-md bg-primary text-primary-foreground px-3 py-2 text-sm font-medium disabled:opacity-50';
const btnGhost = 'rounded-md border border-border px-3 py-2 text-sm disabled:opacity-50';

function typeBadge(t: string) {
  switch (t) {
    case 'quiz':         return 'Quiz';
    case 'pearl':        return 'Pearl';
    case 'presentation': return 'Slides';
    default:             return 'Article';
  }
}

// ── Feed ────────────────────────────────────────────────────
function FeedCard({ row, onOpen }: { row: LearningFeedRow; onOpen: () => void }) {
  return (
    <button
      type="button"
      onClick={onOpen}
      className="w-full text-left rounded-lg border border-border bg-card hover:bg-muted/60 p-4 transition-colors"
      data-testid={'lh-feed-item-' + row.slug}
    >
      <div className="flex items-center gap-2 text-xs text-muted-foreground uppercase tracking-wide mb-1">
        <span className="font-semibold">{typeBadge(row.content_type)}</span>
        {row.category_name && <span>· {row.category_name}</span>}
        {row.question_count ? <span>· {row.question_count} Q</span> : null}
      </div>
      <div className="text-sm font-semibold">{row.title}</div>
      {row.subject && <div className="text-xs text-muted-foreground mt-0.5 truncate">{row.subject}</div>}
    </button>
  );
}

function Feed({
  filter,
  query,
  onOpen,
}: {
  filter: string; // category slug or '' for all
  query: string;
  onOpen: (slug: string) => void;
}) {
  const key: unknown[] =
    query
      ? ['learning-search', query]
      : filter
      ? ['learning-category', filter]
      : ['learning-feed'];

  const { data, isLoading, error } = useQuery<LearningFeedListOk>({
    queryKey: key,
    queryFn: () => {
      if (query) return api.get<LearningFeedListOk>('/api/learning/search?q=' + encodeURIComponent(query));
      if (filter)
        return api.get<LearningFeedListOk & { category?: LearningCategory }>(
          '/api/learning/category/' + encodeURIComponent(filter),
        );
      return api.get<LearningFeedListOk>('/api/learning/feed?limit=30');
    },
  });

  if (isLoading) return <div className="text-sm text-muted-foreground">Loading…</div>;
  if (error) return <div className="text-sm text-destructive">{(error as Error).message}</div>;
  const rows = data?.content || [];
  if (rows.length === 0)
    return <div className="text-sm text-muted-foreground italic py-4">No content found.</div>;
  return (
    <div className="grid grid-cols-1 sm:grid-cols-2 gap-3" data-testid="lh-feed">
      {rows.map((r) => <FeedCard key={r.id} row={r} onOpen={() => onOpen(r.slug)} />)}
    </div>
  );
}

// ── Viewer + Quiz ───────────────────────────────────────────
type AnswerMap = Record<number, { optionId?: number; optionIds: Set<number> }>;
function emptyAnswers(questions: LearningQuestion[]): AnswerMap {
  const m: AnswerMap = {};
  for (const q of questions) m[q.id] = { optionIds: new Set() };
  return m;
}

function Quiz({
  content,
  onReset,
}: {
  content: LearningContentFull;
  onReset: () => void;
}) {
  const qc = useQueryClient();
  const [answers, setAnswers] = useState<AnswerMap>(() => emptyAnswers(content.questions));
  const [result, setResult] = useState<QuizSubmitOk | null>(null);
  const [error, setError] = useState<string | null>(null);

  const submit = useMutation({
    mutationFn: (body: { contentId: number; answers: QuizAnswer[] }) =>
      api.post<QuizSubmitOk>('/api/learning/submit-quiz', body),
    onSuccess: (data) => {
      setResult(data);
      // Refresh progress list the next time the viewer opens.
      qc.invalidateQueries({ queryKey: ['learning-content', content.slug] });
    },
    onError: (e: Error) => setError(e.message || 'Submit failed'),
  });

  function onSubmit(e: React.FormEvent) {
    e.preventDefault();
    setError(null);
    const payload: QuizAnswer[] = content.questions.map((q) => {
      const a = answers[q.id];
      if (q.question_type === 'multi') {
        return { questionId: q.id, optionIds: Array.from(a?.optionIds || []) };
      }
      return { questionId: q.id, optionId: a?.optionId ?? null };
    });
    submit.mutate({ contentId: content.id, answers: payload });
  }

  function selectSingle(q: LearningQuestion, optionId: number) {
    setAnswers((prev) => ({ ...prev, [q.id]: { optionId, optionIds: new Set() } }));
  }
  function toggleMulti(q: LearningQuestion, optionId: number) {
    setAnswers((prev) => {
      const s = new Set(prev[q.id]?.optionIds || []);
      if (s.has(optionId)) s.delete(optionId);
      else s.add(optionId);
      return { ...prev, [q.id]: { optionIds: s } };
    });
  }

  if (result) {
    const color =
      result.percentage >= 80 ? 'bg-green-600'
      : result.percentage >= 50 ? 'bg-amber-500'
      : 'bg-destructive';
    return (
      <section className={card} data-testid="lh-quiz-results">
        <div className="flex items-center gap-3">
          <h3 className="text-base font-semibold">Results</h3>
          <span
            className={'px-2 py-0.5 rounded text-xs font-semibold text-white ' + color}
            data-testid="lh-quiz-score"
          >
            {result.score}/{result.total} ({result.percentage}%)
          </span>
        </div>
        <div className="space-y-3">
          {result.results.map((r, idx) => (
            <div key={r.questionId} className="rounded-md border border-border p-3 bg-muted/30">
              <div className="text-sm font-medium">
                <span className={r.isCorrect ? 'text-green-600' : 'text-destructive'}>
                  {r.isCorrect ? '✓' : '✗'}
                </span>{' '}
                Q{idx + 1}: {r.questionText}
              </div>
              {!r.isCorrect && r.correctOptionText && (
                <div className="text-xs text-green-700 mt-1">
                  <strong>Correct:</strong> {r.correctOptionText}
                </div>
              )}
              {!r.isCorrect && r.selectedExplanation && (
                <div className="text-xs text-destructive mt-1">
                  <strong>Why incorrect:</strong> {r.selectedExplanation}
                </div>
              )}
              {r.generalExplanation && (
                <div className="text-xs text-muted-foreground mt-1">{r.generalExplanation}</div>
              )}
            </div>
          ))}
        </div>
        <div className="flex gap-2">
          <button
            type="button"
            className={btnGhost}
            onClick={() => {
              setResult(null);
              setAnswers(emptyAnswers(content.questions));
            }}
          >
            Retake
          </button>
          <button type="button" className={btnPrimary} onClick={onReset}>Back to Feed</button>
        </div>
      </section>
    );
  }

  return (
    <section className={card} data-testid="lh-quiz">
      <div className="flex items-center justify-between">
        <h3 className="text-base font-semibold">Quiz</h3>
        <span className="text-xs text-muted-foreground">
          {content.questions.length} question{content.questions.length === 1 ? '' : 's'}
        </span>
      </div>
      <form onSubmit={onSubmit} className="space-y-4">
        {content.questions.map((q, idx) => {
          const isMulti = q.question_type === 'multi';
          const typeLabel =
            q.question_type === 'true_false' ? 'True / False'
            : isMulti ? 'Multiple Select'
            : 'Single Choice';
          return (
            <div key={q.id} className="rounded-md border border-border p-3 space-y-2 bg-muted/30">
              <div className="flex items-center justify-between text-xs text-muted-foreground">
                <span className="font-semibold">Q{idx + 1}</span>
                <span>{typeLabel}</span>
              </div>
              <div className="text-sm font-medium">{q.question_text}</div>
              {isMulti && (
                <div className="text-xs text-muted-foreground italic">Select all that apply</div>
              )}
              <div className="space-y-1">
                {q.options.map((opt) => {
                  const a = answers[q.id];
                  const checked = isMulti
                    ? a?.optionIds.has(opt.id) === true
                    : a?.optionId === opt.id;
                  return (
                    <label
                      key={opt.id}
                      className="flex items-start gap-2 text-sm cursor-pointer hover:bg-muted/50 rounded px-2 py-1"
                    >
                      <input
                        type={isMulti ? 'checkbox' : 'radio'}
                        name={'q-' + q.id}
                        checked={checked}
                        onChange={() =>
                          isMulti ? toggleMulti(q, opt.id) : selectSingle(q, opt.id)
                        }
                        className="mt-0.5"
                      />
                      <span>{opt.option_text}</span>
                    </label>
                  );
                })}
              </div>
            </div>
          );
        })}
        {error && <div className="text-sm text-destructive">{error}</div>}
        <button
          type="submit"
          className={btnPrimary}
          disabled={submit.isPending}
          data-testid="btn-lh-submit-quiz"
        >
          {submit.isPending ? 'Submitting…' : 'Submit Answers'}
        </button>
      </form>
    </section>
  );
}

function ContentViewer({ slug, onBack }: { slug: string; onBack: () => void }) {
  const { data, isLoading, error } = useQuery<LearningContentOk>({
    queryKey: ['learning-content', slug],
    queryFn: () => api.get<LearningContentOk>('/api/learning/content/' + encodeURIComponent(slug)),
  });

  if (isLoading) return <div className="text-sm text-muted-foreground">Loading…</div>;
  if (error) return <div className="text-sm text-destructive">{(error as Error).message}</div>;
  if (!data) return null;
  const c = data.content;

  return (
    <div className="space-y-4">
      <button type="button" className={btnGhost} onClick={onBack} data-testid="btn-lh-back">
        ← Back to Feed
      </button>

      <section className={card} data-testid="lh-viewer">
        <div className="flex items-center justify-between gap-4">
          <h2 className="text-xl font-semibold" data-testid="lh-viewer-title">{c.title}</h2>
          <span className="text-xs text-muted-foreground">
            {typeBadge(c.content_type)}
            {c.category_name ? ' · ' + c.category_name : ''}
            {c.author_name ? ' · ' + c.author_name : ''}
          </span>
        </div>

        {c.content_type === 'presentation' ? (
          <div className="text-center py-8 space-y-3 bg-muted/30 rounded-md">
            <div className="text-4xl">📊</div>
            <div className="text-sm font-medium">{c.title}</div>
            <div className="text-xs text-muted-foreground">
              Slide rendering lives in the legacy viewer.
            </div>
            <a
              href={'/#learning/' + encodeURIComponent(c.slug)}
              className={btnPrimary + ' inline-block'}
              rel="noreferrer"
            >
              Open in legacy viewer
            </a>
          </div>
        ) : (
          <div
            className="whitespace-pre-wrap text-sm leading-relaxed"
            data-testid="lh-viewer-body"
          >
            {c.body || ''}
          </div>
        )}
      </section>

      {c.progress && c.progress.length > 0 && (
        <section className={card}>
          <h3 className="text-base font-semibold">Your past attempts</h3>
          <div className="space-y-1 text-sm">
            {c.progress.map((p, i) => {
              const pct = p.total > 0 ? Math.round((p.score / p.total) * 100) : 0;
              const color = pct >= 70 ? 'text-green-600' : 'text-amber-600';
              return (
                <div key={i} className="flex justify-between border-b border-border py-1">
                  <span>{new Date(p.completed_at).toLocaleDateString()}</span>
                  <span className={'font-semibold ' + color}>
                    {p.score}/{p.total} ({pct}%)
                  </span>
                </div>
              );
            })}
          </div>
        </section>
      )}

      {c.questions && c.questions.length > 0 && <Quiz content={c} onReset={onBack} />}
    </div>
  );
}

// ── Page shell ───────────────────────────────────────────────
export default function Learning() {
  const [query, setQuery] = useState('');
  const [filter, setFilter] = useState<string>('');
  const [activeSlug, setActiveSlug] = useState<string | null>(null);

  const { data: cats } = useQuery<LearningCategoriesOk>({
    queryKey: ['learning-categories'],
    queryFn: () => api.get<LearningCategoriesOk>('/api/learning/categories'),
  });

  if (activeSlug) {
    return (
      <div className="max-w-4xl mx-auto p-6">
        <ContentViewer slug={activeSlug} onBack={() => setActiveSlug(null)} />
      </div>
    );
  }

  return (
    <div className="max-w-4xl mx-auto p-6 space-y-4">
      <header>
        <h1 className="text-2xl font-semibold">Learning Hub</h1>
        <p className="text-sm text-muted-foreground">
          Pediatric education, clinical pearls, and self-assessment quizzes.
        </p>
      </header>

      <div className={card}>
        <input
          type="search"
          className={input}
          placeholder="Search topics, subjects…"
          value={query}
          onChange={(e) => setQuery(e.target.value)}
          data-testid="lh-search"
        />
      </div>

      <div className="flex flex-wrap gap-2" data-testid="lh-categories">
        <button
          type="button"
          onClick={() => setFilter('')}
          className={
            pill +
            (filter === '' ? ' bg-primary text-primary-foreground border-primary' : ' bg-muted hover:bg-muted/80')
          }
        >
          All
        </button>
        {cats?.categories.map((cat) => (
          <button
            key={cat.id}
            type="button"
            onClick={() => setFilter(cat.slug)}
            className={
              pill +
              (filter === cat.slug
                ? ' bg-primary text-primary-foreground border-primary'
                : ' bg-muted hover:bg-muted/80')
            }
            data-testid={'lh-cat-' + cat.slug}
          >
            {cat.name}
          </button>
        ))}
      </div>

      <Feed filter={filter} query={query.trim()} onOpen={(slug) => setActiveSlug(slug)} />
    </div>
  );
}
