import { useState, useEffect, useCallback, createContext, useContext } from "react";
import { Routes, Route, useNavigate, useParams } from "react-router-dom";
import { Sidebar } from "./components/Sidebar";
import { Editor } from "./components/Editor";
import { Backlinks } from "./components/Backlinks";
import { GraphView } from "./components/GraphView";
import {
  listNotes,
  readNote,
  writeNote,
  getVaultPath,
  setVaultPath,
  ensureVault,
  getOrCreateDaily,
  type NoteEntry,
} from "./lib/commands";
import { extractWikilinks, type BacklinkEntry } from "./lib/wikilinks";

/* ── Vault Context ──────────────────────────────────────────── */
interface VaultContextType {
  vaultPath: string;
  notes: NoteEntry[];
  refreshNotes: () => Promise<void>;
  currentNote: string | null;
  setCurrentNote: (path: string | null) => void;
  noteContent: string;
  setNoteContent: (content: string) => void;
  backlinks: BacklinkEntry[];
  navigateToNote: (name: string) => void;
}

const VaultContext = createContext<VaultContextType>(null!);
export const useVault = () => useContext(VaultContext);

/* ── Main App ───────────────────────────────────────────────── */
export default function App() {
  const [vaultPath, setVaultPathState] = useState<string>("");
  const [notes, setNotes] = useState<NoteEntry[]>([]);
  const [currentNote, setCurrentNote] = useState<string | null>(null);
  const [noteContent, setNoteContent] = useState<string>("");
  const [backlinks, setBacklinks] = useState<BacklinkEntry[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const navigate = useNavigate();

  // Initialize vault
  useEffect(() => {
    (async () => {
      try {
        console.log("[GraphNotes] Initializing vault...");
        let path: string | null = null;

        try {
          path = await getVaultPath();
          console.log("[GraphNotes] Stored vault path:", path);
        } catch (e) {
          console.warn("[GraphNotes] getVaultPath failed:", e);
        }

        if (!path) {
          // Default to the project's vault directory
          path = "/home/amir/code/notes/vault";
          console.log("[GraphNotes] Using default vault path:", path);
          try {
            await setVaultPath(path);
          } catch (e) {
            console.warn("[GraphNotes] setVaultPath failed:", e);
          }
        }

        try {
          await ensureVault(path);
        } catch (e) {
          console.warn("[GraphNotes] ensureVault failed:", e);
        }

        setVaultPathState(path);
        console.log("[GraphNotes] Vault ready at:", path);
        setLoading(false);
      } catch (e) {
        console.error("[GraphNotes] Init failed:", e);
        setError(String(e));
        setLoading(false);
      }
    })();
  }, []);

  // Load notes when vault is ready
  const refreshNotes = useCallback(async () => {
    if (!vaultPath) return;
    const entries = await listNotes(vaultPath);
    setNotes(entries);
  }, [vaultPath]);

  useEffect(() => {
    if (vaultPath) refreshNotes();
  }, [vaultPath, refreshNotes]);

  // Build backlinks for current note
  useEffect(() => {
    if (!vaultPath || !currentNote || !notes.length) {
      setBacklinks([]);
      return;
    }

    (async () => {
      const currentName = currentNote
        .replace(/\.md$/, "")
        .split("/")
        .pop()
        ?.toLowerCase();
      if (!currentName) return;

      // Read all notes and find backlinks
      const allPaths = flattenNotes(notes);
      const entries: BacklinkEntry[] = [];

      for (const notePath of allPaths) {
        if (notePath === currentNote) continue;
        try {
          const content = await readNote(vaultPath, notePath);
          const links = extractWikilinks(content);
          for (const link of links) {
            if (link.target.toLowerCase() === currentName) {
              const lines = content.split("\n");
              const contextLine =
                lines.find((l) => l.includes(link.raw)) || "";
              entries.push({
                sourcePath: notePath,
                sourceName: notePath.replace(/\.md$/, "").split("/").pop() || notePath,
                context: contextLine.trim().substring(0, 200),
              });
            }
          }
        } catch {
          // Skip unreadable notes
        }
      }

      setBacklinks(entries);
    })();
  }, [vaultPath, currentNote, notes]);

  const navigateToNote = useCallback(
    (name: string) => {
      // Find the note by name (case-insensitive)
      const allPaths = flattenNotes(notes);
      const match = allPaths.find(
        (p) =>
          p
            .replace(/\.md$/, "")
            .split("/")
            .pop()
            ?.toLowerCase() === name.toLowerCase()
      );
      if (match) {
        navigate(`/note/${encodeURIComponent(match)}`);
      } else {
        // Create new note
        const newPath = `${name}.md`;
        writeNote(vaultPath, newPath, `# ${name}\n\n`).then(() => {
          refreshNotes();
          navigate(`/note/${encodeURIComponent(newPath)}`);
        });
      }
    },
    [notes, vaultPath, navigate, refreshNotes]
  );

  if (loading) {
    return (
      <div className="flex items-center justify-center h-screen">
        <div className="text-center animate-fade-in">
          <div className="text-4xl mb-4">📝</div>
          <p className="text-[var(--text-secondary)]">Loading vault...</p>
        </div>
      </div>
    );
  }

  if (error) {
    return (
      <div className="flex items-center justify-center h-screen">
        <div className="text-center animate-fade-in max-w-md">
          <div className="text-4xl mb-4">⚠️</div>
          <p className="text-[var(--text-primary)] font-semibold mb-2">Failed to load vault</p>
          <p className="text-[var(--text-muted)] text-sm">{error}</p>
        </div>
      </div>
    );
  }

  return (
    <VaultContext.Provider
      value={{
        vaultPath,
        notes,
        refreshNotes,
        currentNote,
        setCurrentNote,
        noteContent,
        setNoteContent,
        backlinks,
        navigateToNote,
      }}
    >
      <div className="flex h-screen w-screen overflow-hidden">
        <Sidebar />
        <Routes>
          <Route path="/" element={<WelcomeScreen />} />
          <Route path="/note/:path" element={<NoteView />} />
          <Route path="/daily" element={<DailyView />} />
          <Route path="/graph" element={<GraphView />} />
        </Routes>
      </div>
    </VaultContext.Provider>
  );
}

/* ── Note View ──────────────────────────────────────────────── */
function NoteView() {
  const { path } = useParams<{ path: string }>();
  const { vaultPath, setCurrentNote, noteContent, setNoteContent } = useVault();
  const decodedPath = decodeURIComponent(path || "");

  useEffect(() => {
    if (!decodedPath || !vaultPath) return;
    setCurrentNote(decodedPath);
    readNote(vaultPath, decodedPath).then(setNoteContent).catch(() => setNoteContent(""));
  }, [decodedPath, vaultPath, setCurrentNote, setNoteContent]);

  return (
    <div className="flex flex-1 overflow-hidden">
      <main className="flex-1 overflow-y-auto">
        <Editor />
      </main>
      <Backlinks />
    </div>
  );
}

/* ── Daily View ─────────────────────────────────────────────── */
function DailyView() {
  const { vaultPath, refreshNotes } = useVault();
  const navigate = useNavigate();

  useEffect(() => {
    if (!vaultPath) return;
    getOrCreateDaily(vaultPath).then((dailyPath) => {
      refreshNotes();
      navigate(`/note/${encodeURIComponent(dailyPath)}`, { replace: true });
    });
  }, [vaultPath, navigate, refreshNotes]);

  return (
    <div className="flex-1 flex items-center justify-center">
      <p className="text-[var(--text-muted)]">Creating daily note...</p>
    </div>
  );
}

/* ── Welcome Screen ─────────────────────────────────────────── */
function WelcomeScreen() {
  const navigate = useNavigate();

  return (
    <div className="welcome">
      <div className="welcome-card">
        <div className="welcome-icon">📝</div>
        <h1 className="welcome-title">Graph Notes</h1>
        <p className="welcome-subtitle">
          A local-first knowledge base with bidirectional linking
          and graph visualization. Your notes, your data.
        </p>
        <div className="welcome-actions">
          <button className="btn btn-primary" onClick={() => navigate("/daily")}>
            📅 Today's Note
          </button>
          <button className="btn" onClick={() => navigate("/graph")}>
            🔮 Graph View
          </button>
        </div>
      </div>
    </div>
  );
}

/* ── Helpers ────────────────────────────────────────────────── */
function flattenNotes(entries: NoteEntry[]): string[] {
  const paths: string[] = [];
  for (const entry of entries) {
    if (entry.is_dir && entry.children) {
      paths.push(...flattenNotes(entry.children));
    } else if (!entry.is_dir) {
      paths.push(entry.path);
    }
  }
  return paths;
}
