/**
 * Technique page detail view with version switching.
 *
 * Fetches a single technique by slug. When historical versions exist,
 * shows a version switcher that lets admins view previous snapshots
 * with pipeline metadata (prompt hashes, model config).
 */

import { useEffect, useState } from "react";
import { Link, useParams } from "react-router-dom";
import {
  fetchTechnique,
  fetchTechniqueVersions,
  fetchTechniqueVersion,
  type TechniquePageDetail as TechniqueDetail,
  type TechniquePageVersionSummary,
  type TechniquePageVersionDetail,
  type BodySectionV2,
} from "../api/public-client";
import ReportIssueModal from "../components/ReportIssueModal";
import CopyLinkButton from "../components/CopyLinkButton";
import CreatorAvatar from "../components/CreatorAvatar";
import TableOfContents, { slugify } from "../components/TableOfContents";
import { parseCitations } from "../utils/citations";
import { useDocumentTitle } from "../hooks/useDocumentTitle";

function formatTime(seconds: number): string {
  const m = Math.floor(seconds / 60);
  const s = Math.floor(seconds % 60);
  return `${m}:${s.toString().padStart(2, "0")}`;
}

function formatDate(iso: string): string {
  return new Date(iso).toLocaleDateString("en-US", {
    year: "numeric",
    month: "short",
    day: "numeric",
    hour: "2-digit",
    minute: "2-digit",
  });
}

/** Extract the displayable fields from a version snapshot, matching TechniqueDetail shape. */
function snapshotToOverlay(snapshot: Record<string, unknown>) {
  // body_sections can be either list (v2) or dict (v1)
  let bodySections: BodySectionV2[] | Record<string, unknown> | undefined;
  if (Array.isArray(snapshot.body_sections)) {
    bodySections = snapshot.body_sections as BodySectionV2[];
  } else if (typeof snapshot.body_sections === "object" && snapshot.body_sections !== null) {
    bodySections = snapshot.body_sections as Record<string, unknown>;
  }

  return {
    title: typeof snapshot.title === "string" ? snapshot.title : undefined,
    summary: typeof snapshot.summary === "string" ? snapshot.summary : undefined,
    topic_category:
      typeof snapshot.topic_category === "string"
        ? snapshot.topic_category
        : undefined,
    topic_tags: Array.isArray(snapshot.topic_tags)
      ? (snapshot.topic_tags as string[])
      : undefined,
    body_sections: bodySections,
    body_sections_format:
      typeof snapshot.body_sections_format === "string"
        ? snapshot.body_sections_format
        : undefined,
    signal_chains: Array.isArray(snapshot.signal_chains)
      ? (snapshot.signal_chains as unknown[])
      : undefined,
    plugins: Array.isArray(snapshot.plugins)
      ? (snapshot.plugins as string[])
      : undefined,
    source_quality:
      typeof snapshot.source_quality === "string"
        ? snapshot.source_quality
        : undefined,
  };
}

