// src/components/HumanizerInterface.tsx
/**
 * HumanizerInterface.tsx
 * -------------------------------------------------------------------------------------
 * A complete, production-ready Humanizer UI module with session analytics wired to
 * Firestore and a hash-based cache layer. This file is intentionally verbose and
 * heavily commented for clarity, with defensive checks for all Firestore updates.
 *
 * Key Features
 * ------------
 * - Modes: Normal, Advanced, Expert
 * - Upload .txt / .docx
 * - Hash-based cache lookup to avoid repeated processing (Firestore)
 * - Session analytics:
 *    • stats.totalSessions  (increment when user begins a session)
 *    • stats.averageSessionTime (weighted running average in minutes)
 * - Content stats:
 *    • stats.textsHumanized (increment when output produced)
 *    • stats.wordsProcessed (increment by input word count)
 * - Activity logging to `user_activities`
 * - Clean UI with Tailwind classes, light/dark support via ThemeContext
 *
 * Dependencies
 * ------------
 * - React, React Router (`useNavigate`)
 * - Firebase: `auth`, `db` provided from project-level firebase config
 * - Firestore: doc, updateDoc, getDoc, getDocs, addDoc, collection,
 *              Timestamp, increment, where, query
 * - Hash: sha256 (crypto-hash)
 * - Mammoth: dynamic import for DOCX extraction
 * - lucide-react: icons
 *
 * Firestore Structure (expected)
 * ------------------------------
 * users/{uid}:
 *   - email
 *   - stats: {
 *       textsHumanized: number,
 *       wordsProcessed: number,
 *       gptAverage: number,           // not changed here, used elsewhere
 *       totalSessions: number,
 *       averageSessionTime: number    // minutes, rounded to integer
 *     }
 *   - preferences: { theme, ... }
 *   - lastActive: ISO string
 *
 * user_activities (collection):
 *   - { email, action, mode, wordCount, timestamp, type }
 *
 * humanized_texts (collection):
 *   - { userId, originalText, textHash, humanizedText, createdAt }
 *
 * Notes
 * -----
 * - averageSessionTime is stored in MINUTES as an integer weighted running average.
 * - totalSessions is incremented at "session start" (when user clicks "Humanize").
 * - We compute duration on completion (cache hit or API success) and update running avg.
 * - If session fails to produce output, we simply do not update the average (the session
 *   counter already went up; you can adapt this if you want to only count successful
 *   sessions by moving the increment to the success branch).
 * - To keep the UX snappy and resilient, stats updates are "fire-and-forget" where safe,
 *   and wrapped with try/catch.
 *
 * -------------------------------------------------------------------------------------
 */

import React, {
  useState,
  useContext,
  useMemo,
  useRef,
  useCallback,
  useEffect,
} from "react";
import { ThemeContext } from "../contexts/ThemeContext";
import { sha256 } from "crypto-hash";
import ReactMarkdown from "react-markdown";
import remarkGfm from "remark-gfm";
import {
  Wand2,
  Copy,
  Download,
  AlertCircle,
  CheckCircle,
  Upload,
  Info,
} from "lucide-react";
import { useNavigate } from "react-router-dom";
import { auth, db } from "../firebase";
import {
  doc,
  updateDoc,
  increment,
  addDoc,
  collection,
  Timestamp,
  query,
  where,
  getDocs,
  getDoc,
  Firestore,
  DocumentReference,
  DocumentData,
} from "firebase/firestore";

/* ---------------------------------------------------------------------------------- */
/*                                      Types                                         */
/* ---------------------------------------------------------------------------------- */

type HumanizeMode = "normal" | "advanced" | "expert";

interface HumanizerProps {
  onModeChange?: (mode: HumanizeMode) => void;
}

/**
 * Firestore user.stats model (subset used here).
 */
interface UserStats {
  textsHumanized?: number;
  wordsProcessed?: number;
  gptAverage?: number;
  totalSessions?: number;
  averageSessionTime?: number; // minutes
}

/**
 * Firestore user record (subset used here).
 */
