import { useEffect, useCallback, useState, useRef } from "react";
import { useLocation, useNavigate, useSearchParams } from "react-router-dom";
import { ChevronLeftIcon, PlusIcon } from "@heroicons/react/24/outline";
import type {
  ChatRequest,
  ChatMessage,
  ProjectInfo,
  PermissionMode,
  ToolResultMessage,
} from "../types";
import { useClaudeStreaming } from "../hooks/useClaudeStreaming";
import { useChatState } from "../hooks/chat/useChatState";
import { usePermissions } from "../hooks/chat/usePermissions";
import { usePermissionMode } from "../hooks/chat/usePermissionMode";
import { useAbortController } from "../hooks/chat/useAbortController";
import { useAutoHistoryLoader } from "../hooks/useHistoryLoader";
import { useFileCanvas } from "../hooks/useFileCanvas";
import { useSettings } from "../hooks/useSettings";
import { SettingsButton } from "./SettingsButton";
import { SettingsModal } from "./SettingsModal";
import { HistoryButton } from "./chat/HistoryButton";
import { ChatInput } from "./chat/ChatInput";
import { ChatMessages } from "./chat/ChatMessages";
import { HistoryView } from "./HistoryView";
import { FileCanvas } from "./FileCanvas";
import { FileList } from "./FileList";
import { getChatUrl, getProjectsUrl } from "../config/api";
import { KEYBOARD_SHORTCUTS } from "../utils/constants";
import {
  isAbsoluteFilePath,
  normalizeFilePath,
  normalizeWindowsPath,
  splitFilePath,
  toWindowsPath,
} from "../utils/pathUtils";
import type { StreamingContext } from "../hooks/streaming/useMessageProcessor";
import { extractFilePathsFromToolResult } from "../utils/fileExtractor";
import type { ToolMessage } from "../types";