export default function TechniquePage() {
  const { slug } = useParams<{ slug: string }>();
  const [technique, setTechnique] = useState<TechniqueDetail | null>(null);
  const [loading, setLoading] = useState(true);
  const [notFound, setNotFound] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [showReport, setShowReport] = useState(false);

  useDocumentTitle(technique ? `${technique.title} — Chrysopedia` : "Chrysopedia");

  // Version switching
  const [versions, setVersions] = useState<TechniquePageVersionSummary[]>([]);
  const [selectedVersion, setSelectedVersion] = useState<string>("current");
  const [versionDetail, setVersionDetail] =
    useState<TechniquePageVersionDetail | null>(null);
  const [versionLoading, setVersionLoading] = useState(false);

  // Load technique + version list
  useEffect(() => {
    if (!slug) return;

    let cancelled = false;
    setLoading(true);
    setNotFound(false);
    setError(null);
    setSelectedVersion("current");
    setVersionDetail(null);
    setVersions([]);

    void (async () => {
      try {
        const data = await fetchTechnique(slug);
        if (!cancelled) {
          setTechnique(data);
          // Load versions if any exist
          if (data.version_count > 0) {
            try {
              const vRes = await fetchTechniqueVersions(slug);
              if (!cancelled) setVersions(vRes.items);
            } catch {
              // Non-critical — version list fails silently
            }
          }
        }
      } catch (err) {
        if (!cancelled) {
          if (err instanceof Error && err.message.includes("404")) {
            setNotFound(true);
          } else {
            setError(
              err instanceof Error ? err.message : "Failed to load technique",
            );
          }
        }
      } finally {
        if (!cancelled) setLoading(false);
      }
    })();

    return () => {
      cancelled = true;
    };
  }, [slug]);

  // Load version detail when selection changes
  useEffect(() => {
    if (!slug || selectedVersion === "current") {
      setVersionDetail(null);
      return;
    }

    let cancelled = false;
    setVersionLoading(true);

    void (async () => {
      try {
        const detail = await fetchTechniqueVersion(
          slug,
          Number(selectedVersion),
        );
        if (!cancelled) setVersionDetail(detail);
      } catch {
        if (!cancelled) setVersionDetail(null);
      } finally {
        if (!cancelled) setVersionLoading(false);
      }
    })();

    return () => {
      cancelled = true;
    };
  }, [slug, selectedVersion]);

  // Scroll to hash fragment after technique loads (key moments, section anchors, etc.)
  useEffect(() => {
    if (!technique) return;
    const hash = window.location.hash.slice(1);
    if (hash) {
      const el = document.getElementById(hash);
      if (el) {
        el.scrollIntoView({ behavior: "smooth", block: "start" });
      }
    }
  }, [technique]);

  if (loading) {
    return <div className="loading">Loading technique…</div>;
  }

  if (notFound) {
    return (
      <div className="technique-404">
        <h2>Technique Not Found</h2>
        <p>The technique &ldquo;{slug}&rdquo; doesn&rsquo;t exist.</p>
        <Link to="/" className="btn">
          Back to Home
        </Link>
      </div>
    );
  }

  if (error || !technique) {
    return (
      <div className="loading error-text">
        Error: {error ?? "Unknown error"}
      </div>
    );
  }

  // Overlay snapshot fields when viewing a historical version
  const isHistorical = selectedVersion !== "current" && versionDetail != null;
  const overlay = isHistorical
    ? snapshotToOverlay(versionDetail.content_snapshot)
    : null;

  const displayTitle = overlay?.title ?? technique.title;
  const displaySummary = overlay?.summary ?? technique.summary;
  const displayCategory = overlay?.topic_category ?? technique.topic_category;
  const displayTags = overlay?.topic_tags ?? technique.topic_tags;
  const displaySections = overlay?.body_sections ?? technique.body_sections;
  const displayFormat = overlay?.body_sections_format ?? technique.body_sections_format ?? "v1";
  const displayChains = overlay?.signal_chains ?? technique.signal_chains;
  const displayPlugins = overlay?.plugins ?? technique.plugins;
  const displayQuality = overlay?.source_quality ?? technique.source_quality;

  return (
    <article className="technique-page">
      {/* Back link */}
      <Link to="/" className="back-link">
        ← Back
      </Link>

      {/* Historical version banner */}
      {isHistorical && (
        <div className="technique-banner technique-banner--version">
          📋 Viewing version {versionDetail.version_number} from{" "}
          {formatDate(versionDetail.created_at)}
          <button
            className="btn btn--small btn--primary"
            style={{ marginLeft: "1rem" }}
            onClick={() => setSelectedVersion("current")}
          >
            Back to current
          </button>
        </div>
      )}

      {/* Unstructured content warning */}
      {displayQuality === "unstructured" && (
        <div className="technique-banner technique-banner--amber">
          ⚠ This technique was sourced from a livestream and may have less
          structured content.
        </div>
      )}

      <div className="technique-columns">
        <div className="technique-columns__main">
        <div className="technique-header__title-row">
            <h1 className="technique-header__title">{displayTitle} <CopyLinkButton /></h1>
            {displayCategory && (
              <span className={"badge badge--category badge--cat-" + (displayCategory?.toLowerCase().replace(/\s+/g, "-") ?? "")}>
                {displayCategory}
              </span>
            )}
          </div>
        {technique.creator_info && (
          <div className="technique-header__creator-block">
            <Link to={`/creators/${technique.creator_info.slug}`} className="technique-header__creator-link">
              <CreatorAvatar creatorId={String(technique.creator_info.slug)} name={technique.creator_info.name} size={22} />
              {technique.creator_info.name}
            </Link>
            {technique.creator_info.genres && technique.creator_info.genres.length > 0 && (
              <span className="technique-header__creator-genres">
                {technique.creator_info.genres.map((g) => (
                  <span key={g} className="pill pill--genre-small">{g}</span>
                ))}
              </span>
            )}
          </div>
        )}


        {/* Meta stats line */}
        <div className="technique-header__stats">
          {(() => {
            const sourceCount = new Set(
              technique.key_moments
                .map((km) => km.video_filename)
                .filter(Boolean),
            ).size;
            const momentCount = technique.key_moments.length;
            const updated = new Date(technique.updated_at).toLocaleDateString(
              "en-US",
              { year: "numeric", month: "short", day: "numeric" },
            );
            const parts = [
              `Compiled from ${sourceCount} source${sourceCount !== 1 ? "s" : ""}`,
              `${momentCount} key moment${momentCount !== 1 ? "s" : ""}`,
            ];
            if (technique.version_count > 0) {
              parts.push(
                `${technique.version_count} version${technique.version_count !== 1 ? "s" : ""}`,
              );
            }
            parts.push(`Last updated ${updated}`);
            return parts.join(" · ");
          })()}
        </div>

        {/* Version switcher */}
        <div className="technique-header__actions">
          {versions.length > 0 && (
            <div className="version-switcher">
              <label className="version-switcher__label">Version:</label>
              <select
                className="version-switcher__select"
                value={selectedVersion}
                onChange={(e) => setSelectedVersion(e.target.value)}
                disabled={versionLoading}
              >
                <option value="current">Current (live)</option>
                {versions.map((v) => (
                  <option key={v.version_number} value={String(v.version_number)}>
                    v{v.version_number} — {formatDate(v.created_at)}
                  </option>
                ))}
              </select>
              {versionLoading && (
                <span className="version-switcher__loading">Loading…</span>
              )}
            </div>
          )}

        </div>

      {/* Pipeline metadata for historical versions */}
      {isHistorical && versionDetail.pipeline_metadata && (
        <div className="version-metadata">
          <h4 className="version-metadata__title">Pipeline metadata (v{versionDetail.version_number})</h4>
          <div className="version-metadata__grid">
            {"model" in versionDetail.pipeline_metadata && (
              <div className="version-metadata__item">
                <span className="version-metadata__key">Model</span>
                <span className="version-metadata__value">
                  {String(versionDetail.pipeline_metadata.model)}
                </span>
              </div>
            )}
            {"captured_at" in versionDetail.pipeline_metadata && (
              <div className="version-metadata__item">
                <span className="version-metadata__key">Captured</span>
                <span className="version-metadata__value">
                  {formatDate(String(versionDetail.pipeline_metadata.captured_at))}
                </span>
              </div>
            )}
            {typeof versionDetail.pipeline_metadata.prompt_hashes === "object" &&
              versionDetail.pipeline_metadata.prompt_hashes !== null && (
                <div className="version-metadata__item version-metadata__item--wide">
                  <span className="version-metadata__key">Prompt hashes</span>
                  <div className="version-metadata__hashes">
                    {Object.entries(
                      versionDetail.pipeline_metadata.prompt_hashes as Record<
                        string,
                        string
                      >,
                    ).map(([file, hash]) => (
                      <div key={file} className="version-metadata__hash">
                        <span className="version-metadata__hash-file">
                          {file.replace(/^.*\//, "")}
                        </span>
                        <code className="version-metadata__hash-value">
                          {hash.slice(0, 12)}…
                        </code>
                      </div>
                    ))}
                  </div>
                </div>
              )}
          </div>
        </div>
      )}

      {/* Report modal */}
      {showReport && (
        <ReportIssueModal
          contentType="technique_page"
          contentId={technique.id}
          contentTitle={technique.title}
          onClose={() => setShowReport(false)}
        />
      )}


          {/* Tags + plugin pills — scoped to left column */}
          {((displayTags && displayTags.length > 0) || (displayPlugins && displayPlugins.length > 0)) && (
            <div className="technique-main__tags">
              {displayTags && displayTags.map((tag) => (
                <span key={tag} className="pill">
                  {tag}
                </span>
              ))}
              {displayPlugins && displayPlugins.length > 0 && displayPlugins.map((plugin) => (
                <span key={`plugin-${plugin}`} className="pill pill--plugin">
                  {plugin}
                </span>
              ))}
            </div>
          )}

          {/* Summary */}
      {displaySummary && (
        <section className="technique-summary">
          <p>{displaySummary}</p>
        </section>
      )}

      {/* Study guide prose — body_sections */}
      {displaySections &&
        (Array.isArray(displaySections) ? displaySections.length > 0 : Object.keys(displaySections).length > 0) && (
          <section className="technique-prose">
            {displayFormat === "v2" && Array.isArray(displaySections) ? (
              <>
                {(displaySections as BodySectionV2[]).map((section) => {
                  const sectionSlug = slugify(section.heading);
                  return (
                    <div key={sectionSlug} className="technique-prose__section" id={sectionSlug}>
                      <h2>{section.heading}</h2>
                      {section.content && (
                        <p>{parseCitations(section.content, technique.key_moments)}</p>
                      )}
                      {section.subsections.map((sub) => {
                        const subSlug = `${sectionSlug}--${slugify(sub.heading)}`;
                        return (
                          <div key={subSlug} className="technique-prose__subsection" id={subSlug}>
                            <h3>{sub.heading}</h3>
                            {sub.content && (
                              <p>{parseCitations(sub.content, technique.key_moments)}</p>
                            )}
                          </div>
                        );
                      })}
                    </div>
                  );
                })}
              </>
            ) : (
              /* V1 dict format — original rendering */
              Object.entries(displaySections as Record<string, unknown>).map(
                ([sectionTitle, content]: [string, unknown]) => (
                  <div key={sectionTitle} className="technique-prose__section">
                    <h2>{sectionTitle}</h2>
                    {typeof content === "string" ? (
                      <p>{content as string}</p>
                    ) : typeof content === "object" && content !== null ? (
                      <pre className="technique-prose__json">
                        {JSON.stringify(content, null, 2)}
                      </pre>
                    ) : (
                      <p>{String(content as string)}</p>
                    )}
                  </div>
                ),
              )
            )}
          </section>
        )}

        </div>
        <div className="technique-columns__sidebar">
          {/* Table of Contents — v2 pages only */}
          {displayFormat === "v2" && Array.isArray(displaySections) && (displaySections as BodySectionV2[]).length > 0 && (
            <TableOfContents sections={displaySections as BodySectionV2[]} />
          )}
          {/* Key moments (always from live data — not versioned) */}
      {technique.key_moments.length > 0 && (
        <section className="technique-moments">
          <h2>Key Moments</h2>
          <ol className="technique-moments__list">
            {technique.key_moments.map((km) => (
              <li key={km.id} id={`km-${km.id}`} className="technique-moment">
                <h3 className="technique-moment__title">{km.title}</h3>
                <div className="technique-moment__meta">
                  {km.video_filename && (
                    <span className="technique-moment__source">
                      {km.video_filename}
                    </span>
                  )}
                  <span className="technique-moment__time">
                    {formatTime(km.start_time)} – {formatTime(km.end_time)}
                  </span>
                  <span className="badge badge--content-type">
                    {km.content_type}
                  </span>
                </div>
                <p className="technique-moment__summary">{km.summary}</p>
              </li>
            ))}
          </ol>
        </section>
      )}

      {/* Signal chains */}
      {displayChains &&
        displayChains.length > 0 && (
          <section className="technique-chains">
            <h2>Signal Chains</h2>
            {displayChains.map((chain, i) => {
              const chainObj = chain as Record<string, unknown>;
              const chainName =
                typeof chainObj["name"] === "string"
                  ? chainObj["name"]
                  : `Chain ${i + 1}`;
              const steps = Array.isArray(chainObj["steps"])
                ? (chainObj["steps"] as string[])
                : [];
              return (
                <div key={i} className="technique-chain">
                  <h3>{chainName}</h3>
                  {steps.length > 0 && (
                    <div className="technique-chain__flow">
                      {steps.map((step, j) => (
                        <span key={j}>
                          {j > 0 && (
                            <span className="technique-chain__arrow">
                              {" → "}
                            </span>
                          )}
                          <span className="technique-chain__step">
                            {String(step)}
                          </span>
                        </span>
                      ))}
                    </div>
                  )}
                </div>
              );
            })}
          </section>
        )}

      {/* Related techniques (always from live data) */}
      {technique.related_links.length > 0 && (
        <section className="technique-related">
          <h2>Related Techniques</h2>
          <div className="technique-related__grid">
            {technique.related_links.map((link) => (
              <div key={link.target_slug} className="related-card">
                <Link to={`/techniques/${link.target_slug}`} className="related-card__title">
                  {link.target_title}
                </Link>
                {link.creator_name && (
                  <span className="related-card__creator">{link.creator_name}</span>
                )}
                {link.topic_category && (
                  <span className="related-card__badge">{link.topic_category}</span>
                )}
                {link.reason && (
                  <p className="related-card__reason">{link.reason}</p>
                )}
              </div>
            ))}
          </div>
        </section>
      )}
        </div>
      </div>

      {/* Footer actions */}
      <div className="technique-footer">
        <button
          className="btn btn--ghost btn--small"
          onClick={() => setShowReport(true)}
        >
          ⚑ Report issue with this page
        </button>
        {technique.key_moments.length > 0 && technique.key_moments[0]?.source_video_id && (
          <Link
            to={`/admin/pipeline?video=${technique.key_moments[0].source_video_id}`}
            className="btn btn--ghost btn--small technique-footer__inspect"
            title="View pipeline job for this article"
          >
            <svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
              <circle cx="11" cy="11" r="7" />
              <line x1="16.5" y1="16.5" x2="21" y2="21" />
              <line x1="11" y1="8" x2="11" y2="14" />
              <line x1="8" y1="11" x2="14" y2="11" />
            </svg>
            Inspect pipeline
          </Link>
        )}
      </div>
    </article>
  );
}
