import { useState, useRef, useEffect, useCallback } from "react";
import { useLiveKit } from "./useLiveKit";
import { useDualCamera } from "./useDualCamera";
import { useAuth } from "../../auth/AuthContext";
import { fetchPostComments, createPostComment } from "../../api/client";
import { CREATE_CATEGORY_MAP, FILTER_MAIN_CATEGORIES } from "../Map/mapConfig";
import "./Live.css";

const API_BASE = (import.meta?.env?.VITE_API_BASE_URL || "").replace(/\/+$/, "");
const LIVEKIT_API = "https://live.us1.sociowire.com";

/**
 * LiveKit-based broadcast component
 * Professional video streaming that works everywhere (5G, 4G, WiFi, firewalls)
 */
export default function LiveKitBroadcast({ coords, onClose, onStreamCreated }) {
  const { username, token: authToken } = useAuth();
  const userID = username || `anon_${Date.now()}`;

  const [roomName] = useState(() => `live_${userID}_${Date.now()}`);
  const [title, setTitle] = useState("");
  const [showConfirm, setShowConfirm] = useState(false);
  const [livePostId, setLivePostId] = useState(null);
  const liveCategoryOptions = FILTER_MAIN_CATEGORIES.filter((c) => c !== "All");
  const [liveCategory, setLiveCategory] = useState("Events");
  const [liveSubCategory, setLiveSubCategory] = useState("Live");

  // Timer state
  const [liveStartTime, setLiveStartTime] = useState(null);
  const [elapsedTime, setElapsedTime] = useState(0);

  // Comments state (stored in the post so they persist after live)
  const [comments, setComments] = useState([]);
  const [commentInput, setCommentInput] = useState("");
  const commentsEndRef = useRef(null);

  const [liveCoords] = useState(() => {
    if (coords && typeof coords === "object") {
      if (Array.isArray(coords) && coords.length >= 2) {
        return { lon: coords[0], lat: coords[1] };
      }
      const lat = coords.lat ?? coords.latitude;
      const lon = coords.lon ?? coords.lng ?? coords.longitude;
      if (Number.isFinite(lat) && Number.isFinite(lon)) {
        return { lat, lon };
      }
    }
    return { lat: null, lon: null };
  });

  const videoRef = useRef(null);

  // Camera hook - handles device enumeration and swapping
  const {
    mainStream,
    isSwapped,
    error: cameraError,
    isStarting: cameraStarting,
    isSwapping,
    hasDualCameras,
    startCameras,
    swapCameras,
    stopCameras,
  } = useDualCamera();

  const {
    isLive,
    isConnecting,
    error: liveKitError,
    viewerCount,
    startBroadcast,
    stopBroadcast,
    replaceVideoTrack,
  } = useLiveKit({
    roomName,
    userID,
    username,
    token: authToken,
  });

  const error = cameraError || liveKitError;

  const subCategoryOptions = (() => {
    const options = Array.isArray(CREATE_CATEGORY_MAP[liveCategory])
      ? CREATE_CATEGORY_MAP[liveCategory]
      : [];
    const withLive = ["Live", ...options];
    const deduped = [];
    const seen = new Set();
    for (const item of withLive) {
      const label = (item || "").toString().trim();
      if (!label || seen.has(label)) continue;
      seen.add(label);
      deduped.push(label);
    }
    return deduped;
  })();

  useEffect(() => {
    if (!subCategoryOptions.length) return;
    if (!subCategoryOptions.includes(liveSubCategory)) {
      setLiveSubCategory(subCategoryOptions[0]);
    }
  }, [liveCategory]);

  // Start camera on mount
  useEffect(() => {
    startCameras();
    return () => {
      stopCameras();
    };
  }, []);

  // Update video element when stream changes
  useEffect(() => {
    const el = videoRef.current;
    if (!el || !mainStream) return;
    el.srcObject = mainStream;
    el.muted = true;
    const tryPlay = () => {
      const p = el.play();
      if (p && typeof p.catch === "function") {
        p.catch(() => {});
      }
    };
    el.onloadedmetadata = tryPlay;
    tryPlay();
  }, [mainStream]);

  // Timer effect - update every second when live
  useEffect(() => {
    if (!isLive || !liveStartTime) return;

    const interval = setInterval(() => {
      setElapsedTime(Math.floor((Date.now() - liveStartTime) / 1000));
    }, 1000);

    return () => clearInterval(interval);
  }, [isLive, liveStartTime]);

  // Auto-scroll comments
  useEffect(() => {
    commentsEndRef.current?.scrollIntoView({ behavior: "smooth" });
  }, [comments]);

  // Format elapsed time as MM:SS
  const formatTime = (seconds) => {
    const mins = Math.floor(seconds / 60);
    const secs = seconds % 60;
    return `${mins.toString().padStart(2, "0")}:${secs.toString().padStart(2, "0")}`;
  };

  // Switch between front and back camera
  const switchCamera = useCallback(async () => {
    if (isSwapping || !hasDualCameras) return;

    await swapCameras();

    // If live, replace the video track in LiveKit after swap
    // Note: mainStream will be updated by useDualCamera, we need to wait for it
  }, [isSwapping, hasDualCameras, swapCameras]);

  // Update LiveKit track when mainStream changes during live
  useEffect(() => {
    if (isLive && mainStream) {
      const newVideoTrack = mainStream.getVideoTracks()[0];
      if (newVideoTrack) {
        replaceVideoTrack(newVideoTrack);
      }
    }
  }, [mainStream, isLive, replaceVideoTrack]);

  const refreshComments = useCallback(async () => {
    if (!livePostId) return;
    const items = await fetchPostComments(livePostId, 50);
    if (Array.isArray(items)) {
      setComments(items);
    }
  }, [livePostId]);

  useEffect(() => {
    if (!isLive || !livePostId) return;
    let active = true;
    const poll = async () => {
      if (!active) return;
      await refreshComments();
    };
    poll();
    const timer = setInterval(poll, 4000);
    return () => {
      active = false;
      clearInterval(timer);
    };
  }, [isLive, livePostId, refreshComments]);

  // Add a comment (persist to post immediately)
  const handleAddComment = useCallback(async () => {
    const body = commentInput.trim();
    if (!body || !livePostId) return;
    setCommentInput("");
    const res = await createPostComment(livePostId, body);
    if (res?.ok) {
      await refreshComments();
    }
  }, [commentInput, livePostId, refreshComments]);

  const handleGoLive = useCallback(async () => {
    if (!authToken) {
      alert("Please log in to start a live stream.");
      return;
    }
    if (!title.trim()) {
      alert("Please enter a title");
      return;
    }
    if (!mainStream) {
      alert("Camera not ready");
      return;
    }

    // Get video track from stream
    const videoTrack = mainStream.getVideoTracks()[0];
    await startBroadcast(videoTrack, true);

    // Start timer
    setLiveStartTime(Date.now());
    setElapsedTime(0);

    if (onStreamCreated) {
      onStreamCreated({
        roomName,
        title: title.trim(),
        coords: liveCoords,
      });
    }

    try {
      const res = await fetch(`${API_BASE}/api/post`, {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          ...(authToken ? { Authorization: `Bearer ${authToken}` } : {}),
        },
        body: JSON.stringify({
          title: title.trim(),
          snippet: `Live now${liveSubCategory ? ` · ${liveSubCategory}` : ""}`,
          category: liveCategory === "Events" ? "EVENT" : liveCategory.toUpperCase(),
          sub_category: liveSubCategory || "Live",
          lat: liveCoords?.lat,
          lon: liveCoords?.lon,
          author: username,
          source: "sociowire",
          visibility: "public",
          content_type: "live",
          embed_url: `livekit://${roomName}`,
        }),
      });
      if (res.ok) {
        const post = await res.json();
        setLivePostId(post?.id || null);
        window.dispatchEvent(new CustomEvent("live-post-created", { detail: post }));
      } else {
        const errText = await res.text();
        console.error("[LiveKit] Failed to create live post:", res.status, errText);
        alert("Live started, but we couldn't create the live post.");
      }
    } catch (err) {
      console.error("[LiveKit] Failed to create live post:", err);
      alert("Live started, but we couldn't create the live post.");
    }
  }, [
    title,
    mainStream,
    startBroadcast,
    roomName,
    liveCoords,
    onStreamCreated,
    authToken,
    username,
    liveCategory,
    liveSubCategory,
  ]);

  const handleEndStream = useCallback(async (save) => {
    await stopBroadcast();
    stopCameras();

    // Stop egress recording and get video key
    let videoKey = "";
    let thumbnailKey = "";
    try {
      const egressRes = await fetch(`${LIVEKIT_API}/api/livekit/egress/stop`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ room: roomName, save: !!save }),
      });
      if (egressRes.ok) {
        const egressData = await egressRes.json();
        videoKey = egressData.key || "";
        thumbnailKey = egressData.thumbnail_key || "";
        console.log("[LiveKit] Egress stopped, video key:", videoKey);
      }
    } catch (err) {
      console.warn("[LiveKit] Failed to stop egress:", err);
    }

    if (livePostId) {
      try {
        // Include comments in finalize request
        const res = await fetch(`${API_BASE}/api/live/finalize`, {
          method: "POST",
          headers: {
            "Content-Type": "application/json",
            ...(authToken ? { Authorization: `Bearer ${authToken}` } : {}),
          },
          body: JSON.stringify({
            post_id: livePostId,
            save: !!save,
            video_key: videoKey,
            thumbnail_key: thumbnailKey,
            comments: [],
          }),
        });
        if (res.ok && save) {
          const post = await res.json();
          window.dispatchEvent(new CustomEvent("live-post-updated", { detail: post }));
        }
        if (res.ok && !save) {
          window.dispatchEvent(new CustomEvent("live-post-deleted", { detail: { post_id: livePostId } }));
        }
        if (!res.ok) {
          const errText = await res.text();
          console.error("[LiveKit] Finalize failed:", res.status, errText);
          alert("We couldn't save the live post. Please try again.");
        }
      } catch (err) {
        console.error("[LiveKit] Failed to finalize live post:", err);
        alert("We couldn't save the live post. Please try again.");
      }
    }
    onClose?.();
  }, [stopBroadcast, stopCameras, onClose, livePostId, authToken, roomName, comments]);

  const handleBackdropClick = (e) => {
    if (e.target === e.currentTarget && !isLive) {
      stopCameras();
      onClose?.();
    }
  };

  return (
    <div className="sw-broadcast-modal" onClick={handleBackdropClick}>
      <div className="sw-broadcast-container">
        {/* Header */}
        <div className="sw-broadcast-header">
          <div className="sw-broadcast-header-left">
            <i className="fa-solid fa-broadcast-tower" />
            <span>{isLive ? "LIVE" : "Go Live"}</span>
            {isLive && (
              <>
                <div className="sw-broadcast-live-badge">
                  <span className="sw-broadcast-dot" />
                  <span>{viewerCount} watching</span>
                </div>
                <div className="sw-broadcast-timer">
                  <i className="fa-solid fa-clock" />
                  <span>{formatTime(elapsedTime)}</span>
                </div>
              </>
            )}
          </div>
          <button
            type="button"
            className="sw-broadcast-close"
            onClick={() => {
              if (isLive) {
                setShowConfirm(true);
              } else {
                stopCameras();
                onClose?.();
              }
            }}
          >
            <i className="fa-solid fa-times" />
          </button>
        </div>

        {/* Content */}
        <div className="sw-broadcast-content">
          {/* Video preview */}
          <div className="sw-broadcast-video-area">
            <div className="sw-broadcast-main-video">
              {mainStream ? (
                <video
                  ref={videoRef}
                  autoPlay
                  playsInline
                  muted
                  className="sw-broadcast-video"
                />
              ) : (
                <div className="sw-broadcast-video-placeholder">
                  {cameraStarting ? (
                    <>
                      <i className="fa-solid fa-spinner fa-spin" />
                      <span>Starting camera...</span>
                    </>
                  ) : (
                    <>
                      <i className="fa-solid fa-video-slash" />
                      <span>Camera unavailable</span>
                    </>
                  )}
                </div>
              )}

              {isLive && (
                <div className="sw-broadcast-live-indicator">
                  <span className="sw-broadcast-dot" />
                  <span>LIVE</span>
                </div>
              )}

              {/* Camera controls overlay */}
              <div className="sw-broadcast-controls-overlay">
                {hasDualCameras && (
                  <button
                    type="button"
                    className="sw-broadcast-control-btn"
                    onClick={switchCamera}
                    disabled={isSwapping}
                    title={isSwapped ? "Switch to front camera" : "Switch to back camera"}
                  >
                    {isSwapping ? (
                      <i className="fa-solid fa-spinner fa-spin" />
                    ) : (
                      <i className="fa-solid fa-camera-rotate" />
                    )}
                  </button>
                )}
              </div>
            </div>
          </div>

          {/* Side panel */}
          <div className="sw-broadcast-side">
            {!isLive && (
              <div className="sw-broadcast-form">
                <label className="sw-broadcast-label">Stream Title</label>
                <input
                  type="text"
                  className="sw-broadcast-input"
                  placeholder="What's happening?"
                  value={title}
                  onChange={(e) => setTitle(e.target.value)}
                  maxLength={100}
                />
                <label className="sw-broadcast-label">Category</label>
                <select
                  className="sw-broadcast-input"
                  value={liveCategory}
                  onChange={(e) => setLiveCategory(e.target.value)}
                >
                  {liveCategoryOptions.map((opt) => (
                    <option key={opt} value={opt}>
                      {opt}
                    </option>
                  ))}
                </select>
                <label className="sw-broadcast-label">Subcategory</label>
                <select
                  className="sw-broadcast-input"
                  value={liveSubCategory}
                  onChange={(e) => setLiveSubCategory(e.target.value)}
                >
                  {subCategoryOptions.map((opt) => (
                    <option key={opt} value={opt}>
                      {opt}
                    </option>
                  ))}
                </select>
                <div className="sw-broadcast-hint">
                  Using LiveKit - works on 5G/4G/WiFi
                </div>
              </div>
            )}

            {isLive && (
              <>
                <div className="sw-broadcast-live-info">
                  <h3 className="sw-broadcast-title">{title}</h3>
                  <div className="sw-broadcast-stats">
                    <span>
                      <i className="fa-solid fa-eye" /> {viewerCount} viewers
                    </span>
                    <span>
                      <i className="fa-solid fa-clock" /> {formatTime(elapsedTime)}
                    </span>
                  </div>
                </div>

                {/* Comments section */}
                <div className="sw-broadcast-comments">
                  <div className="sw-broadcast-comments-header">
                    <i className="fa-solid fa-comments" />
                    <span>Comments ({comments.length})</span>
                  </div>
                  <div className="sw-broadcast-comments-list">
                    {comments.length === 0 ? (
                      <div className="sw-broadcast-no-comments">
                        {livePostId ? "No comments yet" : "Connecting chat..."}
                      </div>
                    ) : (
                      comments.map((c, idx) => (
                        <div
                          key={c.id || c.ID || c.created_at || c.createdAt || `${c.username || "user"}-${idx}`}
                          className="sw-broadcast-comment"
                        >
                          <span className="sw-broadcast-comment-author">{c.username || c.author || "User"}</span>
                          <span className="sw-broadcast-comment-text">{c.body || c.text || ""}</span>
                        </div>
                      ))
                    )}
                    <div ref={commentsEndRef} />
                  </div>
                  <div className="sw-broadcast-comment-input-row">
                    <input
                      type="text"
                      className="sw-broadcast-comment-input"
                      placeholder={livePostId ? "Add a comment..." : "Chat starting..."}
                      value={commentInput}
                      onChange={(e) => setCommentInput(e.target.value)}
                      onKeyDown={(e) => e.key === "Enter" && handleAddComment()}
                      maxLength={200}
                      disabled={!livePostId}
                    />
                    <button
                      type="button"
                      className="sw-broadcast-comment-send"
                      onClick={handleAddComment}
                      disabled={!commentInput.trim() || !livePostId}
                    >
                      <i className="fa-solid fa-paper-plane" />
                    </button>
                  </div>
                </div>
              </>
            )}

            {error && (
              <div className="sw-broadcast-error">
                <i className="fa-solid fa-exclamation-triangle" />
                <span>{error}</span>
              </div>
            )}

            <div className="sw-broadcast-actions">
              {isLive ? (
                <button
                  type="button"
                  className="sw-broadcast-btn danger"
                  onClick={() => setShowConfirm(true)}
                >
                  <i className="fa-solid fa-stop" />
                  <span>End Stream</span>
                </button>
              ) : (
                <button
                  type="button"
                  className="sw-broadcast-btn primary"
                  onClick={handleGoLive}
                  disabled={isConnecting || !mainStream}
                >
                  {isConnecting ? (
                    <>
                      <i className="fa-solid fa-spinner fa-spin" />
                      <span>Connecting...</span>
                    </>
                  ) : (
                    <>
                      <i className="fa-solid fa-broadcast-tower" />
                      <span>Go Live</span>
                    </>
                  )}
                </button>
              )}
            </div>
          </div>
        </div>

        {/* Confirm dialog */}
        {showConfirm && (
          <div className="sw-broadcast-confirm-overlay">
            <div className="sw-broadcast-confirm">
              <h3>End Stream?</h3>
              <p>Your live stream will end for all viewers.</p>
              {comments.length > 0 && (
                <p className="sw-broadcast-confirm-comments">
                  <i className="fa-solid fa-comments" /> {comments.length} comments will be saved
                </p>
              )}
              <div className="sw-broadcast-confirm-actions">
                <button
                  type="button"
                  className="sw-broadcast-btn secondary"
                  onClick={() => setShowConfirm(false)}
                >
                  Cancel
                </button>
                <button
                  type="button"
                  className="sw-broadcast-btn danger"
                  onClick={() => handleEndStream(false)}
                >
                  Discard
                </button>
                <button
                  type="button"
                  className="sw-broadcast-btn primary"
                  onClick={() => handleEndStream(true)}
                >
                  Save
                </button>
              </div>
            </div>
          </div>
        )}
      </div>
    </div>
  );
}
