import { useCallback, useEffect, useRef, useState } from "react";
import { Link, useParams } from "react-router-dom";
import WaveSurfer from "wavesurfer.js";
import RegionsPlugin from "wavesurfer.js/dist/plugins/regions.esm.js";
import { SidebarNav } from "./CreatorDashboard";
import { ApiError } from "../api/client";
import {
  fetchCreatorChapters,
  fetchVideo,
  updateChapter,
  reorderChapters,
  approveChapters,
  type Chapter,
  type VideoDetail,
} from "../api/videos";
import { fetchConsentList, type VideoConsentRead } from "../api/consent";
import { useDocumentTitle } from "../hooks/useDocumentTitle";
import styles from "./ChapterReview.module.css";

/* ── Helpers ────────────────────────────────────────────────────────────────── */

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 statusBadgeClass(status: string): string {
  switch (status) {
    case "approved":
      return styles.badgeApproved ?? "";
    case "hidden":
      return styles.badgeHidden ?? "";
    default:
      return styles.badgeDraft ?? "";
  }
}

/* ── Region color per status ───────────────────────────────────────────────── */

function regionColor(status: string): string {
  switch (status) {
    case "approved":
      return "rgba(34, 197, 94, 0.15)";
    case "hidden":
      return "rgba(239, 68, 68, 0.10)";
    default:
      return "rgba(0, 255, 209, 0.12)";
  }
}

/* ── Video Picker (shown when no videoId in URL) ───────────────────────────── */

function VideoPicker() {
  const [videos, setVideos] = useState<VideoConsentRead[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    let cancelled = false;
    fetchConsentList()
      .then((res) => {
        if (!cancelled) setVideos(res.items);
      })
      .catch((err) => {
        if (!cancelled)
          setError(err instanceof ApiError ? err.detail : "Failed to load videos");
      })
      .finally(() => {
        if (!cancelled) setLoading(false);
      });
    return () => { cancelled = true; };
  }, []);

  return (
    <div className={styles.layout}>
      <SidebarNav />
      <div className={styles.content}>
        <h1 className={styles.pageTitle}>Chapter Review</h1>
        <p className={styles.subtitle}>Select a video to review its chapters</p>

        {loading && <div className={styles.loadingState}>Loading videos…</div>}
        {!loading && error && <div className={styles.errorState}>{error}</div>}
        {!loading && !error && videos.length === 0 && (
          <div className={styles.emptyState}>
            <h2>No Videos</h2>
            <p>You don't have any videos yet.</p>
          </div>
        )}
        {!loading && !error && videos.length > 0 && (
          <div className={styles.videoPickerList}>
            {videos.map((v) => (
              <Link
                key={v.source_video_id}
                to={`/creator/chapters/${v.source_video_id}`}
                className={styles.videoPickerCard}
              >
                <svg className={styles.videoPickerIcon} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                  <polygon points="23 7 16 12 23 17 23 7" />
                  <rect x="1" y="5" width="15" height="14" rx="2" ry="2" />
                </svg>
                <div className={styles.videoPickerInfo}>
                  <span className={styles.videoPickerName}>{v.video_filename}</span>
                </div>
              </Link>
            ))}
          </div>
        )}
      </div>
    </div>
  );
}

/* ── Main component ────────────────────────────────────────────────────────── */

export default function ChapterReview() {
  const { videoId } = useParams<{ videoId: string }>();
  useDocumentTitle("Chapter Review");

  // If no videoId in URL, show the video picker
  if (!videoId) return <VideoPicker />;

  return <ChapterReviewDetail videoId={videoId} />;
}

/* ── Detail view (has a videoId) ───────────────────────────────────────────── */

