/**
 * T080, T083-T084: Main application layout with two-pane design
 * Loads directory tree on mount and note + backlinks when path changes
 */
import { useState, useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
import { Plus, Settings as SettingsIcon, FolderPlus } from 'lucide-react';
import { ResizablePanelGroup, ResizablePanel, ResizableHandle } from '@/components/ui/resizable';
import { Button } from '@/components/ui/button';
import { Separator } from '@/components/ui/separator';
import { Alert, AlertDescription } from '@/components/ui/alert';
import { DirectoryTree } from '@/components/DirectoryTree';
import { DirectoryTreeSkeleton } from '@/components/DirectoryTreeSkeleton';
import { SearchBar } from '@/components/SearchBar';
import { NoteViewer } from '@/components/NoteViewer';
import { NoteViewerSkeleton } from '@/components/NoteViewerSkeleton';
import { NoteEditor } from '@/components/NoteEditor';
import { useToast } from '@/hooks/useToast';
import { GraphView } from '@/components/GraphView';
import {
  listNotes,
  getNote,
  getBacklinks,
  getIndexHealth,
  createNote,
  moveNote,
  type BacklinkResult,
  APIException,
} from '@/services/api';
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from '@/components/ui/dialog';
import { Input } from '@/components/ui/input';
import type { IndexHealth } from '@/types/search';
import type { Note, NoteSummary } from '@/types/note';
import { normalizeSlug } from '@/lib/wikilink';
import { Network } from 'lucide-react';
import { AUTH_TOKEN_CHANGED_EVENT, isDemoSession, login } from '@/services/auth';

export function MainApp() {
  const navigate = useNavigate();
  const toast = useToast();
  const [notes, setNotes] = useState<NoteSummary[]>([]);
  const [selectedPath, setSelectedPath] = useState<string | null>(null);
  const [currentNote, setCurrentNote] = useState<Note | null>(null);
  const [backlinks, setBacklinks] = useState<BacklinkResult[]>([]);
  const [isLoadingNotes, setIsLoadingNotes] = useState(true);
  const [isLoadingNote, setIsLoadingNote] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [isEditMode, setIsEditMode] = useState(false);
  const [isGraphView, setIsGraphView] = useState(false);
  const [indexHealth, setIndexHealth] = useState<IndexHealth | null>(null);
  const [isNewNoteDialogOpen, setIsNewNoteDialogOpen] = useState(false);
  const [newNoteName, setNewNoteName] = useState('');
  const [isCreatingNote, setIsCreatingNote] = useState(false);
  const [isNewFolderDialogOpen, setIsNewFolderDialogOpen] = useState(false);
  const [newFolderName, setNewFolderName] = useState('');
  const [isCreatingFolder, setIsCreatingFolder] = useState(false);
  const [isDemoMode, setIsDemoMode] = useState<boolean>(isDemoSession());

  useEffect(() => {
    const handleAuthChange = () => {
      const demo = isDemoSession();
      setIsDemoMode(demo);
      if (demo) {
        setIsEditMode(false);
      }
    };
    window.addEventListener(AUTH_TOKEN_CHANGED_EVENT, handleAuthChange);
    return () => {
      window.removeEventListener(AUTH_TOKEN_CHANGED_EVENT, handleAuthChange);
    };
  }, []);

  // T083: Load directory tree on mount
  // T119: Load index health
  useEffect(() => {
    const loadData = async () => {
      setIsLoadingNotes(true);
      setError(null);
      try {
        // Load notes and index health in parallel
        const [notesList, health] = await Promise.all([
          listNotes(),
          getIndexHealth().catch(() => null), // Don't fail if health unavailable
        ]);
        
        setNotes(notesList);
        setIndexHealth(health);
        
        // Auto-select first note if available
        if (notesList.length > 0 && !selectedPath) {
          setSelectedPath(notesList[0].note_path);
        }
      } catch (err) {
        if (err instanceof APIException) {
          setError(err.error);
        } else {
          setError('Failed to load notes');
        }
        console.error('Error loading notes:', err);
      } finally {
        setIsLoadingNotes(false);
      }
    };

    loadData();
  }, []);

  // T084: Load note and backlinks when path changes
  useEffect(() => {
    if (!selectedPath) {
      setCurrentNote(null);
      setBacklinks([]);
      return;
    }

    const loadNote = async () => {
      setIsLoadingNote(true);
      setError(null);
      try {
        const [note, noteBacklinks] = await Promise.all([
          getNote(selectedPath),
          getBacklinks(selectedPath),
        ]);
        setCurrentNote(note);
        setBacklinks(noteBacklinks);
      } catch (err) {
        if (err instanceof APIException) {
          setError(err.error);
        } else {
          setError('Failed to load note');
        }
        console.error('Error loading note:', err);
        setCurrentNote(null);
        setBacklinks([]);
      } finally {
        setIsLoadingNote(false);
      }
    };

    loadNote();
  }, [selectedPath]);

  // Handle wikilink clicks
  const handleWikilinkClick = async (linkText: string) => {
    const slug = normalizeSlug(linkText);
    console.log(`[Wikilink] Clicked: "${linkText}", Slug: "${slug}"`);
    
    // Try to find exact match first
    let targetNote = notes.find(
      (note) => normalizeSlug(note.title) === slug
    );

    // If not found, try path-based matching
    if (!targetNote) {
      targetNote = notes.find((note) => {
        const pathSlug = normalizeSlug(note.note_path.replace(/\.md$/, ''));
        // console.log(`Checking path: ${note.note_path}, Slug: ${pathSlug}`);
        return pathSlug.endsWith(slug);
      });
    }

    if (targetNote) {
      console.log(`[Wikilink] Found target: ${targetNote.note_path}`);
      setSelectedPath(targetNote.note_path);
    } else {
      // TODO: Show "Create note" dialog
      console.log('Note not found for wikilink:', linkText);
      setError(`Note not found: ${linkText}`);
    }
  };

  const handleSelectNote = (path: string) => {
    setSelectedPath(path);
    setError(null);
    setIsEditMode(false); // Exit edit mode when switching notes
  };

  // T093: Handle edit button click
  const handleEdit = () => {
    if (isDemoMode) {
      toast.error('Demo mode is read-only. Sign in with Hugging Face to edit notes.');
      return;
    }
    setIsEditMode(true);
  };

  // Handle note save from editor
  const handleNoteSave = (updatedNote: Note) => {
    setCurrentNote(updatedNote);
    setIsEditMode(false);
    setError(null);
    // Reload notes list to update modified timestamp
    listNotes().then(setNotes).catch(console.error);
  };

  // Handle editor cancel
  const handleEditCancel = () => {
    setIsEditMode(false);
  };

  // Handle note dialog open change
  const handleDialogOpenChange = (open: boolean) => {
    if (open && isDemoMode) {
      toast.error('Demo mode is read-only. Sign in with Hugging Face to create notes.');
      return;
    }
    setIsNewNoteDialogOpen(open);
    if (!open) {
      // Clear input when dialog closes
      setNewNoteName('');
    }
  };

  // Handle folder dialog open change
  const handleFolderDialogOpenChange = (open: boolean) => {
    if (open && isDemoMode) {
      toast.error('Demo mode is read-only. Sign in with Hugging Face to create folders.');
      return;
    }
    setIsNewFolderDialogOpen(open);
    if (!open) {
      // Clear input when dialog closes
      setNewFolderName('');
    }
  };

  // Handle create new note
  const handleCreateNote = async () => {
    if (isDemoMode) {
      toast.error('Demo mode is read-only. Sign in to create notes.');
      return;
    }
    if (!newNoteName.trim() || isCreatingNote) return;

    setIsCreatingNote(true);
    setError(null);

    try {
      const baseName = newNoteName.replace(/\.md$/, '');
      let notePath = newNoteName.endsWith('.md') ? newNoteName : `${newNoteName}.md`;
      let attempt = 1;
      const maxAttempts = 100;

      // Retry with number suffix if note already exists
      while (attempt <= maxAttempts) {
        try {
          const note = await createNote({
            note_path: notePath,
            title: baseName,
            body: `# ${baseName}\n\nStart writing your note here...`,
          });

          // Refresh notes list
          const notesList = await listNotes();
          setNotes(notesList);

          // Select the new note
          setSelectedPath(note.note_path);
          setIsEditMode(true);
          const displayName = notePath.replace(/\.md$/, '');
          toast.success(`Note "${displayName}" created successfully`);
          break;
        } catch (err) {
          if (err instanceof APIException && err.status === 409) {
            // Note already exists, try with number suffix
            attempt++;
            if (attempt <= maxAttempts) {
              notePath = `${baseName} ${attempt}.md`;
              continue;
            } else {
              throw err;
            }
          } else {
            throw err;
          }
        }
      }
    } catch (err) {
      let errorMessage = 'Failed to create note';
      if (err instanceof APIException) {
        // Use the message field which contains the actual error description
        errorMessage = err.message || err.error;
      } else if (err instanceof Error) {
        errorMessage = err.message;
      }
      toast.error(errorMessage);
      console.error('Error creating note:', err);
    } finally {
      setIsCreatingNote(false);
      // Always close dialog, regardless of success or failure
      handleDialogOpenChange(false);
    }
  };

  // Handle create new folder
  const handleCreateFolder = async () => {
    if (isDemoMode) {
      toast.error('Demo mode is read-only. Sign in to create folders.');
      return;
    }
    if (!newFolderName.trim() || isCreatingFolder) return;

    setIsCreatingFolder(true);
    setError(null);

    try {
      // Create a placeholder note in the folder
      const folderPath = newFolderName.replace(/\/$/, ''); // Remove trailing slash if present
      const placeholderPath = `${folderPath}/.placeholder.md`;

      await createNote({
        note_path: placeholderPath,
        title: 'Folder',
        body: `# ${folderPath}\n\nThis folder was created.`,
      });

      // Refresh notes list
      const notesList = await listNotes();
      setNotes(notesList);

      toast.success(`Folder "${folderPath}" created successfully`);
    } catch (err) {
      let errorMessage = 'Failed to create folder';
      if (err instanceof APIException) {
        errorMessage = err.message || err.error;
      } else if (err instanceof Error) {
        errorMessage = err.message;
      }
      toast.error(errorMessage);
      console.error('Error creating folder:', err);
    } finally {
      setIsCreatingFolder(false);
      // Always close dialog, regardless of success or failure
      handleFolderDialogOpenChange(false);
    }
  };

  // Handle dragging file to folder
  const handleMoveNoteToFolder = async (oldPath: string, targetFolderPath: string) => {
    if (isDemoMode) {
      toast.error('Demo mode is read-only. Sign in to move notes.');
      return;
    }
    try {
      // Get the filename from the old path
      const fileName = oldPath.split('/').pop();
      if (!fileName) {
        toast.error('Invalid file path');
        return;
      }

      // Construct new path: targetFolder/fileName
      const newPath = targetFolderPath ? `${targetFolderPath}/${fileName}` : fileName;

      // Don't move if source and destination are the same
      if (newPath === oldPath) {
        return;
      }

      await moveNote(oldPath, newPath);

      // Refresh notes list
      const notesList = await listNotes();
      setNotes(notesList);

      // If moving currently selected note, update selection
      if (selectedPath === oldPath) {
        setSelectedPath(newPath);
      }

      toast.success(`Note moved successfully`);
    } catch (err) {
      let errorMessage = 'Failed to move note';
      if (err instanceof APIException) {
        errorMessage = err.message || err.error;
      } else if (err instanceof Error) {
        errorMessage = err.message;
      }
      toast.error(errorMessage);
      console.error('Error moving note:', err);
    }
  };

  return (
    <div className="h-screen flex flex-col">
      {/* Demo warning banner */}
      <Alert variant="destructive" className="rounded-none border-x-0 border-t-0">
        <AlertDescription className="text-center">
          DEMO ONLY - ALL DATA IS TEMPORARY AND MAY BE DELETED AT ANY TIME
        </AlertDescription>
      </Alert>
      
      {/* Top bar */}
      <div className="border-b border-border p-4 animate-fade-in">
        <div className="flex items-center justify-between gap-2">
          <h1 className="text-xl font-semibold">📚 Document Viewer</h1>
          <div className="flex gap-2">
            {isDemoMode && (
              <Button
                variant="default"
                size="sm"
                onClick={() => login()}
                title="Sign in with Hugging Face"
              >
                Sign in
              </Button>
            )}
            <Button
              variant={isGraphView ? "secondary" : "ghost"}
              size="sm"
              onClick={() => setIsGraphView(!isGraphView)}
              title={isGraphView ? "Switch to Note View" : "Switch to Graph View"}
            >
              <Network className="h-4 w-4" />
            </Button>
            <Button variant="ghost" size="sm" onClick={() => navigate('/settings')}>
              <SettingsIcon className="h-4 w-4" />
            </Button>
          </div>
        </div>
      </div>

      {/* Main content */}
      <div className="flex-1 overflow-hidden animate-fade-in" style={{ animationDelay: '0.1s' }}>
        {isDemoMode && (
          <div className="border-b border-border bg-muted/40 px-4 py-2 text-sm text-muted-foreground flex flex-wrap items-center justify-between gap-2">
            <span>
              You are browsing the shared demo vault in read-only mode. Sign in with your Hugging Face account to create and edit notes.
            </span>
            <Button variant="outline" size="sm" onClick={() => login()}>
              Sign in
            </Button>
          </div>
        )}
        <ResizablePanelGroup direction="horizontal">
          {/* Left sidebar */}
          <ResizablePanel defaultSize={25} minSize={15} maxSize={40}>
            <div className="h-full flex flex-col">
              <div className="p-4 space-y-4">
                <Dialog
                  open={isNewNoteDialogOpen}
                  onOpenChange={handleDialogOpenChange}
                >
                  <DialogTrigger asChild>
                    <Button variant="outline" size="sm" className="w-full" disabled={isDemoMode}>
                      <Plus className="h-4 w-4 mr-1" />
                      New Note
                    </Button>
                  </DialogTrigger>
                  <DialogContent>
                    <DialogHeader>
                      <DialogTitle>Create New Note</DialogTitle>
                      <DialogDescription>
                        Enter a name for your new note. The .md extension will be added automatically if not provided.
                      </DialogDescription>
                    </DialogHeader>
                    <div className="grid gap-4 py-4">
                      <div className="grid gap-2">
                        <label htmlFor="note-name" className="text-sm font-medium">Note Name</label>
                        <Input
                          id="note-name"
                          placeholder="my-note"
                          value={newNoteName}
                          onChange={(e) => setNewNoteName(e.target.value)}
                          onKeyDown={(e) => {
                            if (e.key === 'Enter') {
                              handleCreateNote();
                            }
                          }}
                        />
                      </div>
                    </div>
                    <DialogFooter>
                      <Button
                        variant="outline"
                        onClick={() => setIsNewNoteDialogOpen(false)}
                        disabled={isCreatingNote}
                      >
                        Cancel
                      </Button>
                      <Button
                        onClick={handleCreateNote}
                        disabled={!newNoteName.trim() || isCreatingNote}
                      >
                        {isCreatingNote ? 'Creating...' : 'Create Note'}
                      </Button>
                    </DialogFooter>
                  </DialogContent>
                </Dialog>
                <Dialog
                  open={isNewFolderDialogOpen}
                  onOpenChange={handleFolderDialogOpenChange}
                >
                  <DialogTrigger asChild>
                    <Button variant="outline" size="sm" className="w-full" disabled={isDemoMode}>
                      <FolderPlus className="h-4 w-4 mr-1" />
                      New Folder
                    </Button>
                  </DialogTrigger>
                  <DialogContent>
                    <DialogHeader>
                      <DialogTitle>Create New Folder</DialogTitle>
                      <DialogDescription>
                        Enter a name for your new folder. You can use forward slashes for nested folders (e.g., "Projects/Work").
                      </DialogDescription>
                    </DialogHeader>
                    <div className="grid gap-4 py-4">
                      <div className="grid gap-2">
                        <label htmlFor="folder-name" className="text-sm font-medium">Folder Name</label>
                        <Input
                          id="folder-name"
                          placeholder="my-folder"
                          value={newFolderName}
                          onChange={(e) => setNewFolderName(e.target.value)}
                          onKeyDown={(e) => {
                            if (e.key === 'Enter') {
                              handleCreateFolder();
                            }
                          }}
                        />
                      </div>
                    </div>
                    <DialogFooter>
                      <Button
                        variant="outline"
                        onClick={() => setIsNewFolderDialogOpen(false)}
                        disabled={isCreatingFolder}
                      >
                        Cancel
                      </Button>
                      <Button
                        onClick={handleCreateFolder}
                        disabled={!newFolderName.trim() || isCreatingFolder}
                      >
                        {isCreatingFolder ? 'Creating...' : 'Create Folder'}
                      </Button>
                    </DialogFooter>
                  </DialogContent>
                </Dialog>
                <SearchBar onSelectNote={handleSelectNote} />
                <Separator />
              </div>
              <div className="flex-1 overflow-hidden">
                {isLoadingNotes ? (
                  <DirectoryTreeSkeleton />
                ) : (
                  <DirectoryTree
                    notes={notes}
                    selectedPath={selectedPath || undefined}
                    onSelectNote={handleSelectNote}
                    onMoveNote={handleMoveNoteToFolder}
                  />
                )}
              </div>
            </div>
          </ResizablePanel>

          <ResizableHandle withHandle />

          {/* Main content pane */}
          <ResizablePanel defaultSize={75}>
            <div className="h-full bg-background">
              {error && (
                <div className="p-4">
                  <Alert variant="destructive">
                    <AlertDescription>{error}</AlertDescription>
                  </Alert>
                </div>
              )}

              {isGraphView ? (
                <GraphView onSelectNote={(path) => {
                  handleSelectNote(path);
                  setIsGraphView(false);
                }} />
              ) : (
                isLoadingNote ? (
                  <NoteViewerSkeleton />
                ) : currentNote ? (
                  isEditMode ? (
                    <NoteEditor
                      note={currentNote}
                      onSave={handleNoteSave}
                      onCancel={handleEditCancel}
                      onWikilinkClick={handleWikilinkClick}
                    />
                  ) : (
                    <NoteViewer
                      note={currentNote}
                      backlinks={backlinks}
                      onEdit={isDemoMode ? undefined : handleEdit}
                      onWikilinkClick={handleWikilinkClick}
                    />
                  )
                ) : (
                  <div className="flex items-center justify-center h-full">
                    <div className="text-center text-muted-foreground">
                      <p className="text-lg mb-2">Select a note to view</p>
                      <p className="text-sm">
                        {notes.length === 0
                          ? 'No notes available. Create your first note to get started.'
                          : 'Choose a note from the sidebar'}
                      </p>
                    </div>
                  </div>
                )
              )}
            </div>
          </ResizablePanel>
        </ResizablePanelGroup>
      </div>

      {/* Footer with Index Health */}
      <div className="border-t border-border px-4 py-2 text-xs text-muted-foreground animate-fade-in" style={{ animationDelay: '0.2s' }}>
        <div className="flex items-center justify-between">
          <div>
            {indexHealth ? (
              <>
                <span className="font-medium">{indexHealth.note_count}</span> note{indexHealth.note_count !== 1 ? 's' : ''} indexed
              </>
            ) : (
              <>
                <span className="font-medium">{notes.length}</span> note{notes.length !== 1 ? 's' : ''} indexed
              </>
            )}
          </div>
          {indexHealth && indexHealth.last_incremental_update && (
            <div className="flex items-center gap-2">
              <span>Last updated:</span>
              <span className="font-medium">
                {new Date(indexHealth.last_incremental_update).toLocaleString('en-US', {
                  month: 'short',
                  day: 'numeric',
                  hour: '2-digit',
                  minute: '2-digit',
                })}
              </span>
            </div>
          )}
        </div>
      </div>
    </div>
  );
}

