import { writable } from "svelte/store";
import { invoke } from "@tauri-apps/api/core";

export type ProjectFile = "PROJECT" | "REQUIREMENTS" | "ROADMAP" | "STATE" | "CODEBASE";

export const PROJECT_FILE_NAMES: Record<ProjectFile, string> = {
  PROJECT: "PROJECT.md",
  REQUIREMENTS: "REQUIREMENTS.md",
  ROADMAP: "ROADMAP.md",
  STATE: "STATE.md",
  CODEBASE: "CODEBASE.md",
};

export const PROJECT_TEMPLATES: Record<ProjectFile, string> = {
  PROJECT: `# Project Overview

## What is this project?

## Goals

## Tech Stack

## Architecture
`,
  REQUIREMENTS: `# Requirements

## Functional Requirements

## Non-Functional Requirements

## Out of Scope
`,
  ROADMAP: `# Roadmap

## Current Sprint

## Next Sprint

## Backlog

## Completed
`,
  STATE: `# Current State

## Last Updated

## What's Working

## In Progress

## Known Issues

## Next Steps
`,
  CODEBASE: "",
};

const PROJECT_FILES = Object.keys(PROJECT_FILE_NAMES) as ProjectFile[];

export interface ProjectScan {
  working_dir: string;
  file_tree: string;
  detected_type: string;
  key_files: string[];
}

function createProjectContextStore() {
  const contents = writable<Record<ProjectFile, string | null>>({
    PROJECT: null,
    REQUIREMENTS: null,
    ROADMAP: null,
    STATE: null,
    CODEBASE: null,
  });

  const isLoading = writable<Record<ProjectFile, boolean>>({
    PROJECT: false,
    REQUIREMENTS: false,
    ROADMAP: false,
    STATE: false,
    CODEBASE: false,
  });

  const isSaving = writable<Record<ProjectFile, boolean>>({
    PROJECT: false,
    REQUIREMENTS: false,
    ROADMAP: false,
    STATE: false,
    CODEBASE: false,
  });

  const activeFile = writable<ProjectFile>("PROJECT");
  const isMappingCodebase = writable<boolean>(false);

  async function loadFile(file: ProjectFile, workingDirectory: string): Promise<void> {
    isLoading.update((state) => ({ ...state, [file]: true }));
    try {
      const path = `${workingDirectory}/${PROJECT_FILE_NAMES[file]}`;
      const content = await invoke<string>("read_file_content", { path });
      contents.update((state) => ({ ...state, [file]: content }));
    } catch {
      contents.update((state) => ({ ...state, [file]: null }));
    } finally {
      isLoading.update((state) => ({ ...state, [file]: false }));
    }
  }

  async function saveFile(
    file: ProjectFile,
    content: string,
    workingDirectory: string
  ): Promise<boolean> {
    isSaving.update((state) => ({ ...state, [file]: true }));
    try {
      const path = `${workingDirectory}/${PROJECT_FILE_NAMES[file]}`;
      await invoke("write_file_content", { path, content });
      contents.update((state) => ({ ...state, [file]: content }));
      return true;
    } catch (error) {
      console.error("Failed to save project context file:", error);
      return false;
    } finally {
      isSaving.update((state) => ({ ...state, [file]: false }));
    }
  }

  async function loadAll(workingDirectory: string): Promise<void> {
    await Promise.all(PROJECT_FILES.map((file) => loadFile(file, workingDirectory)));
  }

  function setActiveFile(file: ProjectFile): void {
    activeFile.set(file);
  }

  function getTemplate(file: ProjectFile): string {
    return PROJECT_TEMPLATES[file];
  }

  async function mapCodebase(workingDirectory: string, conversationId: string): Promise<void> {
    isMappingCodebase.set(true);
    try {
      const scan = await invoke<ProjectScan>("scan_project", {
        workingDir: workingDirectory,
      });

      const prompt = buildCodebaseMapPrompt(scan);
      await invoke("send_prompt", { conversationId, message: prompt });
    } catch (error) {
      console.error("Failed to map codebase:", error);
      isMappingCodebase.set(false);
    }
  }

  function finishMapping(): void {
    isMappingCodebase.set(false);
  }

  return {
    contents: { subscribe: contents.subscribe },
    isLoading: { subscribe: isLoading.subscribe },
    isSaving: { subscribe: isSaving.subscribe },
    activeFile: { subscribe: activeFile.subscribe },
    isMappingCodebase: { subscribe: isMappingCodebase.subscribe },
    loadFile,
    saveFile,
    loadAll,
    setActiveFile,
    getTemplate,
    mapCodebase,
    finishMapping,
  };
}

function buildCodebaseMapPrompt(scan: ProjectScan): string {
  const keyFilesSection =
    scan.key_files.length > 0
      ? `\n\nKey files detected:\n${scan.key_files.map((f) => `- ${f}`).join("\n")}`
      : "";

  return `Please analyse this codebase and generate a comprehensive \`CODEBASE.md\` file in the working directory (${scan.working_dir}).

Project type detected: **${scan.detected_type}**${keyFilesSection}

Directory structure:
\`\`\`
${scan.file_tree}
\`\`\`

The CODEBASE.md file should include:
1. **Overview** — what the project does and its purpose
2. **Architecture** — key directories, how the code is organised, and the overall structure
3. **Key Components** — the most important files and modules, what they do, and how they interact
4. **Data Flow** — how data moves through the system (if applicable)
5. **Dependencies** — notable external dependencies and why they are used
6. **Development Notes** — anything helpful for a developer new to the codebase

Write the file concisely but thoroughly. Focus on information that helps a developer understand the codebase quickly. Use the actual file structure above to inform your analysis — read the key files as needed before writing.`;
}

export const projectContextStore = createProjectContextStore();

// Signal store for injecting context into the active InputBar.
// StatusBar sets this; InputBar subscribes and applies it to inputValue directly,
// then resets it to null so the signal only fires once.
export const injectTextStore = writable<string | null>(null);

// Appended silently to custom_instructions at connection time (never saved to config).
// Mirrors how CLAUDE.md works natively — Claude checks the files itself if they exist.
export const PROJECT_CONTEXT_SYSTEM_ADDENDUM = `

---
The following project context files may exist in your working directory. If they exist, read and refer to them as needed:
- PROJECT.md — project overview, goals, and architecture
- REQUIREMENTS.md — functional and non-functional requirements
- ROADMAP.md — current sprint, backlog, and completed work
- STATE.md — current state, known issues, and next steps
- CODEBASE.md — auto-generated codebase map and architecture overview`;
