import { writable, derived } from "svelte/store";
import type { ConnectionStatus, PermissionRequest } from "$lib/types/messages";

export interface TerminalLine {
  id: string;
  type: "user" | "assistant" | "system" | "tool" | "error";
  content: string;
  timestamp: Date;
  toolName?: string;
}

function createClaudeStore() {
  const connectionStatus = writable<ConnectionStatus>("disconnected");
  const sessionId = writable<string | null>(null);
  const currentWorkingDirectory = writable<string>("");
  const terminalLines = writable<TerminalLine[]>([]);
  const pendingPermission = writable<PermissionRequest | null>(null);
  const isProcessing = writable<boolean>(false);
  const grantedTools = writable<Set<string>>(new Set());
  const pendingRetryMessage = writable<string | null>(null);

  let lineIdCounter = 0;

  function generateLineId(): string {
    return `line-${Date.now()}-${lineIdCounter++}`;
  }

  return {
    connectionStatus: { subscribe: connectionStatus.subscribe },
    sessionId: { subscribe: sessionId.subscribe },
    currentWorkingDirectory: { subscribe: currentWorkingDirectory.subscribe },
    terminalLines: { subscribe: terminalLines.subscribe },
    pendingPermission: { subscribe: pendingPermission.subscribe },
    isProcessing: { subscribe: isProcessing.subscribe },
    grantedTools: { subscribe: grantedTools.subscribe },
    pendingRetryMessage: { subscribe: pendingRetryMessage.subscribe },

    setConnectionStatus: (status: ConnectionStatus) => connectionStatus.set(status),
    setSessionId: (id: string | null) => sessionId.set(id),
    setWorkingDirectory: (dir: string) => currentWorkingDirectory.set(dir),
    setProcessing: (processing: boolean) => isProcessing.set(processing),

    addLine: (type: TerminalLine["type"], content: string, toolName?: string) => {
      const line: TerminalLine = {
        id: generateLineId(),
        type,
        content,
        timestamp: new Date(),
        toolName,
      };
      terminalLines.update((lines) => [...lines, line]);
      return line.id;
    },

    updateLine: (id: string, content: string) => {
      terminalLines.update((lines) =>
        lines.map((line) => (line.id === id ? { ...line, content } : line))
      );
    },

    appendToLine: (id: string, additionalContent: string) => {
      terminalLines.update((lines) =>
        lines.map((line) =>
          line.id === id ? { ...line, content: line.content + additionalContent } : line
        )
      );
    },

    clearTerminal: () => terminalLines.set([]),

    getConversationHistory: (): string => {
      let lines: TerminalLine[] = [];
      terminalLines.subscribe((l) => (lines = l))();

      // Filter to just user and assistant messages, skip system/tool noise
      const relevantLines = lines.filter(
        (line) => line.type === "user" || line.type === "assistant"
      );

      if (relevantLines.length === 0) return "";

      return relevantLines
        .map((line) => {
          const role = line.type === "user" ? "User" : "Assistant";
          return `${role}: ${line.content}`;
        })
        .join("\n\n");
    },

    requestPermission: (request: PermissionRequest) => pendingPermission.set(request),
    clearPermission: () => pendingPermission.set(null),

    grantTool: (toolName: string) => {
      grantedTools.update((tools) => {
        const newTools = new Set(tools);
        newTools.add(toolName);
        return newTools;
      });
    },

    getGrantedTools: (): string[] => {
      let tools: string[] = [];
      grantedTools.subscribe((t) => (tools = Array.from(t)))();
      return tools;
    },

    setPendingRetryMessage: (message: string | null) => pendingRetryMessage.set(message),

    reset: () => {
      connectionStatus.set("disconnected");
      sessionId.set(null);
      currentWorkingDirectory.set("");
      terminalLines.set([]);
      pendingPermission.set(null);
      isProcessing.set(false);
      grantedTools.set(new Set());
      pendingRetryMessage.set(null);
    },
  };
}

export const claudeStore = createClaudeStore();

export const hasPermissionPending = derived(
  claudeStore.pendingPermission,
  ($permission) => $permission !== null
);