interface UserDoc {
  email?: string;
  stats?: UserStats;
  preferences?: {
    theme?: "dark" | "light";
    [k: string]: unknown;
  };
  [k: string]: unknown;
}

/**
 * Response shape from the backend humanizer API (`/api/routes.php`).
 */
interface HumanizerAPIResponse {
  success: boolean;
  humanizedText?: string;
  error?: string;
}

/**
 * Record in `humanized_texts` collection.
 */
interface HumanizedTextRecord {
  userId: string;
  originalText: string; // stored for convenience (you can remove if sensitive)
  textHash: string; // sha256 of originalText
  humanizedText: string;
  createdAt: Timestamp;
}

/* ---------------------------------------------------------------------------------- */
/*                                   Utilities                                        */
/* ---------------------------------------------------------------------------------- */

/**
 * Safely returns the current user or null.
 */
const getCurrentUser = () => auth.currentUser ?? null;

/**
 * Convert a duration in milliseconds to a whole number of minutes, lower-bounded at 0.
 * We round down to keep a stable integer for averageSessionTime.
 */
const msToWholeMinutes = (ms: number): number => {
  const mins = Math.floor(ms / 60000);
  return mins < 0 ? 0 : mins;
};

/**
 * Weighted running average:
 *   newAvg = (prevAvg * prevCount + newValue) / (prevCount + 1)
 * Caller must supply the counts correctly (e.g., totalSessions already includes
 * this new session, or not, depending on where you do the increment).
 */
const weightedAverage = (
  prevAvg: number,
  prevCount: number,
  newValue: number
) => {
  if (!Number.isFinite(prevAvg) || prevAvg < 0) prevAvg = 0;
  if (!Number.isFinite(prevCount) || prevCount < 0) prevCount = 0;
  if (!Number.isFinite(newValue) || newValue < 0) newValue = 0;

  // If prevCount is 0, average is simply newValue
  if (prevCount === 0) return newValue;

  // Normal running average for (prevCount + 1) samples
  return (prevAvg * prevCount + newValue) / (prevCount + 1);
};

/**
 * Count words in a text by splitting on whitespace.
 */
const countWords = (t: string) => (t.trim() ? t.trim().split(/\s+/).length : 0);

/**
 * Defensive localStorage helper (optional use).
 */
const safeLocalSet = (key: string, value: unknown) => {
  try {
    localStorage.setItem(key, JSON.stringify(value));
  } catch {
    /* no-op */
  }
};

const safeLocalGet = <T,>(key: string, fallback: T): T => {
  try {
    const raw = localStorage.getItem(key);
    return raw ? (JSON.parse(raw) as T) : fallback;
  } catch {
    return fallback;
  }
};

/* ---------------------------------------------------------------------------------- */
/*                            Firestore Helper Functions                              */
/* ---------------------------------------------------------------------------------- */

/**
 * Returns the user document reference for the current user, or null if not logged in.
 */
const getUserRef = (dbInst: Firestore): DocumentReference<DocumentData> | null =>
  getCurrentUser() ? doc(dbInst, "users", getCurrentUser()!.uid) : null;

/**
 * Increment `stats.totalSessions` at session *start*. This function does not await the
 * result (fire-and-forget); you can await if you want strict ordering.
 */
const incrementTotalSessions = async (dbInst: Firestore) => {
  const userRef = getUserRef(dbInst);
  if (!userRef) return;
  try {
    await updateDoc(userRef, {
      "stats.totalSessions": increment(1),
    });
  } catch (e) {
    console.warn("[incrementTotalSessions] Failed to update total sessions:", e);
  }
};

/**
 * Update average session time with a new duration (in minutes).
 * The logic:
 *   - We first read the current stats to obtain current average and totalSessions.
 *   - We compute a new weighted average using totalSessions as the count.
 *   - We then write the new average.
 *
 * Note: We assume `totalSessions` was incremented at session start.
 */
