"use client";

import { Suspense, useState } from "react";
import { useEditMode } from "./EditModeContext";
import type { TrailStop } from "@/data/queries";
import { StopEmbed, type EmbedCache } from "./StopEmbed";
import { extractLink } from "./utils/linkExtraction";
import { getLinkMetadata, blueskyUrlToAtUri } from "./utils/embed-resolver";
import "./TrailStopCard.css";

function EmbedLoading() {
  return (
    <div className="BlueskyPostEmbed-container">
      <div className="BlueskyPostEmbed loading">
        <div className="BlueskyPostEmbed-loading">loading...</div>
      </div>
    </div>
  );
}

type Props = {
  stop: TrailStop;
  stepNumber: number;
  totalStops: number;
  isCurrent?: boolean;
};

export function TrailStopCard({ stop, stepNumber, totalStops, isCurrent = false }: Props) {
  const editContext = useEditMode();
  const isEditing = !!editContext;
  const updateStop = editContext?.updateStop;
  const error = editContext?.inlineErrors[stop.tid];
  const [embedCache, setEmbedCache] = useState<EmbedCache>(() => new Map());

  const handleTitleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    if (updateStop) updateStop(stop.tid, { title: e.target.value });
  };

  const handleContentChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
    if (updateStop) updateStop(stop.tid, { content: e.target.value });
  };

  const handlePaste = async (e: React.ClipboardEvent<HTMLTextAreaElement>) => {
    // If there's already a link, just paste normally
    if (stop.external) return;

    const pastedText = e.clipboardData.getData("text");
    const extractedLink = extractLink(pastedText);
    if (!extractedLink || !updateStop) return;

    // Bluesky links - prevent paste, set external
    if (extractedLink.type === "bluesky") {
      e.preventDefault();
      let linkUrl = extractedLink.uri;
      if (linkUrl.startsWith("http")) {
        const atUri = blueskyUrlToAtUri(linkUrl);
        if (atUri) linkUrl = atUri;
      }
      updateStop(stop.tid, {
        external: { uri: linkUrl, title: linkUrl, description: "" },
      });
      return;
    }

    // HTTP links - always set external
    const linkUrl = extractedLink.url;

    // For embeddable links, prevent text paste
    const embedDomains = [
      "youtube.com",
      "youtu.be",
      "spotify.com",
      "soundcloud.com",
      "music.apple.com",
      "vimeo.com",
      "twitch.tv",
      "giphy.com",
      "tenor.com",
    ];
    try {
      const host = new URL(linkUrl).hostname.replace(/^www\./, "");
      if (embedDomains.some((d) => host === d || host.endsWith("." + d))) {
        e.preventDefault();
      }
    } catch {}

    updateStop(stop.tid, {
      external: { uri: linkUrl, title: linkUrl, description: "" },
    });

    const metadata = await getLinkMetadata(linkUrl);
    if (metadata && updateStop) {
      updateStop(stop.tid, { external: metadata });
    }
  };

  const handleRemoveLink = () => {
    if (!updateStop) return;

    setEmbedCache(new Map());

    // Check if there's a link in the content to remove
    const extractedLink = extractLink(stop.content);
    if (extractedLink) {
      const linkText = extractedLink.type === "bluesky" ? extractedLink.uri : extractedLink.url;
      const newContent = stop.content.replace(linkText, "").trim();
      updateStop(stop.tid, {
        content: newContent,
        external: undefined,
      });
    } else {
      // Link text already removed, just clear the external field
      updateStop(stop.tid, {
        external: undefined,
      });
    }
  };

  const handleButtonTextChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    if (updateStop) updateStop(stop.tid, { buttonText: e.target.value });
  };

  return (
    <div className="TrailStopCard">
      {error && isEditing && <div className="TrailStopCard-error">{error}</div>}

      <div className="TrailStopCard-header">
        {isEditing ? (
          <input
            type="text"
            value={stop.title}
            onChange={handleTitleChange}
            className={`TrailStopCard-titleEdit ${error ? "TrailStopCard-titleEdit--error" : ""}`}
            placeholder="name this stop"
          />
        ) : (
          stop.title && (
            <h2 className="TrailStopCard-title">
              <span>{stop.title}</span>
            </h2>
          )
        )}
        <div className="TrailStopCard-counter">
          Stop {stepNumber} of {totalStops}
        </div>
      </div>

      <div className="TrailStopCard-content">
        {isEditing ? (
          <textarea
            value={stop.content}
            onChange={handleContentChange}
            onPaste={handlePaste}
            className="TrailStopCard-contentEdit"
            placeholder="what happens here?"
            rows={2}
            onInput={(e) => {
              e.currentTarget.style.height = "auto";
              e.currentTarget.style.height = e.currentTarget.scrollHeight + "px";
            }}
          />
        ) : (
          stop.content && <p className="TrailStopCard-text">{stop.content}</p>
        )}

        {stop.external && (
          <div
            className="TrailStopCard-embed"
            style={isEditing ? { opacity: 0.9, marginTop: "0.5rem" } : undefined}
          >
            <Suspense fallback={<EmbedLoading />}>
              <StopEmbed
                external={stop.external}
                cache={embedCache}
                onDelete={isEditing ? handleRemoveLink : undefined}
              />
            </Suspense>
          </div>
        )}
      </div>

      {/* Custom button text shown when editing current step */}
      {isEditing && isCurrent && (
        <div className="TrailStopCard-buttonPreview">
          <input
            type="text"
            value={stop.buttonText || ""}
            onChange={handleButtonTextChange}
            className="TrailStopCard-buttonTextInput"
            placeholder="done that"
          />
        </div>
      )}
    </div>
  );
}