export function ChatPage() {
  const location = useLocation();
  const navigate = useNavigate();
  const [searchParams] = useSearchParams();
  const [projects, setProjects] = useState<ProjectInfo[]>([]);
  const [isSettingsOpen, setIsSettingsOpen] = useState(false);
  const [isFileCanvasOpen, setIsFileCanvasOpen] = useState(false);
  const lastRecentScanRef = useRef<number>(0);
  const { settings } = useSettings();

  // Extract and normalize working directory from URL
  const workingDirectory = (() => {
    const rawPath = location.pathname.replace("/projects", "");
    if (!rawPath) return undefined;

    // URL decode the path
    const decodedPath = decodeURIComponent(rawPath);

    // Normalize Windows paths (remove leading slash from /C:/... format)
    return normalizeWindowsPath(decodedPath);
  })();

  const workingDirectoryForApi = workingDirectory
    ? toWindowsPath(workingDirectory)
    : undefined;

  // Get current view and sessionId from query parameters
  const currentView = searchParams.get("view");
  const sessionId = searchParams.get("sessionId");
  const isHistoryView = currentView === "history";
  const isLoadedConversation = !!sessionId && !isHistoryView;

  const { processStreamLine } = useClaudeStreaming();
  const { abortRequest, createAbortHandler } = useAbortController();

  // File canvas hook
  const fileCanvas = useFileCanvas(workingDirectory);

  // Permission mode state management
  const { permissionMode, setPermissionMode } = usePermissionMode();

  // Get encoded name for current working directory
  const getEncodedName = useCallback(() => {
    if (!workingDirectory || !projects.length) {
      return null;
    }

    const project = projects.find((p) => p.path === workingDirectory);

    // Normalize paths for comparison (handle Windows path issues)
    const normalizedWorking = normalizeWindowsPath(workingDirectory);
    const normalizedProject = projects.find(
      (p) => normalizeWindowsPath(p.path) === normalizedWorking,
    );

    // Use normalized result if exact match fails
    const finalProject = project || normalizedProject;

    return finalProject?.encodedName || null;
  }, [workingDirectory, projects]);

  // Load conversation history if sessionId is provided
  const {
    messages: historyMessages,
    loading: historyLoading,
    error: historyError,
    sessionId: loadedSessionId,
  } = useAutoHistoryLoader(
    getEncodedName() || undefined,
    sessionId || undefined,
    workingDirectoryForApi,
  );

  // Initialize chat state with loaded history
  const {
    messages,
    input,
    isLoading,
    currentSessionId,
    currentRequestId,
    hasShownInitMessage,
    currentAssistantMessage,
    setInput,
    setMessages,
    setCurrentSessionId,
    setHasShownInitMessage,
    setHasReceivedInit,
    setCurrentAssistantMessage,
    addMessage,
    updateLastMessage,
    clearInput,
    generateRequestId,
    resetRequestState,
    startRequest,
  } = useChatState({
    initialMessages: historyMessages,
    initialSessionId: loadedSessionId || undefined,
  });

  // Extract file paths from new tool messages and results
  useEffect(() => {
    if (!isHistoryView && !historyLoading && messages.length > 0) {
      // Get the last few messages to check for new file creations
      const recentMessages = messages.slice(-10);

      const buildFileInfoRequest = (filePath: string) => {
        const normalizedPath = normalizeFilePath(filePath, workingDirectory) || filePath;
        if (isAbsoluteFilePath(normalizedPath)) {
          const { directory, fileName } = splitFilePath(normalizedPath);
          return {
            path: fileName,
            workingDirectory: directory || workingDirectory,
            normalizedPath,
          };
        }
        return {
          path: normalizedPath,
          workingDirectory,
          normalizedPath,
        };
      };

      const ensureFileExists = async (filePath: string) => {
        if (!workingDirectory) return;

        const request = buildFileInfoRequest(filePath);
        if (!request.workingDirectory) return;

        const exists = fileCanvas.files.some((f) => f.path === request.normalizedPath);
        if (exists) return;

        const params = new URLSearchParams({
          path: request.path,
          workingDirectory: request.workingDirectory,
        });

        try {
          const response = await fetch(`/api/file/info?${params}`);
          if (!response.ok) return;
          const data = await response.json();
          if (data?.path) {
            fileCanvas.addFile(filePath, data.size || 0);
          }
        } catch (error) {
          console.debug("Failed to check file info:", error);
        }
      };

      const pendingChecks: Promise<void>[] = [];
      const scanRecentFiles = async () => {
        if (!workingDirectory) return;
        if (!recentMessages.some((message) => message.type === "tool" || message.type === "tool_result")) {
          return;
        }

        const latestTimestamp = recentMessages.reduce((latest, message) => {
          return Math.max(latest, message.timestamp || 0);
        }, 0);

        const since = Math.max(latestTimestamp - 2000, lastRecentScanRef.current);
        lastRecentScanRef.current = Date.now();

        const params = new URLSearchParams({
          workingDirectory,
          since: String(since),
        });

        try {
          const response = await fetch(`/api/files/recent?${params}`);
          if (!response.ok) return;
          const data = await response.json();
          if (!data?.files || !Array.isArray(data.files)) return;

          for (const file of data.files) {
            if (!file?.path) continue;
            const normalizedPath = normalizeFilePath(file.path, workingDirectory) || file.path;
            const exists = fileCanvas.files.some((f) => f.path === normalizedPath);
            if (!exists) {
              fileCanvas.addFile(file.path, file.size || 0);
            }
          }
        } catch (error) {
          console.debug("Failed to scan recent files:", error);
        }
      };

      for (const message of recentMessages) {
        // Check tool messages for file paths (from Write tool input)
        if (message.type === "tool") {
          const toolMsg = message as ToolMessage & { filePaths?: string[] };

          // File paths are now extracted from tool input and stored in the message
          if (toolMsg.filePaths && toolMsg.filePaths.length > 0) {
            for (const filePath of toolMsg.filePaths) {
              pendingChecks.push(ensureFileExists(filePath));
            }
          }
        }

        // Also check tool results as fallback
        if (message.type === "tool_result") {
          const toolResult = message as ToolResultMessage;

          // Extract file paths from the tool result
          const filePaths = extractFilePathsFromToolResult(
            toolResult.toolName,
            toolResult.content,
          );

          // Add each new file to the canvas
          for (const filePath of filePaths) {
            pendingChecks.push(ensureFileExists(filePath));
          }
        }
      }

      if (pendingChecks.length > 0) {
        void Promise.allSettled(pendingChecks);
      }

      void scanRecentFiles();
    }
  }, [messages, isHistoryView, historyLoading, fileCanvas, workingDirectory]);

  useEffect(() => {
    if (!isLoadedConversation) return;
    if (historyLoading) return;
    if (!workingDirectory) return;
    if (messages.length === 0) return;

    const buildFileInfoRequest = (filePath: string) => {
      const normalizedPath = normalizeFilePath(filePath, workingDirectory) || filePath;
      if (isAbsoluteFilePath(normalizedPath)) {
        const { directory, fileName } = splitFilePath(normalizedPath);
        return {
          path: fileName,
          workingDirectory: directory || workingDirectory,
          normalizedPath,
        };
      }
      return {
        path: normalizedPath,
        workingDirectory,
        normalizedPath,
      };
    };

    const ensureFileExists = async (filePath: string) => {
      const request = buildFileInfoRequest(filePath);
      if (!request.workingDirectory) return;

      const exists = fileCanvas.files.some((f) => f.path === request.normalizedPath);
      if (exists) return;

      const params = new URLSearchParams({
        path: request.path,
        workingDirectory: request.workingDirectory,
      });

      try {
        const response = await fetch(`/api/file/info?${params}`);
        if (!response.ok) return;
        const data = await response.json();
        if (data?.path) {
          fileCanvas.addFile(filePath, data.size || 0);
        }
      } catch (error) {
        console.debug("Failed to check file info:", error);
      }
    };

    const pendingChecks: Promise<void>[] = [];

    for (const message of messages) {
      if (message.type === "tool") {
        const toolMsg = message as ToolMessage & { filePaths?: string[] };
        if (toolMsg.filePaths && toolMsg.filePaths.length > 0) {
          for (const filePath of toolMsg.filePaths) {
            pendingChecks.push(ensureFileExists(filePath));
          }
        }
      }

      if (message.type === "tool_result") {
        const toolResult = message as ToolResultMessage;
        const filePaths = extractFilePathsFromToolResult(
          toolResult.toolName,
          toolResult.content,
        );
        for (const filePath of filePaths) {
          pendingChecks.push(ensureFileExists(filePath));
        }
      }
    }

    if (pendingChecks.length > 0) {
      void Promise.allSettled(pendingChecks);
    }
  }, [messages, isLoadedConversation, historyLoading, fileCanvas, workingDirectory]);

  const {
    allowedTools,
    permissionRequest,
    showPermissionRequest,
    closePermissionRequest,
    allowToolTemporary,
    allowToolPermanent,
    isPermissionMode,
    planModeRequest,
    showPlanModeRequest,
    closePlanModeRequest,
    updatePermissionMode,
  } = usePermissions({
    onPermissionModeChange: setPermissionMode,
  });

  const handlePermissionError = useCallback(
    (toolName: string, patterns: string[], toolUseId: string) => {
      // Check if this is an ExitPlanMode permission error
      if (patterns.includes("ExitPlanMode")) {
        // For ExitPlanMode, show plan permission interface instead of regular permission
        showPlanModeRequest(""); // Empty plan content since it was already displayed
      } else {
        showPermissionRequest(toolName, patterns, toolUseId);
      }
    },
    [showPermissionRequest, showPlanModeRequest],
  );

  const sendMessage = useCallback(
    async (
      messageContent?: string,
      tools?: string[],
      hideUserMessage = false,
      overridePermissionMode?: PermissionMode,
    ) => {
      const content = messageContent || input.trim();
      if (!content || isLoading) return;

      const requestId = generateRequestId();

      // Only add user message to chat if not hidden
      if (!hideUserMessage) {
        const userMessage: ChatMessage = {
          type: "chat",
          role: "user",
          content: content,
          timestamp: Date.now(),
        };
        addMessage(userMessage);
      }

      if (!messageContent) clearInput();
      startRequest();

      try {
        const response = await fetch(getChatUrl(), {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({
            message: content,
            requestId,
            ...(currentSessionId ? { sessionId: currentSessionId } : {}),
            allowedTools: tools || allowedTools,
            ...(workingDirectory ? { workingDirectory } : {}),
            permissionMode: overridePermissionMode || permissionMode,
            ...(settings.model ? { model: settings.model } : {}),
          } as ChatRequest),
        });

        if (!response.body) throw new Error("No response body");

        const reader = response.body.getReader();
        const decoder = new TextDecoder();

        // Local state for this streaming session
        let localHasReceivedInit = false;
        let shouldAbort = false;

        const streamingContext: StreamingContext = {
          currentAssistantMessage,
          setCurrentAssistantMessage,
          addMessage,
          updateLastMessage,
          onSessionId: setCurrentSessionId,
          shouldShowInitMessage: () => !hasShownInitMessage,
          onInitMessageShown: () => setHasShownInitMessage(true),
          get hasReceivedInit() {
            return localHasReceivedInit;
          },
          setHasReceivedInit: (received: boolean) => {
            localHasReceivedInit = received;
            setHasReceivedInit(received);
          },
          onPermissionError: handlePermissionError,
          onAbortRequest: async () => {
            shouldAbort = true;
            await createAbortHandler(requestId)();
          },
        };

        while (true) {
          const { done, value } = await reader.read();
          if (done || shouldAbort) break;

          const chunk = decoder.decode(value);
          const lines = chunk.split("\n").filter((line) => line.trim());

          for (const line of lines) {
            if (shouldAbort) break;
            processStreamLine(line, streamingContext);
          }

          if (shouldAbort) break;
        }
      } catch (error) {
        console.error("Failed to send message:", error);
        addMessage({
          type: "chat",
          role: "assistant",
          content: "Error: Failed to get response",
          timestamp: Date.now(),
        });
      } finally {
        resetRequestState();
      }
    },
    [
      input,
      isLoading,
      currentSessionId,
      allowedTools,
      hasShownInitMessage,
      currentAssistantMessage,
      workingDirectory,
      permissionMode,
      settings.model,
      generateRequestId,
      clearInput,
      startRequest,
      addMessage,
      updateLastMessage,
      setCurrentSessionId,
      setHasShownInitMessage,
      setHasReceivedInit,
      setCurrentAssistantMessage,
      resetRequestState,
      processStreamLine,
      handlePermissionError,
      createAbortHandler,
    ],
  );

  const handleAbort = useCallback(() => {
    abortRequest(currentRequestId, isLoading, resetRequestState);
  }, [abortRequest, currentRequestId, isLoading, resetRequestState]);

  // Permission request handlers
  const handlePermissionAllow = useCallback(() => {
    if (!permissionRequest) return;

    // Add all patterns temporarily
    let updatedAllowedTools = allowedTools;
    permissionRequest.patterns.forEach((pattern) => {
      updatedAllowedTools = allowToolTemporary(pattern, updatedAllowedTools);
    });

    closePermissionRequest();

    if (currentSessionId) {
      sendMessage("continue", updatedAllowedTools, true);
    }
  }, [
    permissionRequest,
    currentSessionId,
    sendMessage,
    allowedTools,
    allowToolTemporary,
    closePermissionRequest,
  ]);

  const handlePermissionAllowPermanent = useCallback(() => {
    if (!permissionRequest) return;

    // Add all patterns permanently
    let updatedAllowedTools = allowedTools;
    permissionRequest.patterns.forEach((pattern) => {
      updatedAllowedTools = allowToolPermanent(pattern, updatedAllowedTools);
    });

    closePermissionRequest();

    if (currentSessionId) {
      sendMessage("continue", updatedAllowedTools, true);
    }
  }, [
    permissionRequest,
    currentSessionId,
    sendMessage,
    allowedTools,
    allowToolPermanent,
    closePermissionRequest,
  ]);

  const handlePermissionDeny = useCallback(() => {
    closePermissionRequest();
  }, [closePermissionRequest]);

  // Plan mode request handlers
  const handlePlanAcceptWithEdits = useCallback(() => {
    updatePermissionMode("acceptEdits");
    closePlanModeRequest();
    if (currentSessionId) {
      sendMessage("accept", allowedTools, true, "acceptEdits");
    }
  }, [
    updatePermissionMode,
    closePlanModeRequest,
    currentSessionId,
    sendMessage,
    allowedTools,
  ]);

  const handlePlanAcceptDefault = useCallback(() => {
    updatePermissionMode("default");
    closePlanModeRequest();
    if (currentSessionId) {
      sendMessage("accept", allowedTools, true, "default");
    }
  }, [
    updatePermissionMode,
    closePlanModeRequest,
    currentSessionId,
    sendMessage,
    allowedTools,
  ]);

  const handlePlanKeepPlanning = useCallback(() => {
    updatePermissionMode("plan");
    closePlanModeRequest();
  }, [updatePermissionMode, closePlanModeRequest]);

  // Create permission data for inline permission interface
  const permissionData = permissionRequest
    ? {
        patterns: permissionRequest.patterns,
        onAllow: handlePermissionAllow,
        onAllowPermanent: handlePermissionAllowPermanent,
        onDeny: handlePermissionDeny,
      }
    : undefined;

  // Create plan permission data for plan mode interface
  const planPermissionData = planModeRequest
    ? {
        onAcceptWithEdits: handlePlanAcceptWithEdits,
        onAcceptDefault: handlePlanAcceptDefault,
        onKeepPlanning: handlePlanKeepPlanning,
      }
    : undefined;

  const handleHistoryClick = useCallback(() => {
    const searchParams = new URLSearchParams();
    searchParams.set("view", "history");
    navigate({ search: searchParams.toString() });
  }, [navigate]);

  const handleSettingsClick = useCallback(() => {
    setIsSettingsOpen(true);
  }, []);

  const handleSettingsClose = useCallback(() => {
    setIsSettingsOpen(false);
  }, []);

  // Load projects to get encodedName mapping
  useEffect(() => {
    const loadProjects = async () => {
      try {
        const response = await fetch(getProjectsUrl());
        if (response.ok) {
          const data = await response.json();
          setProjects(data.projects || []);
        }
      } catch (error) {
        console.error("Failed to load projects:", error);
      }
    };
    loadProjects();
  }, []);

  const handleBackToChat = useCallback(() => {
    navigate({ search: "" });
  }, [navigate]);

  const handleBackToHistory = useCallback(() => {
    const searchParams = new URLSearchParams();
    searchParams.set("view", "history");
    navigate({ search: searchParams.toString() });
  }, [navigate]);

  const handleBackToProjects = useCallback(() => {
    navigate("/");
  }, [navigate]);

  const handleBackToProjectChat = useCallback(() => {
    if (workingDirectory) {
      navigate(`/projects/${workingDirectory}`);
    }
  }, [navigate, workingDirectory]);

  const handleNewChat = useCallback(() => {
    if (isLoading && currentRequestId) {
      handleAbort();
    }
    resetRequestState();
    clearInput();
    setMessages([]);
    setCurrentSessionId(null);
    setHasShownInitMessage(false);
    setHasReceivedInit(false);
    setCurrentAssistantMessage(null);
    closePermissionRequest();
    closePlanModeRequest();
    if (workingDirectory) {
      navigate(`/projects/${workingDirectory}`);
    } else {
      navigate({ search: "" });
    }
  }, [
    isLoading,
    currentRequestId,
    handleAbort,
    resetRequestState,
    clearInput,
    setMessages,
    setCurrentSessionId,
    setHasShownInitMessage,
    setHasReceivedInit,
    setCurrentAssistantMessage,
    closePermissionRequest,
    closePlanModeRequest,
    navigate,
    workingDirectory,
  ]);

  // Handle global keyboard shortcuts
  useEffect(() => {
    const handleGlobalKeyDown = (e: KeyboardEvent) => {
      if (e.key === KEYBOARD_SHORTCUTS.ABORT && isLoading && currentRequestId) {
        e.preventDefault();
        handleAbort();
      }
    };

    document.addEventListener("keydown", handleGlobalKeyDown);
    return () => document.removeEventListener("keydown", handleGlobalKeyDown);
  }, [isLoading, currentRequestId, handleAbort]);

  return (
    <div className="min-h-screen bg-slate-50 dark:bg-slate-900 transition-colors duration-300">
      <div className="max-w-7xl mx-auto p-3 sm:p-6 h-screen flex flex-col">
        {/* Header */}
        <div className="flex items-center justify-between mb-4 sm:mb-8 flex-shrink-0">
          <div className="flex items-center gap-4">
            {isHistoryView && (
              <button
                onClick={handleBackToChat}
                className="p-2 rounded-lg bg-white/80 dark:bg-slate-800/80 border border-slate-200 dark:border-slate-700 hover:bg-white dark:hover:bg-slate-800 transition-all duration-200 backdrop-blur-sm shadow-sm hover:shadow-md"
                aria-label="Back to chat"
              >
                <ChevronLeftIcon className="w-5 h-5 text-slate-600 dark:text-slate-400" />
              </button>
            )}
            {isLoadedConversation && (
              <button
                onClick={handleBackToHistory}
                className="p-2 rounded-lg bg-white/80 dark:bg-slate-800/80 border border-slate-200 dark:border-slate-700 hover:bg-white dark:hover:bg-slate-800 transition-all duration-200 backdrop-blur-sm shadow-sm hover:shadow-md"
                aria-label="Back to history"
              >
                <ChevronLeftIcon className="w-5 h-5 text-slate-600 dark:text-slate-400" />
              </button>
            )}
            <div>
              <nav aria-label="Breadcrumb">
                <div className="flex items-center">
                  <button
                    onClick={handleBackToProjects}
                    className="text-slate-800 dark:text-slate-100 text-lg sm:text-3xl font-bold tracking-tight hover:text-blue-600 dark:hover:text-blue-400 transition-colors duration-200 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 dark:focus:ring-offset-slate-900 rounded-md px-1 -mx-1"
                    aria-label="Back to project selection"
                  >
                    OpenCode Web UI
                  </button>
                  {(isHistoryView || sessionId) && (
                    <>
                      <span
                        className="text-slate-800 dark:text-slate-100 text-lg sm:text-3xl font-bold tracking-tight mx-3 select-none"
                        aria-hidden="true"
                      >
                        {" "}
                        ›{" "}
                      </span>
                      <h1
                        className="text-slate-800 dark:text-slate-100 text-lg sm:text-3xl font-bold tracking-tight"
                        aria-current="page"
                      >
                        {isHistoryView
                          ? "Conversation History"
                          : "Conversation"}
                      </h1>
                    </>
                  )}
                </div>
              </nav>
              {workingDirectory && (
                <div className="flex items-center text-sm font-mono mt-1">
                  <button
                    onClick={handleBackToProjectChat}
                    className="text-slate-600 dark:text-slate-400 hover:text-blue-600 dark:hover:text-blue-400 transition-colors duration-200 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 dark:focus:ring-offset-slate-900 rounded px-1 -mx-1 cursor-pointer"
                    aria-label={`Return to new chat in ${workingDirectory}`}
                  >
                    {workingDirectory}
                  </button>
                  {sessionId && (
                    <span className="ml-2 text-xs text-slate-600 dark:text-slate-400">
                      Session: {sessionId.substring(0, 8)}...
                    </span>
                  )}
                </div>
              )}
            </div>
          </div>
          <div className="flex items-center gap-3">
            {!isHistoryView && (
              <button
                onClick={handleNewChat}
                className="inline-flex items-center gap-2 px-4 py-2 rounded-lg bg-white/80 dark:bg-slate-800/80 border border-slate-200 dark:border-slate-700 hover:bg-white dark:hover:bg-slate-800 transition-all duration-200 backdrop-blur-sm shadow-sm hover:shadow-md text-sm font-medium text-slate-700 dark:text-slate-200"
                title="New conversation"
                aria-label="New conversation"
              >
                <PlusIcon className="w-4 h-4" />
                New Chat
              </button>
            )}
            {!isHistoryView && <HistoryButton onClick={handleHistoryClick} />}
            <button
              onClick={() => setIsFileCanvasOpen(!isFileCanvasOpen)}
              className={`p-2 rounded-lg transition-all duration-200 ${
                isFileCanvasOpen
                  ? "bg-blue-100 dark:bg-blue-900/30 text-blue-700 dark:text-blue-300"
                  : "bg-white/80 dark:bg-slate-800/80 border border-slate-200 dark:border-slate-700 text-slate-600 dark:text-slate-400 hover:text-slate-800 dark:hover:text-slate-200"
              }`}
              title={isFileCanvasOpen ? "Close file canvas" : "Open file canvas"}
              aria-label={isFileCanvasOpen ? "Close file canvas" : "Open file canvas"}
            >
              <svg
                className="w-5 h-5"
                fill="none"
                stroke="currentColor"
                viewBox="0 0 24 24"
              >
                <path
                  strokeLinecap="round"
                  strokeLinejoin="round"
                  strokeWidth={2}
                  d="M4 5a1 1 0 011-1h14a1 1 0 011 1v2a1 1 0 01-1 1H5a1 1 0 01-1-1V5zM4 13a1 1 0 011-1h6a1 1 0 011 1v6a1 1 0 01-1 1H5a1 1 0 01-1-1v-6zM16 13a1 1 0 011-1h2a1 1 0 011 1v6a1 1 0 01-1 1h-2a1 1 0 01-1-1v-6z"
                />
              </svg>
            </button>
            <SettingsButton onClick={handleSettingsClick} />
          </div>
        </div>

        {/* Main Content */}
        <div className="flex-1 flex gap-3 overflow-hidden">
          {/* Left side - Chat area */}
          <div className="flex-1 flex flex-col overflow-hidden">
            {isHistoryView ? (
              <HistoryView
                workingDirectory={workingDirectory}
                encodedName={getEncodedName()}
                onBack={handleBackToChat}
              />
            ) : historyLoading ? (
              /* Loading conversation history */
              <div className="flex-1 flex items-center justify-center">
                <div className="text-center">
                  <div className="w-8 h-8 border-2 border-slate-300 border-t-slate-600 rounded-full animate-spin mx-auto mb-4"></div>
                  <p className="text-slate-600 dark:text-slate-400">
                    Loading conversation history...
                  </p>
                </div>
              </div>
            ) : historyError ? (
              /* Error loading conversation history */
              <div className="flex-1 flex items-center justify-center">
                <div className="text-center max-w-md">
                  <div className="w-16 h-16 mx-auto mb-4 bg-red-100 dark:bg-red-900/20 rounded-full flex items-center justify-center">
                    <svg
                      className="w-8 h-8 text-red-500"
                      fill="none"
                      stroke="currentColor"
                      viewBox="0 0 24 24"
                    >
                      <path
                        strokeLinecap="round"
                        strokeLinejoin="round"
                        strokeWidth={2}
                        d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
                      />
                    </svg>
                  </div>
                  <h2 className="text-slate-800 dark:text-slate-100 text-xl font-semibold mb-2">
                    Error Loading Conversation
                  </h2>
                  <p className="text-slate-600 dark:text-slate-400 text-sm mb-4">
                    {historyError}
                  </p>
                  <button
                    onClick={() => navigate({ search: "" })}
                    className="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors"
                  >
                    Start New Conversation
                  </button>
                </div>
              </div>
            ) : (
              <>
                {/* Chat Messages */}
                <ChatMessages messages={messages} isLoading={isLoading} />

                {/* Input */}
                <ChatInput
                  input={input}
                  isLoading={isLoading}
                  currentRequestId={currentRequestId}
                  onInputChange={setInput}
                  onSubmit={() => sendMessage()}
                  onAbort={handleAbort}
                  permissionMode={permissionMode}
                  onPermissionModeChange={setPermissionMode}
                  showPermissions={isPermissionMode}
                  permissionData={permissionData}
                  planPermissionData={planPermissionData}
                />
              </>
            )}
          </div>

          {/* Right side - File canvas (desktop only) */}
          {isFileCanvasOpen && (
            <div className="hidden lg:flex w-96 flex-col overflow-hidden bg-white/70 dark:bg-slate-800/70 border border-slate-200/60 dark:border-slate-700/60 rounded-2xl shadow-sm backdrop-blur-sm">
              <div className="flex-1 flex flex-col overflow-hidden">
                {/* File list (upper section) */}
                <div className="h-1/3 flex flex-col border-b border-slate-200 dark:border-slate-700">
                  <FileList
                    files={fileCanvas.files}
                    selectedFile={fileCanvas.selectedFile}
                    onFileSelect={fileCanvas.selectFile}
                    onClearFiles={fileCanvas.clearFiles}
                  />
                </div>

                {/* File canvas (lower section) */}
                <div className="h-2/3 flex flex-col">
                  <FileCanvas
                    fileInfo={fileCanvas.selectedFile}
                    content={fileCanvas.fileContent}
                    base64={fileCanvas.fileBase64}
                    isLoading={fileCanvas.isLoading}
                    error={fileCanvas.error}
                  />
                </div>
              </div>
            </div>
          )}
        </div>

        {/* Settings Modal */}
        <SettingsModal isOpen={isSettingsOpen} onClose={handleSettingsClose} />
      </div>
    </div>
  );
}