const updateAverageSessionTime = async (
  dbInst: Firestore,
  durationMinutes: number
) => {
  const userRef = getUserRef(dbInst);
  if (!userRef) return;

  try {
    const snap = await getDoc(userRef);
    if (!snap.exists()) return;

    const user = snap.data() as UserDoc;
    const prevAvg = user?.stats?.averageSessionTime || 0;
    const totalSessions = user?.stats?.totalSessions || 0;

    // If for any reason totalSessions is 0, treat as new sample (avoid div by zero).
    const countForAvg = Math.max(totalSessions, 0);

    // Weighted average with the *new* value included.
    // Because totalSessions was incremented at session start, that value already
    // represents the new count. We should use (countForAvg - 1) as prevCount.
    const prevCount = Math.max(countForAvg - 1, 0);
    const nextAvg = weightedAverage(prevAvg, prevCount, durationMinutes);

    await updateDoc(userRef, {
      "stats.averageSessionTime": Math.max(0, Math.round(nextAvg)), // store rounded integer minutes
    });
  } catch (e) {
    console.warn(
      "[updateAverageSessionTime] Failed to compute/write average:",
      e
    );
  }
};

/**
 * Update basic counters after successful result (either from cache or API).
 * - textsHumanized +1
 * - wordsProcessed +{wordCount}
 * - lastActive (ISO string)
 */
const bumpContentStats = async (dbInst: Firestore, wordCount: number) => {
  const userRef = getUserRef(dbInst);
  if (!userRef) return;
  try {
    await updateDoc(userRef, {
      "stats.textsHumanized": increment(1),
      "stats.wordsProcessed": increment(Math.max(0, wordCount)),
      lastActive: new Date().toISOString(),
    });
  } catch (e) {
    console.warn("[bumpContentStats] Failed to update stats:", e);
  }
};

/**
 * Log user activity to `user_activities`.
 */
const logActivity = async (dbInst: Firestore, payload: Record<string, any>) => {
  try {
    await addDoc(collection(dbInst, "user_activities"), {
      ...payload,
      timestamp: Timestamp.fromDate(new Date()),
    });
  } catch (e) {
    console.warn("[logActivity] Failed to write activity log:", e);
  }
};

/**
 * Query `humanized_texts` by (userId + textHash). Returns the first found record or null.
 */
const findCachedHumanizedText = async (
  dbInst: Firestore,
  userId: string,
  textHash: string
): Promise<HumanizedTextRecord | null> => {
  try {
    const q = query(
      collection(dbInst, "humanized_texts"),
      where("userId", "==", userId),
      where("textHash", "==", textHash)
    );
    const snap = await getDocs(q);
    if (snap.empty) return null;
    return snap.docs[0].data() as HumanizedTextRecord;
  } catch (e) {
    console.warn("[findCachedHumanizedText] Query error:", e);
    return null;
  }
};

/**
 * Persist a new record into `humanized_texts`.
 */
const saveHumanizedText = async (
  dbInst: Firestore,
  record: Omit<HumanizedTextRecord, "createdAt">
) => {
  try {
    await addDoc(collection(dbInst, "humanized_texts"), {
      ...record,
      createdAt: Timestamp.fromDate(new Date()),
    });
  } catch (e) {
    console.warn("[saveHumanizedText] Failed to save cache record:", e);
  }
};

/* ---------------------------------------------------------------------------------- */
/*                                Component: Humanizer                                */
/* ---------------------------------------------------------------------------------- */

