import { json, type ActionFunctionArgs } from "@remix-run/node";
import { Form, useActionData, useNavigation, useSearchParams } from "@remix-run/react";
import { useState, useEffect, useRef } from "react";
import DeviceSelector from "../components/DeviceSelector";

export async function action({ request }: ActionFunctionArgs) {
  const formData = await request.formData();
  const command = formData.get("command") as string;
  const sessionId = formData.get("sessionId") as string;
  const deviceId = formData.get("deviceId") as string;

  try {
    const response = await fetch("http://localhost:8000/api/pm3/command", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        command,
        session_id: sessionId,
        device_id: deviceId,
      }),
    });

    const result = await response.json();
    return json(result);
  } catch (error) {
    return json({
      success: false,
      output: "",
      error: `Failed to execute command: ${error}`,
    });
  }
}

// Helper to get/set session from localStorage
const SESSION_STORAGE_KEY = "pm3_sessions";

function getStoredSession(deviceId: string): string | null {
  if (typeof window === "undefined") return null;
  try {
    const sessions = JSON.parse(localStorage.getItem(SESSION_STORAGE_KEY) || "{}");
    return sessions[deviceId] || null;
  } catch {
    return null;
  }
}

function storeSession(deviceId: string, sessionId: string): void {
  if (typeof window === "undefined") return;
  try {
    const sessions = JSON.parse(localStorage.getItem(SESSION_STORAGE_KEY) || "{}");
    sessions[deviceId] = sessionId;
    localStorage.setItem(SESSION_STORAGE_KEY, JSON.stringify(sessions));
  } catch {
    // Ignore storage errors
  }
}

function clearStoredSession(deviceId: string): void {
  if (typeof window === "undefined") return;
  try {
    const sessions = JSON.parse(localStorage.getItem(SESSION_STORAGE_KEY) || "{}");
    delete sessions[deviceId];
    localStorage.setItem(SESSION_STORAGE_KEY, JSON.stringify(sessions));
  } catch {
    // Ignore storage errors
  }
}