function ChapterReviewDetail({ videoId }: { videoId: string }) {

  const [chapters, setChapters] = useState<Chapter[]>([]);
  const [video, setVideo] = useState<VideoDetail | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [selected, setSelected] = useState<Set<string>>(new Set());
  const [saving, setSaving] = useState(false);

  // WaveSurfer refs
  const waveContainerRef = useRef<HTMLDivElement | null>(null);
  const wsRef = useRef<WaveSurfer | null>(null);
  const regionsRef = useRef<RegionsPlugin | null>(null);
  const audioRef = useRef<HTMLAudioElement | null>(null);

  // Stable ref for chapters so region callbacks see latest state
  const chaptersRef = useRef<Chapter[]>(chapters);
  chaptersRef.current = chapters;

  /* ── Fetch data ──────────────────────────────────────────────────────────── */

  useEffect(() => {
    if (!videoId) return;
    let cancelled = false;
    setLoading(true);
    setError(null);

    Promise.all([fetchCreatorChapters(videoId), fetchVideo(videoId)])
      .then(([chapRes, vid]) => {
        if (cancelled) return;
        setChapters(chapRes.chapters);
        setVideo(vid);
      })
      .catch((err) => {
        if (cancelled) return;
        setError(err instanceof ApiError ? err.detail : "Failed to load chapters");
      })
      .finally(() => {
        if (!cancelled) setLoading(false);
      });

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

  /* ── WaveSurfer init ─────────────────────────────────────────────────────── */

  useEffect(() => {
    const container = waveContainerRef.current;
    const audio = audioRef.current;
    if (!container || !audio || chapters.length === 0) return;

    // Destroy any previous instance
    if (wsRef.current) {
      wsRef.current.destroy();
      wsRef.current = null;
      regionsRef.current = null;
    }

    const regions = RegionsPlugin.create();
    regionsRef.current = regions;

    const ws = WaveSurfer.create({
      container,
      media: audio,
      height: 128,
      waveColor: "rgba(34, 211, 238, 0.4)",
      progressColor: "rgba(34, 211, 238, 0.8)",
      cursorColor: "#22d3ee",
      barWidth: 2,
      barGap: 1,
      barRadius: 2,
      backend: "MediaElement",
      plugins: [regions],
    });

    wsRef.current = ws;

    ws.on("ready", () => {
      for (const ch of chaptersRef.current) {
        regions.addRegion({
          id: ch.id,
          start: ch.start_time,
          end: ch.end_time,
          content: ch.title,
          color: regionColor(ch.chapter_status),
          drag: true,
          resize: true,
        });
      }
    });

    // Sync region drag/resize back to chapter state and API
    regions.on("region-updated", (region: any) => {
      const chId = region.id as string;
      const newStart = region.start as number;
      const newEnd = region.end as number;

      setChapters((prev) =>
        prev.map((c) =>
          c.id === chId ? { ...c, start_time: newStart, end_time: newEnd } : c,
        ),
      );

      // Persist to backend (fire-and-forget with error logging)
      updateChapter(chId, { start_time: newStart, end_time: newEnd }).catch((err) =>
        console.error("Failed to save region update:", err),
      );
    });

    return () => {
      ws.destroy();
      wsRef.current = null;
      regionsRef.current = null;
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [video, chapters.length > 0]); // re-init when video loads or chapters first arrive

  /* ── Chapter actions ─────────────────────────────────────────────────────── */

  const handleTitleChange = useCallback(
    (chapterId: string, newTitle: string) => {
      setChapters((prev) =>
        prev.map((c) => (c.id === chapterId ? { ...c, title: newTitle } : c)),
      );
    },
    [],
  );

  const handleTitleBlur = useCallback(
    (chapterId: string, title: string) => {
      updateChapter(chapterId, { title }).catch((err) =>
        console.error("Failed to save title:", err),
      );
      // Update region label
      const regions = regionsRef.current;
      if (regions) {
        const allRegions = regions.getRegions();
        const r = allRegions.find((rg: any) => rg.id === chapterId);
        if (r) {
          r.setOptions({ content: title });
        }
      }
    },
    [],
  );

  const handleStatusToggle = useCallback(
    async (chapterId: string, currentStatus: string) => {
      const next: Record<string, string> = {
        draft: "approved",
        approved: "hidden",
        hidden: "draft",
      };
      const newStatus = next[currentStatus] || "draft";
      try {
        const updated = await updateChapter(chapterId, { chapter_status: newStatus });
        setChapters((prev) =>
          prev.map((c) => (c.id === chapterId ? { ...c, ...updated } : c)),
        );
        // Update region color
        const regions = regionsRef.current;
        if (regions) {
          const allRegions = regions.getRegions();
          const r = allRegions.find((rg: any) => rg.id === chapterId);
          if (r) r.setOptions({ color: regionColor(newStatus) });
        }
      } catch (err) {
        console.error("Failed to toggle status:", err);
      }
    },
    [],
  );

  const handleMoveUp = useCallback(
    async (index: number) => {
      if (!videoId || index <= 0) return;
      const newList = [...chapters];
      const a = newList[index - 1]; const b = newList[index];
      if (!a || !b) return;
      [newList[index - 1], newList[index]] = [b, a];
      const order = newList.map((c, i) => ({ id: c.id, sort_order: i }));
      setChapters(newList);
      try {
        const res = await reorderChapters(videoId, order);
        setChapters(res.chapters);
      } catch (err) {
        console.error("Failed to reorder:", err);
      }
    },
    [chapters, videoId],
  );

  const handleMoveDown = useCallback(
    async (index: number) => {
      if (!videoId || index >= chapters.length - 1) return;
      const newList = [...chapters];
      const a = newList[index]; const b = newList[index + 1];
      if (!a || !b) return;
      [newList[index], newList[index + 1]] = [b, a];
      const order = newList.map((c, i) => ({ id: c.id, sort_order: i }));
      setChapters(newList);
      try {
        const res = await reorderChapters(videoId, order);
        setChapters(res.chapters);
      } catch (err) {
        console.error("Failed to reorder:", err);
      }
    },
    [chapters, videoId],
  );

  /* ── Bulk actions ────────────────────────────────────────────────────────── */

  const toggleSelect = useCallback((id: string) => {
    setSelected((prev) => {
      const next = new Set(prev);
      if (next.has(id)) next.delete(id);
      else next.add(id);
      return next;
    });
  }, []);

  const toggleSelectAll = useCallback(() => {
    setSelected((prev) =>
      prev.size === chapters.length
        ? new Set()
        : new Set(chapters.map((c) => c.id)),
    );
  }, [chapters]);

  const handleApproveSelected = useCallback(async () => {
    if (!videoId || selected.size === 0) return;
    setSaving(true);
    try {
      const res = await approveChapters(videoId, Array.from(selected));
      setChapters(res.chapters);
      setSelected(new Set());
    } catch (err) {
      console.error("Failed to approve:", err);
    } finally {
      setSaving(false);
    }
  }, [videoId, selected]);

  const handleApproveAll = useCallback(async () => {
    if (!videoId) return;
    setSaving(true);
    try {
      const allIds = chapters.map((c) => c.id);
      const res = await approveChapters(videoId, allIds);
      setChapters(res.chapters);
      setSelected(new Set());
    } catch (err) {
      console.error("Failed to approve all:", err);
    } finally {
      setSaving(false);
    }
  }, [videoId, chapters]);

  /* ── Audio source ────────────────────────────────────────────────────────── */

  const audioSrc = video?.video_url || (video ? `/api/v1/videos/${video.id}/stream` : "");

  /* ── Render ──────────────────────────────────────────────────────────────── */

  return (
    <div className={styles.layout}>
      <SidebarNav />
      <div className={styles.content}>
        <h1 className={styles.pageTitle}>Chapter Review</h1>
        <p className={styles.subtitle}>
          {video ? video.filename : "Loading…"}
          {chapters.length > 0 && ` · ${chapters.length} chapters`}
        </p>

        {loading && <div className={styles.loadingState}>Loading chapters…</div>}

        {!loading && error && <div className={styles.errorState}>{error}</div>}

        {!loading && !error && chapters.length === 0 && (
          <div className={styles.emptyState}>
            <h2>No Chapters</h2>
            <p>This video doesn't have any auto-detected chapters yet.</p>
          </div>
        )}

        {!loading && !error && chapters.length > 0 && (
          <>
            {/* ── Waveform ─────────────────────────────────────────── */}
            <div className={styles.waveformWrap}>
              <p className={styles.waveformLabel}>
                Drag region edges to adjust chapter boundaries
              </p>
              <audio ref={audioRef} src={audioSrc} preload="metadata" style={{ display: "none" }} />
              <div ref={waveContainerRef} className={styles.waveformCanvas} />
            </div>

            {/* ── Bulk action bar ──────────────────────────────────── */}
            <div className={styles.bulkBar}>
              <button className={styles.bulkBtn} onClick={toggleSelectAll} type="button">
                {selected.size === chapters.length ? "Deselect All" : "Select All"}
              </button>
              <button
                className={`${styles.bulkBtn} ${styles.bulkBtnPrimary}`}
                onClick={handleApproveSelected}
                disabled={selected.size === 0 || saving}
                type="button"
              >
                Approve Selected ({selected.size})
              </button>
              <button
                className={styles.bulkBtn}
                onClick={handleApproveAll}
                disabled={saving}
                type="button"
              >
                Approve All
              </button>
              {selected.size > 0 && (
                <span className={styles.selectedCount}>
                  {selected.size} of {chapters.length} selected
                </span>
              )}
            </div>

            {/* ── Chapter list ─────────────────────────────────────── */}
            <div className={styles.chapterList}>
              {chapters.map((ch, idx) => (
                <div key={ch.id} className={styles.chapterRow}>
                  <input
                    type="checkbox"
                    className={styles.chapterCheckbox}
                    checked={selected.has(ch.id)}
                    onChange={() => toggleSelect(ch.id)}
                  />
                  <span className={styles.chapterIndex}>{idx + 1}</span>
                  <input
                    type="text"
                    className={styles.chapterTitle}
                    value={ch.title}
                    onChange={(e) => handleTitleChange(ch.id, e.target.value)}
                    onBlur={(e) => handleTitleBlur(ch.id, e.target.value)}
                  />
                  <span className={styles.chapterTimes}>
                    {formatTime(ch.start_time)} – {formatTime(ch.end_time)}
                  </span>
                  <span className={`${styles.badge} ${statusBadgeClass(ch.chapter_status)}`}>
                    {ch.chapter_status}
                  </span>
                  <div className={styles.rowActions}>
                    {/* Move up */}
                    <button
                      className={styles.iconBtn}
                      onClick={() => handleMoveUp(idx)}
                      disabled={idx === 0}
                      title="Move up"
                      type="button"
                    >
                      <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                        <polyline points="18 15 12 9 6 15" />
                      </svg>
                    </button>
                    {/* Move down */}
                    <button
                      className={styles.iconBtn}
                      onClick={() => handleMoveDown(idx)}
                      disabled={idx === chapters.length - 1}
                      title="Move down"
                      type="button"
                    >
                      <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                        <polyline points="6 9 12 15 18 9" />
                      </svg>
                    </button>
                    {/* Status cycle: draft → approved → hidden → draft */}
                    <button
                      className={styles.iconBtn}
                      onClick={() => handleStatusToggle(ch.id, ch.chapter_status)}
                      title={`Status: ${ch.chapter_status} (click to cycle)`}
                      type="button"
                    >
                      <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                        {ch.chapter_status === "approved" ? (
                          <><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14" /><polyline points="22 4 12 14.01 9 11.01" /></>
                        ) : ch.chapter_status === "hidden" ? (
                          <><path d="M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94" /><line x1="1" y1="1" x2="23" y2="23" /></>
                        ) : (
                          <circle cx="12" cy="12" r="10" />
                        )}
                      </svg>
                    </button>
                  </div>
                </div>
              ))}
            </div>
          </>
        )}
      </div>
    </div>
  );
}