const HumanizerInterface: React.FC<HumanizerProps> = ({ onModeChange }) => {
  const { theme } = useContext(ThemeContext);
  const navigate = useNavigate();

  // ----------------------------------------------------------------------------------
  // UI State
  // ----------------------------------------------------------------------------------
  const [inputText, setInputText] = useState<string>("");
  const [outputText, setOutputText] = useState<string>("");
  const [mode, setMode] = useState<HumanizeMode>("normal");
  const [loading, setLoading] = useState<boolean>(false);
  const [error, setError] = useState<string>("");
  const [fileName, setFileName] = useState<string>("");
  const [copied, setCopied] = useState<boolean>(false);

  // Session start timestamp (ms). Reset on completion or error.
  const sessionStartRef = useRef<number | null>(null);

  // Memoized counts for UX
  const inputWordCount = useMemo(() => countWords(inputText), [inputText]);
  const outputWordCount = useMemo(() => countWords(outputText), [outputText]);

  // Tailwind class shortcuts based on theme
  const cardBg = theme === "dark" ? "bg-gray-800" : "bg-white";
  const textPrimary = theme === "dark" ? "text-white" : "text-gray-900";
  const textSecondary = theme === "dark" ? "text-gray-300" : "text-gray-600";
  const borderCard = theme === "dark" ? "border-gray-700" : "border-gray-200";

  // ----------------------------------------------------------------------------------
  // Mode Handling
  // ----------------------------------------------------------------------------------
  const handleModeChange = (newMode: HumanizeMode) => {
    setMode(newMode);
    onModeChange?.(newMode);
  };

  // ----------------------------------------------------------------------------------
  // File Upload (.txt / .docx)
  // ----------------------------------------------------------------------------------
  const handleFileUpload = async (
    e: React.ChangeEvent<HTMLInputElement>
  ): Promise<void> => {
    const file = e.target.files?.[0];
    if (!file) return;

    setError("");
    setFileName(file.name);

    try {
      if (file.type === "text/plain" || file.name.endsWith(".txt")) {
        const text = await file.text();
        setInputText(text);
      } else if (
        file.type ===
          "application/vnd.openxmlformats-officedocument.wordprocessingml.document" ||
        file.name.endsWith(".docx")
      ) {
        const reader = new FileReader();
        reader.onload = async (event) => {
          try {
            const arrayBuffer = event.target?.result as ArrayBuffer;
            // Dynamic import for lightweight initial bundle
            const mammoth = await import("mammoth");
            const result = await mammoth.extractRawText({ arrayBuffer });
            setInputText(result.value || "");
          } catch (docxErr) {
            console.error(docxErr);
            setError("Failed to parse DOCX file");
          }
        };
        reader.readAsArrayBuffer(file);
      } else {
        setError("Unsupported file type. Please upload .txt or .docx");
      }
    } catch (err) {
      console.error(err);
      setError("Error reading file");
    }
  };

  // ----------------------------------------------------------------------------------
  // Hash-based Cache Lookup
  // ----------------------------------------------------------------------------------
  const checkHumanizedText = useCallback(
    async (text: string): Promise<HumanizedTextRecord | null> => {
      const user = getCurrentUser();
      if (!user) return null;

      try {
        const textHash = await sha256(text);
        const cached = await findCachedHumanizedText(db, user.uid, textHash);
        return cached;
      } catch (e) {
        console.warn("[checkHumanizedText] Error:", e);
        return null;
      }
    },
    []
  );

  // ----------------------------------------------------------------------------------
  // Copy & Download helpers
  // ----------------------------------------------------------------------------------
  const copyOutput = () => {
    if (!outputText) return;
    navigator.clipboard.writeText(outputText);
    setCopied(true);
    window.setTimeout(() => setCopied(false), 2000);
  };

  const downloadOutput = () => {
    if (!outputText) return;
    const blob = new Blob([outputText], { type: "text/plain" });
    const url = URL.createObjectURL(blob);
    const a = document.createElement("a");
    a.href = url;
    a.download = `humanized-text-${Date.now()}.txt`;
    a.click();
    URL.revokeObjectURL(url);
  };

  // ----------------------------------------------------------------------------------
  // Session Flow
  // ----------------------------------------------------------------------------------

  /**
   * Entry point from the "Humanize" button.
   * 1) Ensures user is logged in (redirects if not).
   * 2) Saves session start time.
   * 3) Increments totalSessions immediately.
   * 4) Calls humanizeText() which handles cache/API + result writes.
   */
  const handleHumanizeClick = async () => {
    const user = getCurrentUser();
    if (!user) {
      navigate("/login");
      return;
    }

    // Start a new session
    sessionStartRef.current = Date.now();

    // Count this as a session start (you can move this to success if you only
    // want to count successful sessions).
    await incrementTotalSessions(db);

    // Proceed with processing
    await humanizeText();
  };

  /**
   * Compute duration since session start and write to average if we have a start time.
   * We use "minutes" as our stored unit (rounded).
   */
  const finalizeSessionDuration = async () => {
    if (!sessionStartRef.current) return;
    const ms = Date.now() - sessionStartRef.current;
    const durationMinutes = msToWholeMinutes(ms);
    await updateAverageSessionTime(db, durationMinutes);
    sessionStartRef.current = null;
  };

  // ----------------------------------------------------------------------------------
  // Humanization Orchestration
  // ----------------------------------------------------------------------------------

  /**
   * Central function that:
   * - Validates input
   * - Checks cache
   * - Calls the API if needed
   * - Writes Firestore stats and activity logs
   * - Updates average session time
   */
  const humanizeText = async () => {
    if (!inputText.trim()) {
      setError("Please enter or upload text to humanize");
      return;
    }

    const wordCount = countWords(inputText);
    if (wordCount > 6000) {
      setError(`Word limit exceeded. Max 6,000 words. Current: ${wordCount}.`);
      return;
    }

    const user = getCurrentUser();
    if (!user) {
      setError("Please log in to continue");
      navigate("/login");
      return;
    }

    try {
      setLoading(true);
      setError("");

      // Step 1: Cache lookup
      const cached = await checkHumanizedText(inputText);
      if (cached?.humanizedText) {
        setOutputText(cached.humanizedText);

        // Step 2a: Update stats for a successful "result" (from cache)
        await bumpContentStats(db, wordCount);

        // Step 2b: Update average session time
        await finalizeSessionDuration();

        // Step 2c: Log activity
        await logActivity(db, {
          email: user.email ?? null,
          action: "Humanized Text (cache)",
          mode,
          wordCount,
          type: "humanizer",
        });

        return; // Done
      }

      // Step 2: Call backend API
      const resp = await fetch("https://humanizerx.pro/api/routes.php", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          text: inputText,
          mode,
          userId: user.uid,
        }),
      });

      let data: HumanizerAPIResponse | null = null;
      try {
        data = (await resp.json()) as HumanizerAPIResponse;
      } catch {
        data = null;
      }

      if (!resp.ok || !data || !data.success || !data.humanizedText) {
        const msg =
          data?.error ||
          `Failed to humanize text (HTTP ${resp.status}). Please try again.`;
        setError(msg);

        // NOTE: If you only want to count successful sessions, consider decrementing
        // totalSessions here, or move the increment to after success. We keep the counter
        // as-is to reflect attempted sessions. We also skip average time update on error.
        return;
      }

      // Step 3: Display result
      setOutputText(data.humanizedText);

      // Step 4: Save to cache (best-effort)
      try {
        await saveHumanizedText(db, {
          userId: user.uid,
          originalText: inputText, // keep or remove based on your privacy needs
          textHash: await sha256(inputText),
          humanizedText: data.humanizedText,
        });
      } catch {
        /* non-fatal */
      }

      // Step 5: Update stats
      await bumpContentStats(db, wordCount);

      // Step 6: Average session time
      await finalizeSessionDuration();

      // Step 7: Log activity
      await logActivity(db, {
        email: user.email ?? null,
        action: "Humanized Text",
        mode,
        wordCount,
        type: "humanizer",
      });
    } catch (err: any) {
      console.error(err);
      setError(err?.message || "Error processing text");
      // On error, we do not finalize session time; you can choose to do it if desired.
    } finally {
      setLoading(false);
    }
  };

  // ----------------------------------------------------------------------------------
  // Optional: Persist last used mode locally (so it survives reloads)
  // ----------------------------------------------------------------------------------
  useEffect(() => {
    const lastMode = safeLocalGet<HumanizeMode>("humanizer:lastMode", "normal");
    if (lastMode !== mode) {
      setMode(lastMode);
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  useEffect(() => {
    safeLocalSet("humanizer:lastMode", mode);
  }, [mode]);

  // ----------------------------------------------------------------------------------
  // Render
  // ----------------------------------------------------------------------------------

  return (
    <div className="space-y-6">
      {/* MODE SELECTION */}
      <div className={`${cardBg} rounded-xl shadow-lg p-6`}>
        <div className="flex items-start justify-between mb-4">
          <h2 className={`text-lg font-semibold ${textPrimary}`}>
            Humanization Mode
          </h2>
          <div
            className={`flex items-center gap-2 text-xs px-2 py-1 rounded-md ${
              theme === "dark"
                ? "bg-gray-700 text-gray-300"
                : "bg-gray-100 text-gray-600"
            }`}
            title="Modes adjust how aggressively the text is rephrased."
          >
            <Info size={14} />
            <span>Modes adjust rewrite strength</span>
          </div>
        </div>

        <div className="grid grid-cols-1 md:grid-cols-3 gap-3">
          {([
            { id: "normal", name: "Normal", desc: "Balanced humanization" },
            { id: "advanced", name: "Advanced", desc: "Stronger rephrasing" },
            { id: "expert", name: "Expert", desc: "Maximum transformation" },
          ] as { id: HumanizeMode; name: string; desc: string }[]).map(
            (modeOption) => (
              <button
                key={modeOption.id}
                onClick={() => handleModeChange(modeOption.id)}
                className={`p-3 rounded-lg border-2 transition-all text-left ${
                  mode === modeOption.id
                    ? "border-blue-500 bg-blue-50 dark:bg-blue-900/20"
                    : theme === "dark"
                    ? "border-gray-600 hover:border-gray-500"
                    : "border-gray-200 hover:border-gray-300"
                }`}
              >
                <div className={`font-medium ${textPrimary}`}>
                  {modeOption.name}
                </div>
                <div className={`text-sm ${textSecondary}`}>
                  {modeOption.desc}
                </div>
              </button>
            )
          )}
        </div>
      </div>

      {/* MAIN GRID */}
      <div className="grid lg:grid-cols-2 gap-6">
        {/* INPUT SECTION */}
        <div
          className={`${cardBg} rounded-xl shadow-lg p-6 border ${borderCard} space-y-4`}
        >
          <div className="flex justify-between items-center mb-2">
            <h3 className={`text-sm font-medium ${textPrimary}`}>Input Text</h3>
            <label className="flex items-center gap-2 px-4 py-2 bg-blue-600 text-white text-sm rounded-lg cursor-pointer hover:bg-blue-700 transition-colors shadow-md">
              <Upload size={18} />
              <span>Upload</span>
              <input
                type="file"
                accept=".txt,.docx"
                onChange={handleFileUpload}
                className="hidden"
              />
            </label>
          </div>

          <div
            className={`relative h-96 border rounded-xl shadow-inner transition-all duration-200 ${
              theme === "dark"
                ? "bg-gradient-to-br from-gray-800 to-gray-900 border-gray-700 text-white"
                : "bg-gradient-to-br from-gray-50 to-white border-gray-300 text-gray-900"
            }`}
          >
            <textarea
              value={inputText}
              onChange={(e) => setInputText(e.target.value)}
              placeholder="Paste text here or upload a file..."
              className="w-full h-full p-4 resize-none bg-transparent focus:ring-2 focus:ring-blue-500 focus:border-transparent rounded-xl"
              style={{
                lineHeight: "1.6",
                fontSize: "0.95rem",
                fontFamily: "Inter, ui-sans-serif, system-ui, -apple-system",
              }}
            />
            {fileName && (
              <p
                className={`absolute bottom-2 left-4 text-xs ${textSecondary} truncate max-w-[70%]`}
              >
                Uploaded: {fileName}
              </p>
            )}
          </div>

          <div className="flex justify-between items-center">
            <span
              className={`text-sm ${
                inputWordCount > 6000
                  ? theme === "dark"
                    ? "text-red-400"
                    : "text-red-600"
                  : textSecondary
              }`}
            >
              {inputWordCount.toLocaleString()} / 6,000 words
            </span>

            <button
              onClick={handleHumanizeClick}
              disabled={loading || !inputText.trim() || inputWordCount > 6000}
              className="px-6 py-3 bg-gradient-to-r from-indigo-900 to-slate-900 text-white rounded-lg font-medium hover:from-indigo-600 hover:to-slate-700 disabled:opacity-50 transition-all duration-200 flex items-center gap-2"
            >
              <Wand2 size={16} />
              {loading ? "Humanizing..." : "Humanize Text"}
            </button>
          </div>
        </div>
{/* OUTPUT SECTION */}
<div
  className={`${cardBg} rounded-xl shadow-lg p-6 border ${borderCard} space-y-4`}
>
  <div className="flex items-center justify-between">
    <h3 className={`text-lg font-semibold ${textPrimary}`}>
      Humanized Text
    </h3>

    <div className="flex gap-2">
      {outputText && (
        <>
          <button
            onClick={copyOutput}
            className={`flex items-center gap-2 px-3 py-2 rounded-lg transition-all duration-300 ${
              copied
                ? "bg-green-500 text-white"
                : "bg-gray-600 text-white hover:bg-gray-700"
            }`}
          >
            <Copy size={16} />
            {copied ? "Copied!" : "Copy"}
          </button>

          <button
            onClick={downloadOutput}
            className="flex items-center gap-2 px-3 py-2 bg-green-600 text-white rounded-lg hover:bg-green-700 transition-colors"
          >
            <Download size={16} />
            Download
          </button>
        </>
      )}
    </div>
  </div>

  {loading ? (
    <div className="flex flex-col items-center justify-center h-96">
      <div className="animate-spin rounded-full h-8 w-8 border-b-2 border-indigo-600 mb-3"></div>
      <p className={textSecondary}>Processing your text...</p>
    </div>
  ) : outputText ? (
    <>
      <div
        className={`w-full h-96 p-4 border rounded-xl overflow-y-auto shadow-inner text-sm leading-relaxed prose prose-sm max-w-none ${
          theme === "dark"
            ? "prose-invert bg-gradient-to-br from-gray-800 to-gray-900 border-gray-700 text-gray-100"
            : "bg-gradient-to-br from-gray-50 to-white border-gray-300 text-gray-800"
        }`}
        style={{ whiteSpace: "pre-wrap" }} // ✅ preserve spaces & blank lines
      >
        <ReactMarkdown remarkPlugins={[remarkGfm]}>
          {outputText}
        </ReactMarkdown>
      </div>

      <div className="flex justify-between items-center">
        <span className={`text-sm ${textSecondary}`}>
          {outputWordCount.toLocaleString()} words
        </span>
        <div
          className={`flex items-center gap-2 ${
            theme === "dark" ? "text-green-400" : "text-green-600"
          }`}
        >
          <CheckCircle size={16} />
          <span className="text-sm font-medium">
            Text humanized successfully
          </span>
        </div>
      </div>
    </>
  ) : (
    <div
      className={`flex flex-col items-center justify-center h-96 ${textSecondary}`}
    >
      <Wand2 size={48} className="mb-3 opacity-50" />
      <p>Humanized text will appear here...</p>
    </div>
  )}
</div>
      </div>

      {/* ERROR STATE */}
      {error && (
        <div
          className={`rounded-lg p-4 border ${
            theme === "dark"
              ? "bg-red-900/20 border-red-800 text-red-300"
              : "bg-red-50 border-red-200 text-red-700"
          }`}
        >
          <div className="flex items-center gap-2 text-sm">
            <AlertCircle size={16} />
            <span>{error}</span>
          </div>
        </div>
      )}

      {/* FOOTNOTE / HINTS */}
      <div
        className={`text-xs ${
          theme === "dark" ? "text-gray-400" : "text-gray-500"
        }`}
      >
      </div>
    </div>
  );
};

export default HumanizerInterface;

/* ---------------------------------------------------------------------------------- */
/*                                      EOF                                           */
/* ---------------------------------------------------------------------------------- */