export default function Commands() {
  const actionData = useActionData<typeof action>();
  const navigation = useNavigation();
  const [searchParams] = useSearchParams();
  const [commandHistory, setCommandHistory] = useState<string[]>([]);
  const [historyIndex, setHistoryIndex] = useState(-1);
  const [sessionId, setSessionId] = useState<string | null>(null);
  const [selectedDeviceId, setSelectedDeviceId] = useState<string | null>(null);
  const [sessionError, setSessionError] = useState<string | null>(null);
  const inputRef = useRef<HTMLInputElement>(null);
  const outputRef = useRef<HTMLDivElement>(null);

  const isSubmitting = navigation.state === "submitting";

  // Create or reuse session when device is selected
  useEffect(() => {
    if (!selectedDeviceId) {
      setSessionId(null);
      setSessionError(null);
      return;
    }

    async function ensureSession() {
      // First, check if we have a stored session for this device
      const storedSessionId = getStoredSession(selectedDeviceId);

      if (storedSessionId) {
        // Try to verify the stored session is still valid by using it
        // We'll set it and if commands fail, we'll create a new one
        setSessionId(storedSessionId);
        setSessionError(null);
        return;
      }

      // No stored session, create a new one
      try {
        const response = await fetch("/api/system/session/create", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({
            device_id: selectedDeviceId,
            force_takeover: true,  // Take over any stale sessions
          }),
        });
        const data = await response.json();
        if (data.success) {
          setSessionId(data.session_id);
          storeSession(selectedDeviceId, data.session_id);
          setSessionError(null);
        } else {
          setSessionId(null);
          clearStoredSession(selectedDeviceId);
          setSessionError(data.error || "Failed to create session");
        }
      } catch (error) {
        console.error("Failed to create session:", error);
        setSessionId(null);
        setSessionError("Network error while creating session");
      }
    }
    ensureSession();
  }, [selectedDeviceId]);

  // Pre-fill command from URL param
  const prefilledCommand = searchParams.get("cmd")?.replace(/\+/g, " ") || "";

  // Add command to history
  useEffect(() => {
    if (actionData && "output" in actionData) {
      const form = document.querySelector("form") as HTMLFormElement;
      const commandInput = form?.querySelector('input[name="command"]') as HTMLInputElement;
      if (commandInput?.value) {
        setCommandHistory((prev) => [commandInput.value, ...prev].slice(0, 50));
        setHistoryIndex(-1);
      }
    }
  }, [actionData]);

  // Auto-scroll output
  useEffect(() => {
    if (outputRef.current) {
      outputRef.current.scrollTop = outputRef.current.scrollHeight;
    }
  }, [actionData]);

  // Handle keyboard shortcuts
  const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
    if (e.key === "ArrowUp") {
      e.preventDefault();
      if (historyIndex < commandHistory.length - 1) {
        const newIndex = historyIndex + 1;
        setHistoryIndex(newIndex);
        if (inputRef.current) {
          inputRef.current.value = commandHistory[newIndex];
        }
      }
    } else if (e.key === "ArrowDown") {
      e.preventDefault();
      if (historyIndex > 0) {
        const newIndex = historyIndex - 1;
        setHistoryIndex(newIndex);
        if (inputRef.current) {
          inputRef.current.value = commandHistory[newIndex];
        }
      } else if (historyIndex === 0) {
        setHistoryIndex(-1);
        if (inputRef.current) {
          inputRef.current.value = "";
        }
      }
    }
  };

  const quickCommands = [
    { label: "HW Status", cmd: "hw status", icon: "◈" },
    { label: "HW Version", cmd: "hw version", icon: "ⓘ" },
    { label: "HW Tune", cmd: "hw tune", icon: "📡" },
    { label: "HF Search", cmd: "hf search", icon: "🔍" },
    { label: "LF Search", cmd: "lf search", icon: "🔍" },
    { label: "HF List", cmd: "hf list", icon: "≡" },
  ];

  return (
    <div className="container">
      <h1 style={{ marginBottom: "var(--space-6)" }}>
        <span style={{ color: "var(--color-accent)" }}>▶</span> PM3 Commands
      </h1>

      {/* Device Selector */}
      <div style={{ marginBottom: "var(--space-4)" }}>
        <DeviceSelector
          selectedDeviceId={selectedDeviceId}
          onDeviceSelect={setSelectedDeviceId}
          showIdentifyButton={true}
          autoSelectSingle={true}
        />
      </div>

      {/* Session Error/Warning */}
      {selectedDeviceId && sessionError && (
        <div className="card" style={{ marginBottom: "var(--space-4)", borderColor: "var(--color-error)" }}>
          <div style={{ display: "flex", alignItems: "center", gap: "var(--space-3)" }}>
            <span style={{ fontSize: "1.5rem" }}>✗</span>
            <div>
              <strong>Session Error</strong>
              <p className="text-secondary" style={{ marginTop: "var(--space-1)", marginBottom: 0 }}>
                {sessionError}
              </p>
            </div>
          </div>
        </div>
      )}

      {selectedDeviceId && !sessionId && !sessionError && (
        <div className="card" style={{ marginBottom: "var(--space-4)", borderColor: "var(--color-warning)" }}>
          <div style={{ display: "flex", alignItems: "center", gap: "var(--space-3)" }}>
            <span style={{ fontSize: "1.5rem" }}>⚠</span>
            <div>
              <strong>Creating Session...</strong>
              <p className="text-secondary" style={{ marginTop: "var(--space-1)", marginBottom: 0 }}>
                Establishing connection to device...
              </p>
            </div>
          </div>
        </div>
      )}

      {/* Quick Commands */}
      <div className="card" style={{ marginBottom: "var(--space-4)" }}>
        <h3 className="card-title">Quick Commands</h3>
        <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(140px, 1fr))", gap: "var(--space-2)" }}>
          {quickCommands.map((qc) => (
            <button
              key={qc.cmd}
              onClick={() => {
                if (inputRef.current) {
                  inputRef.current.value = qc.cmd;
                  inputRef.current.focus();
                }
              }}
              className="btn btn-secondary"
              style={{ fontSize: "0.75rem", padding: "var(--space-2) var(--space-3)" }}
            >
              <span>{qc.icon}</span>
              <span>{qc.label}</span>
            </button>
          ))}
        </div>
      </div>

      {/* Command Input */}
      <div className="card" style={{ marginBottom: "var(--space-4)" }}>
        <Form method="post">
          <input type="hidden" name="sessionId" value={sessionId || ""} />
          <input type="hidden" name="deviceId" value={selectedDeviceId || ""} />
          <div className="form-group">
            <label htmlFor="command" className="label">
              Command
            </label>
            <div style={{ display: "flex", gap: "var(--space-2)" }}>
              <input
                ref={inputRef}
                type="text"
                id="command"
                name="command"
                className="input"
                placeholder={
                  !selectedDeviceId
                    ? "Select a device first..."
                    : !sessionId
                    ? "Creating session..."
                    : "Enter PM3 command (e.g., hw status)"
                }
                defaultValue={prefilledCommand}
                onKeyDown={handleKeyDown}
                disabled={!selectedDeviceId || !sessionId || isSubmitting}
                autoComplete="off"
                autoFocus={!!sessionId}
                style={{ flex: 1 }}
              />
              <button
                type="submit"
                className="btn btn-primary"
                disabled={!selectedDeviceId || !sessionId || isSubmitting}
                style={{ minWidth: "100px" }}
              >
                {isSubmitting ? (
                  <>
                    <span className="spinner"></span>
                    <span>Running...</span>
                  </>
                ) : (
                  <>
                    <span>▶</span>
                    <span>Execute</span>
                  </>
                )}
              </button>
            </div>
            <p className="text-muted" style={{ fontSize: "0.75rem", marginTop: "var(--space-2)", marginBottom: 0 }}>
              {selectedDeviceId && sessionId
                ? "Use ↑/↓ arrow keys to navigate command history"
                : !selectedDeviceId
                ? "Select a Proxmark3 device above to start executing commands"
                : "Waiting for session..."}
            </p>
          </div>
        </Form>
      </div>

      {/* Output Terminal */}
      <div className="card">
        <h3 className="card-title">Output</h3>
        {actionData ? (
          <div ref={outputRef} className="terminal">
            {actionData.success ? (
              <>
                <div style={{ color: "var(--color-primary)", marginBottom: "var(--space-2)" }}>
                  ▸ Command executed successfully
                </div>
                <pre style={{ margin: 0, whiteSpace: "pre-wrap", wordWrap: "break-word" }}>
                  {actionData.output || "(No output)"}
                </pre>
              </>
            ) : (
              <>
                <div style={{ color: "var(--color-error)", marginBottom: "var(--space-2)" }}>
                  ✗ Command failed
                </div>
                <pre style={{ margin: 0, color: "var(--color-error)", whiteSpace: "pre-wrap", wordWrap: "break-word" }}>
                  {actionData.error || "Unknown error"}
                </pre>
              </>
            )}
          </div>
        ) : (
          <div className="terminal" style={{ color: "var(--color-text-muted)", fontStyle: "italic" }}>
            Ready. Enter a command above and press Execute.
            <br /><br />
            <span style={{ color: "var(--color-text-secondary)" }}>Examples:</span>
            <br />
            • hw status — Check hardware status
            <br />
            • hw version — Show firmware version
            <br />
            • hf search — Search for HF tags
            <br />
            • lf search — Search for LF tags
          </div>
        )}
      </div>

      {/* Command History */}
      {commandHistory.length > 0 && (
        <div className="card" style={{ marginTop: "var(--space-4)" }}>
          <h3 className="card-title">Recent Commands</h3>
          <div style={{ display: "flex", flexDirection: "column", gap: "var(--space-2)" }}>
            {commandHistory.slice(0, 10).map((cmd, idx) => (
              <button
                key={idx}
                onClick={() => {
                  if (inputRef.current) {
                    inputRef.current.value = cmd;
                    inputRef.current.focus();
                  }
                }}
                className="btn btn-secondary"
                style={{
                  justifyContent: "flex-start",
                  fontFamily: "var(--font-mono)",
                  fontSize: "0.875rem",
                  textAlign: "left",
                }}
              >
                <span style={{ color: "var(--color-text-muted)" }}>▸</span>
                <span>{cmd}</span>
              </button>
            ))}
          </div>
        </div>
      )}
    </div>
  );
}
