import { useState, useRef, useCallback } from "react";

// =============================================
// TODO: Implement the debounce function
// =============================================
//
// A debounce function takes a callback and a delay, and returns
// a new function that:
//   1. Resets a timer on every call
//   2. Only invokes the callback after the caller stops calling
//      for `delay` milliseconds
//
// Signature:
//   function debounce<T extends (...args: any[]) => void>(
//     fn: T,
//     delay: number
//   ): (...args: Parameters<T>) => void
//
// Hints:
//   - Use setTimeout / clearTimeout
//   - Store the timer ID in a closure variable (let timer)
//   - Return a wrapper function that clears the old timer
//     and sets a new one each time it's called
//   - The wrapper should forward all arguments to fn

function debounce(fn: (...args: any[]) => void, delay: number) {
  // TODO: Your implementation here
  // For now it just calls fn immediately (no debouncing)
  return (...args: any[]) => {
    fn(...args);
  };
}

// =============================================
// Log entry type (DO NOT MODIFY)
// =============================================
interface LogEntry {
  id: number;
  text: string;
  timestamp: string;
  type: "raw" | "debounced";
}

export default function App() {
  const [query, setQuery] = useState("");
  const [logs, setLogs] = useState<LogEntry[]>([]);
  const logIdRef = useRef(0);

  // =============================================
  // Helper: adds a log entry (DO NOT MODIFY)
  // =============================================
  const addLog = (text: string, type: LogEntry["type"]) => {
    logIdRef.current += 1;
    setLogs((prev) =>
      [
        {
          id: logIdRef.current,
          text,
          timestamp: new Date().toLocaleTimeString("en-US", {
            hour12: false,
            hour: "2-digit",
            minute: "2-digit",
            second: "2-digit",
            fractionalSecondDigits: 3,
          }),
          type,
        },
        ...prev,
      ].slice(0, 50)
    );
  };

  // =============================================
  // Simulated API call — this should be debounced
  // =============================================
  const search = (value: string) => {
    addLog(`API call → "${value}"`, "debounced");
  };

  // TODO: Wrap `search` with your debounce function (500ms delay)
  // Hint: use useCallback so the debounced version is stable across renders
  //
  // const debouncedSearch = useCallback(debounce(search, 500), []);
  const debouncedSearch = search; // ← replace this line

  // =============================================
  // Input handler (DO NOT MODIFY)
  // =============================================
  const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const value = e.target.value;
    setQuery(value);
    addLog(`Keystroke → "${value}"`, "raw");
    debouncedSearch(value);
  };

  const clearLogs = () => setLogs([]);

  return (
    <div style={{ maxWidth: 600, margin: "0 auto", padding: 24, fontFamily: "system-ui" }}>
      <h2 style={{ fontSize: 20, fontWeight: 700, marginBottom: 4 }}>
        Custom Debounce
      </h2>
      <p style={{ fontSize: 14, color: "#666", marginBottom: 24 }}>
        Implement the <code>debounce</code> function at the top of this file.
        Right now every keystroke fires an API call — your debounce should
        batch them into one call after 500ms of silence.
      </p>

      {/* Search Input */}
      <div style={{ marginBottom: 20 }}>
        <label style={{ display: "block", fontSize: 14, fontWeight: 500, marginBottom: 8 }}>
          Search Input
        </label>
        <input
          type="text"
          value={query}
          onChange={handleChange}
          placeholder="Start typing to see debounce in action..."
          style={{
            width: "100%",
            padding: "10px 14px",
            border: "1px solid #d1d5db",
            borderRadius: 8,
            fontSize: 14,
            outline: "none",
            boxSizing: "border-box",
          }}
        />
      </div>

      {/* Event Log */}
      <div style={{ border: "1px solid #e5e7eb", borderRadius: 8, overflow: "hidden" }}>
        {/* Log header */}
        <div style={{
          display: "flex",
          justifyContent: "space-between",
          alignItems: "center",
          padding: "10px 14px",
          background: "#f9fafb",
          borderBottom: "1px solid #e5e7eb",
          fontSize: 13,
        }}>
          <span style={{ fontWeight: 600 }}>Event Log</span>
          <div style={{ display: "flex", alignItems: "center", gap: 16 }}>
            <span style={{ display: "flex", alignItems: "center", gap: 6 }}>
              <span style={{ width: 8, height: 8, borderRadius: "50%", background: "#d1d5db", display: "inline-block" }} />
              Keystroke
            </span>
            <span style={{ display: "flex", alignItems: "center", gap: 6 }}>
              <span style={{ width: 8, height: 8, borderRadius: "50%", background: "#22c55e", display: "inline-block" }} />
              API Call
            </span>
            <button onClick={clearLogs} style={{ color: "#999", cursor: "pointer" }}>
              Clear
            </button>
          </div>
        </div>

        {/* Log entries */}
        <div style={{ height: 300, overflowY: "auto" }}>
          {logs.length === 0 ? (
            <div style={{ display: "flex", alignItems: "center", justifyContent: "center", height: "100%", color: "#999", fontSize: 14 }}>
              Type in the search box to see events
            </div>
          ) : (
            logs.map((log) => (
              <div
                key={log.id}
                style={{
                  display: "flex",
                  alignItems: "center",
                  gap: 10,
                  padding: "8px 14px",
                  borderBottom: "1px solid #f3f4f6",
                  fontSize: 13,
                }}
              >
                <span style={{
                  width: 8,
                  height: 8,
                  borderRadius: "50%",
                  background: log.type === "raw" ? "#d1d5db" : "#22c55e",
                  flexShrink: 0,
                }} />
                <span style={{ fontFamily: "monospace", fontSize: 11, color: "#999", flexShrink: 0 }}>
                  {log.timestamp}
                </span>
                <span style={{
                  color: log.type === "raw" ? "#888" : "#111",
                  fontWeight: log.type === "raw" ? 400 : 600,
                }}>
                  {log.text}
                </span>
              </div>
            ))
          )}
        </div>
      </div>

      {/* Hint */}
      <div style={{
        marginTop: 24,
        padding: 16,
        background: "#f9fafb",
        borderLeft: "4px solid #111",
        borderRadius: "0 8px 8px 0",
        fontSize: 13,
        color: "#555",
      }}>
        <strong>Expected behavior:</strong> You should see many grey "Keystroke"
        entries but only <strong>one</strong> green "API call" entry after you
        stop typing for 500ms. If you see an API call on every keystroke, your
        debounce isn't working yet.
      </div>
    </div>
  );
}