'use client';

import { useState, useEffect, useCallback } from 'react';
import { Note } from '@/services/notes';
import { Folder } from '@/services/folders';
import { Task } from '@/lib/types';
import { notesClient } from '@/clients/notes';
import { NotesList } from '@/components/notes/NotesList';
import { MarkdownEditor } from '@/components/notes/MarkdownEditor';
import { FoldersSidebar } from '@/components/notes/FoldersSidebar';
import { Header } from '@/components/ui/Header';
import { Card } from '@/components/ui';
import { TasksProvider, useTasksContext } from '@/contexts/TasksContext';
import { Tag } from '@/lib/types';
import { FileText, AlertCircle, ChevronLeft, ChevronRight } from 'lucide-react';
import { getFolders } from '@/actions/folders';
import { reorderNotes } from '@/actions/notes';

interface NotesPageClientProps {
  initialNotes: Note[];
  initialTags: (Tag & { usage: number })[];
  initialFolders: Folder[];
}

function NotesPageContent({
  initialNotes,
  initialFolders,
}: {
  initialNotes: Note[];
  initialFolders: Folder[];
}) {
  const [notes, setNotes] = useState<Note[]>(initialNotes);
  const [folders, setFolders] = useState<Folder[]>(initialFolders);
  const [selectedNote, setSelectedNote] = useState<Note | null>(null);
  const [selectedFolderId, setSelectedFolderId] = useState<string | null>(null);
  const [isNewNote, setIsNewNote] = useState(false);
  const { tags: availableTags } = useTasksContext();
  const [error, setError] = useState<string | null>(null);
  const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false);
  const [sidebarCollapsed, setSidebarCollapsed] = useState(false);
  const glassSurface =
    'bg-[var(--card)]/40 backdrop-blur-md relative before:absolute before:inset-0 before:bg-gradient-to-r before:from-[color-mix(in_srgb,var(--primary)_8%,transparent)] before:via-[color-mix(in_srgb,var(--primary)_4%,transparent)] before:to-transparent before:opacity-80 before:pointer-events-none';
  const glassDivider = `${glassSurface} border-b border-[var(--border)]/60`;

  // Select first note if none selected
  useEffect(() => {
    if (notes.length > 0 && !selectedNote) {
      setSelectedNote(notes[0]);
    }
  }, [notes, selectedNote]);

  const handleSelectNote = useCallback(
    (note: Note) => {
      // Check for unsaved changes before switching
      if (hasUnsavedChanges && selectedNote) {
        const shouldSwitch = window.confirm(
          'Vous avez des modifications non sauvegardées. Voulez-vous continuer sans sauvegarder ?'
        );
        if (!shouldSwitch) return;
      }

      setSelectedNote(note);
      setIsNewNote(false);
      setHasUnsavedChanges(false);
    },
    [hasUnsavedChanges, selectedNote]
  );

  const handleCreateNote = useCallback(async () => {
    try {
      // Déterminer le folderId : null si "Toutes les notes" ou "Non classées", sinon le dossier actif
      const targetFolderId =
        !selectedFolderId || selectedFolderId === '__uncategorized__'
          ? undefined
          : selectedFolderId;

      console.log(
        '[handleCreateNote] selectedFolderId:',
        selectedFolderId,
        'targetFolderId:',
        targetFolderId
      );

      const newNote = await notesClient.createNote({
        title: 'Nouvelle note',
        content: '# Nouvelle note\n\nCommencez à écrire...',
        folderId: targetFolderId,
      });

      setNotes((prev) => [newNote, ...prev]);
      setSelectedNote(newNote);
      setIsNewNote(true);
      setHasUnsavedChanges(false);
    } catch (err) {
      setError('Erreur lors de la création de la note');
      console.error('Error creating note:', err);
    }
  }, [selectedFolderId]);

  const handleDeleteNote = useCallback(
    async (noteId: string) => {
      try {
        await notesClient.deleteNote(noteId);
        setNotes((prev) => prev.filter((note) => note.id !== noteId));

        // If deleted note was selected, select another one
        if (selectedNote?.id === noteId) {
          const remainingNotes = notes.filter((note) => note.id !== noteId);
          setSelectedNote(remainingNotes.length > 0 ? remainingNotes[0] : null);
        }
      } catch (err) {
        setError('Erreur lors de la suppression de la note');
        console.error('Error deleting note:', err);
      }
    },
    [selectedNote, notes]
  );

  const reloadNotes = useCallback(async () => {
    try {
      const updatedNotes = await notesClient.getNotes();
      setNotes(updatedNotes);
    } catch (err) {
      console.error('Error reloading notes:', err);
    }
  }, []);

  const handleReorderNotes = useCallback(
    async (noteOrders: Array<{ id: string; order: number }>) => {
      try {
        // Optimistic update
        const notesMap = new Map(notes.map((n) => [n.id, n]));
        const reorderedNotes = noteOrders
          .map((no) => notesMap.get(no.id))
          .filter((n): n is Note => n !== undefined);
        setNotes(reorderedNotes);

        // Server update
        const result = await reorderNotes(noteOrders);
        if (!result.success) {
          throw new Error(result.error);
        }
      } catch (err) {
        setError('Erreur lors du réordonnancement des notes');
        console.error('Error reordering notes:', err);
        // Reload notes on error
        reloadNotes();
      }
    },
    [notes, reloadNotes]
  );

  const getNoteTitle = (content: string): string => {
    // Extract title from first line, removing markdown headers
    const firstLine = content.split('\n')[0] || '';
    const title = firstLine
      .replace(/^#{1,6}\s+/, '') // Remove markdown headers
      .replace(/\*\*(.*?)\*\*/g, '$1') // Remove bold
      .replace(/\*(.*?)\*/g, '$1') // Remove italic
      .replace(/`(.*?)`/g, '$1') // Remove inline code
      .trim();

    return title || 'Note sans titre';
  };

  const handleContentChange = useCallback(
    (content: string) => {
      if (selectedNote) {
        setSelectedNote((prev) => (prev ? { ...prev, content } : null));
        setHasUnsavedChanges(true);
      }
    },
    [selectedNote]
  );

  const handleSave = useCallback(async () => {
    if (!selectedNote) return;

    try {
      // setIsSaving(true);
      setError(null);

      // Construire l'objet de mise à jour en incluant explicitement les champs
      const updateData: {
        content: string;
        tags?: string[];
        taskId?: string;
        folderId?: string | null;
      } = {
        content: selectedNote.content,
        tags: selectedNote.tags,
      };

      // Ajouter taskId et folderId seulement s'ils sont définis
      if (selectedNote.taskId !== undefined) {
        updateData.taskId = selectedNote.taskId;
      }
      if (selectedNote.folderId !== undefined) {
        updateData.folderId = selectedNote.folderId;
      }

      const updatedNote = await notesClient.updateNote(
        selectedNote.id,
        updateData
      );

      // Mettre à jour la liste des notes mais pas selectedNote pour éviter la perte de focus
      setNotes((prev) =>
        prev.map((note) => (note.id === selectedNote.id ? updatedNote : note))
      );

      setHasUnsavedChanges(false);
      setIsNewNote(false);
    } catch (err) {
      setError('Erreur lors de la sauvegarde');
      console.error('Error saving note:', err);
    } finally {
      // setIsSaving(false);
    }
  }, [selectedNote]);

  const handleTagsChange = useCallback(
    (tags: string[]) => {
      if (!selectedNote) return;

      setSelectedNote((prev) => (prev ? { ...prev, tags } : null));
      setHasUnsavedChanges(true);
    },
    [selectedNote]
  );

  const handleTaskChange = useCallback(
    (task: Task | null) => {
      if (!selectedNote) return;

      setSelectedNote((prev) =>
        prev ? { ...prev, taskId: task?.id, task } : null
      );
      setHasUnsavedChanges(true);
    },
    [selectedNote]
  );

  const handleFolderChange = useCallback(
    async (folderId: string | null) => {
      if (!selectedNote) return;

      try {
        // Sauvegarder immédiatement
        const updateData: { folderId: string | null } = {
          folderId: folderId,
        };
        const updatedNote = await notesClient.updateNote(
          selectedNote.id,
          updateData
        );

        // Mettre à jour la liste des notes
        setNotes((prev) =>
          prev.map((note) => (note.id === selectedNote.id ? updatedNote : note))
        );

        // Mettre à jour la note sélectionnée
        setSelectedNote(updatedNote);
      } catch (err) {
        console.error('Error changing folder:', err);
        setError('Erreur lors du changement de dossier');
      }
    },
    [selectedNote]
  );

  // Auto-save quand les tags changent
  useEffect(() => {
    if (hasUnsavedChanges && selectedNote) {
      const timeoutId = setTimeout(() => {
        handleSave();
      }, 1000); // Sauvegarder après 1 seconde d'inactivité

      return () => clearTimeout(timeoutId);
    }
  }, [selectedNote, hasUnsavedChanges, handleSave]);

  // Filtrer les notes par dossier
  const filteredNotes =
    selectedFolderId === '__uncategorized__'
      ? notes.filter((note) => !note.folderId) // Notes sans dossier
      : selectedFolderId
        ? notes.filter((note) => note.folderId === selectedFolderId)
        : notes; // Toutes les notes

  // Gérer le changement de dossier
  const handleSelectFolder = useCallback(
    (folderId: string | null) => {
      setSelectedFolderId(folderId);

      // Sélectionner automatiquement la première note du dossier
      const folderNotes =
        folderId === '__uncategorized__'
          ? notes.filter((note) => !note.folderId)
          : folderId
            ? notes.filter((note) => note.folderId === folderId)
            : notes;

      if (folderNotes.length > 0) {
        setSelectedNote(folderNotes[0]);
      } else {
        setSelectedNote(null);
      }
    },
    [notes]
  );

  // Recharger les dossiers
  const handleFoldersChange = useCallback(async () => {
    try {
      const result = await getFolders();
      if (result.success && result.data) {
        setFolders(result.data);
      }
    } catch (err) {
      console.error('Error fetching folders:', err);
    }
  }, []);

  // Gérer le drop d'une note sur un dossier
  const handleNoteDrop = useCallback(
    async (noteId: string, folderId: string | null) => {
      try {
        const updateData: { folderId: string | null } = {
          folderId: folderId,
        };
        const updatedNote = await notesClient.updateNote(noteId, updateData);

        // Mettre à jour la liste des notes
        setNotes((prev) =>
          prev.map((note) => (note.id === noteId ? updatedNote : note))
        );

        // Si la note sélectionnée est celle qu'on déplace, la mettre à jour aussi
        if (selectedNote?.id === noteId) {
          setSelectedNote(updatedNote);
        }

        // Recharger les dossiers pour mettre à jour les compteurs
        handleFoldersChange();
      } catch (err) {
        console.error('Error moving note:', err);
        setError('Erreur lors du déplacement de la note');
      }
    },
    [selectedNote, handleFoldersChange]
  );

  return (
    <div className="min-h-screen bg-[var(--background)] flex flex-col">
      <Header title="Notes" subtitle="Gestionnaire de notes markdown" />

      <div className="flex-1 container mx-auto px-4 py-6">
        <Card
          variant="glass"
          className="flex h-full rounded-2xl overflow-hidden"
        >
          {/* Combined Sidebar: Folders + Notes List */}
          <div
            className={`${sidebarCollapsed ? 'w-12' : 'w-80'} flex-shrink-0 border-r border-[var(--border)] transition-all duration-300 ease-in-out flex flex-col`}
          >
            {sidebarCollapsed ? (
              <div className="h-full flex flex-col items-center py-4">
                <button
                  onClick={() => setSidebarCollapsed(false)}
                  className="p-2 rounded-lg bg-[var(--card)]/60 hover:bg-[var(--card)]/80 backdrop-blur-sm text-[var(--foreground)] border border-[var(--border)]/40 hover:border-[var(--border)]/60 transition-all duration-200 shadow-sm hover:shadow-md"
                >
                  <ChevronRight className="w-4 h-4" />
                </button>
                <div className="mt-4 text-xs text-[var(--muted-foreground)] font-mono writing-mode-vertical-rl text-orientation-mixed">
                  NOTES
                </div>
              </div>
            ) : (
              <>
                {/* Header */}
                <div
                  className={`${glassDivider} flex items-center justify-between p-3`}
                >
                  <h2 className="text-sm font-mono font-semibold text-[var(--foreground)] uppercase tracking-wider">
                    Notes
                  </h2>
                  <button
                    onClick={() => setSidebarCollapsed(true)}
                    className="p-1 rounded-lg bg-[var(--card)]/60 hover:bg-[var(--card)]/80 backdrop-blur-sm text-[var(--foreground)] border border-[var(--border)]/40 hover:border-[var(--border)]/60 transition-all duration-200 shadow-sm hover:shadow-md"
                  >
                    <ChevronLeft className="w-3 h-3" />
                  </button>
                </div>

                {/* Folders Section */}
                <div className="flex-shrink-0 border-b border-[var(--border)]">
                  <FoldersSidebar
                    folders={folders}
                    selectedFolderId={selectedFolderId || undefined}
                    onSelectFolder={handleSelectFolder}
                    onFoldersChange={handleFoldersChange}
                    availableTags={availableTags}
                    onNoteDrop={handleNoteDrop}
                  />
                </div>

                {/* Notes List */}
                <div className="flex-1 overflow-hidden">
                  <NotesList
                    notes={filteredNotes}
                    onSelectNote={handleSelectNote}
                    onCreateNote={handleCreateNote}
                    onDeleteNote={handleDeleteNote}
                    onReorderNotes={handleReorderNotes}
                    selectedNoteId={selectedNote?.id}
                    isLoading={false}
                    availableTags={availableTags}
                  />
                </div>
              </>
            )}
          </div>

          {/* Main Editor Area */}
          <div className="flex-1 flex flex-col min-h-0">
            {error && (
              <div className="flex items-center gap-2 p-3 bg-[var(--destructive)]/10 border-b border-[var(--destructive)]/20 text-[var(--destructive)]">
                <AlertCircle className="w-4 h-4" />
                <span className="text-sm">{error}</span>
                <button
                  onClick={() => setError(null)}
                  className="ml-auto text-xs underline hover:no-underline"
                >
                  Fermer
                </button>
              </div>
            )}

            {selectedNote ? (
              <>
                {/* Note Header */}
                <div className={`${glassDivider} flex items-center gap-4 p-4`}>
                  <FileText className="w-5 h-5 text-[var(--muted-foreground)]" />
                  <div className="flex-1">
                    <h2 className="text-lg font-semibold text-[var(--foreground)] truncate">
                      {getNoteTitle(selectedNote.content)}
                    </h2>
                    {selectedNote.folderId &&
                      (() => {
                        const findFolder = (
                          foldersList: typeof folders
                        ): (typeof folders)[0] | null => {
                          for (const folder of foldersList) {
                            if (folder.id === selectedNote.folderId)
                              return folder;
                            if (folder.children) {
                              const found = findFolder(folder.children);
                              if (found) return found;
                            }
                          }
                          return null;
                        };
                        const currentFolder = findFolder(folders);
                        const folderTag = currentFolder?.tagId
                          ? availableTags.find(
                              (t) => t.id === currentFolder.tagId
                            )
                          : null;

                        return currentFolder ? (
                          <div className="flex items-center gap-2 mt-1">
                            <span className="text-xs text-[var(--muted-foreground)]">
                              📁 {currentFolder.name}
                            </span>
                            {folderTag && (
                              <div
                                className="flex items-center gap-1 px-2 py-0.5 rounded-full text-xs"
                                style={{
                                  backgroundColor: `${folderTag.color}20`,
                                  color: folderTag.color,
                                }}
                              >
                                <span>{folderTag.name}</span>
                              </div>
                            )}
                          </div>
                        ) : null;
                      })()}
                  </div>
                  <div className="flex items-center gap-2 text-sm text-[var(--muted-foreground)]">
                    {hasUnsavedChanges && (
                      <span className="text-[var(--accent)]">
                        Non sauvegardé
                      </span>
                    )}
                    <span>
                      Modifié{' '}
                      {new Date(selectedNote.updatedAt).toLocaleDateString(
                        'fr-FR'
                      )}
                    </span>
                  </div>
                </div>

                {/* Editor */}
                <div className="flex-1 min-h-0">
                  <MarkdownEditor
                    value={selectedNote.content}
                    onChange={handleContentChange}
                    autoSave={true}
                    onSave={handleSave}
                    tags={selectedNote.tags}
                    onTagsChange={handleTagsChange}
                    availableTags={availableTags}
                    selectedTaskId={selectedNote.taskId}
                    selectedTask={selectedNote.task}
                    onTaskChange={handleTaskChange}
                    selectedFolderId={selectedNote.folderId}
                    availableFolders={folders}
                    onFolderChange={handleFolderChange}
                    onCreateNote={handleCreateNote}
                    onToggleSidebar={() =>
                      setSidebarCollapsed(!sidebarCollapsed)
                    }
                    initialIsEditing={isNewNote}
                    onEditingChange={(isEditing) => {
                      if (!isEditing) {
                        setIsNewNote(false);
                      }
                    }}
                    className="h-full"
                  />
                </div>
              </>
            ) : (
              <div className="flex-1 flex items-center justify-center text-[var(--muted-foreground)]">
                <div className="text-center">
                  <FileText className="w-16 h-16 mx-auto mb-4 opacity-50" />
                  <h3 className="text-lg font-medium mb-2">
                    Aucune note sélectionnée
                  </h3>
                  <p className="text-sm">
                    Sélectionnez une note dans la liste ou créez-en une nouvelle
                  </p>
                </div>
              </div>
            )}
          </div>
        </Card>
      </div>
    </div>
  );
}

export function NotesPageClient({
  initialNotes,
  initialTags,
  initialFolders,
}: NotesPageClientProps) {
  return (
    <TasksProvider initialTasks={[]} initialTags={initialTags}>
      <NotesPageContent
        initialNotes={initialNotes}
        initialFolders={initialFolders}
      />
    </TasksProvider>
  );
}
