import {
  RiAddLine,
  RiArrowLeftLine,
  RiCloseLine,
  RiDeleteBinLine,
  RiFolderAddLine,
  RiFolderTransferLine,
  RiLoader4Line,
  RiLogoutBoxLine,
  RiSearchLine,
  RiShareLine,
  RiUserLine,
} from '@remixicon/react'
import { useEffect, useMemo, useState } from 'react'
import { Link, useNavigate, useParams } from 'react-router-dom'
import FolderCard from '../components/FolderCard'
import FolderModal from '../components/FolderModal'
import Logo from '../components/Logo'
import MoveToFolderModal from '../components/MoveToFolderModal'
import ProjectCard from '../components/ProjectCard'
import ProjectModal from '../components/ProjectModal'
import ShareModal from '../components/ShareModal'
import { useAuth } from '../context/AuthContext'
import { useFolders } from '../hooks/useFolders'
import { useProjects } from '../hooks/useProjects'
import { useSharedProjects } from '../hooks/useSharedProjects'
import { confirmAction, showError } from '../lib/alerts'
import * as folderService from '../services/folderService'
import * as projectService from '../services/projectService'

function Dashboard() {
  const { user, signOut } = useAuth()
  const { folderId } = useParams()
  const navigate = useNavigate()

  const { projects, loading: loadingProjects, error, refresh: refreshProjects } = useProjects(folderId)
  const {
    folders,
    loading: loadingFolders,
    refresh: refreshFolders,
  } = useFolders()
  const { sharedProjects } = useSharedProjects()

  const [currentFolder, setCurrentFolder] = useState(null)
  const [loadingFolder, setLoadingFolder] = useState(Boolean(folderId))

  const [search, setSearch] = useState('')
  const [showCreateModal, setShowCreateModal] = useState(false)
  const [showFolderModal, setShowFolderModal] = useState(false)
  const [renamingProject, setRenamingProject] = useState(null)
  const [renamingFolder, setRenamingFolder] = useState(null)
  const [changingColorFolder, setChangingColorFolder] = useState(null)
  const [busyId, setBusyId] = useState(null)
  const [selectedKeys, setSelectedKeys] = useState(new Set())
  const [movingProjects, setMovingProjects] = useState(null)
  const [sharingProject, setSharingProject] = useState(null)

  useEffect(() => {
    setSelectedKeys(new Set())
  }, [folderId])

  useEffect(() => {
    if (!folderId) {
      setCurrentFolder(null)
      return
    }
    let cancelled = false
    setLoadingFolder(true)
    folderService
      .getFolder(folderId)
      .then((data) => {
        if (!cancelled) setCurrentFolder(data)
      })
      .catch((err) => {
        if (!cancelled) showError(err.message, 'No se pudo abrir la carpeta')
      })
      .finally(() => {
        if (!cancelled) setLoadingFolder(false)
      })
    return () => {
      cancelled = true
    }
  }, [folderId])

  const query = search.trim().toLowerCase()
  const filteredFolders = useMemo(() => {
    if (folderId || !query) return folderId ? [] : folders
    return folders.filter((folder) => folder.name.toLowerCase().includes(query))
  }, [folders, folderId, query])
  const filteredProjects = useMemo(() => {
    if (!query) return projects
    return projects.filter((project) => project.name.toLowerCase().includes(query))
  }, [projects, query])
  const filteredSharedProjects = useMemo(() => {
    if (folderId) return []
    if (!query) return sharedProjects
    return sharedProjects.filter((project) => project.name.toLowerCase().includes(query))
  }, [sharedProjects, folderId, query])

  const loading = loadingProjects || loadingFolders || loadingFolder
  const isEmpty =
    filteredFolders.length === 0 && filteredProjects.length === 0 && filteredSharedProjects.length === 0

  const selectionMode = selectedKeys.size > 0
  const selectedProjects = filteredProjects.filter((p) => selectedKeys.has(`project:${p.id}`))
  const selectedFolders = filteredFolders.filter((f) => selectedKeys.has(`folder:${f.id}`))

  const clearSelection = () => setSelectedKeys(new Set())

  const toggleSelectProject = (project) => {
    setSelectedKeys((prev) => {
      const next = new Set(prev)
      const key = `project:${project.id}`
      if (next.has(key)) next.delete(key)
      else next.add(key)
      return next
    })
  }

  const toggleSelectFolder = (folder) => {
    setSelectedKeys((prev) => {
      const next = new Set(prev)
      const key = `folder:${folder.id}`
      if (next.has(key)) next.delete(key)
      else next.add(key)
      return next
    })
  }

  const handleCreateProject = async ({ name, description, color }) => {
    const trimmedName = name.trim()
    const isDuplicate = projects.some(
      (p) => p.name.trim().toLowerCase() === trimmedName.toLowerCase(),
    )
    if (isDuplicate) {
      showError(`Ya existe un proyecto llamado "${trimmedName}". Elige un nombre distinto.`)
      return
    }

    const project = await projectService.createProject({
      name: trimmedName,
      description,
      color,
      folderId: folderId || null,
    })
    setShowCreateModal(false)
    navigate(`/projects/${project.id}`)
  }

  const handleCreateFolder = async ({ name, color }) => {
    const trimmedName = name.trim()
    const isDuplicate = folders.some(
      (f) => f.name.trim().toLowerCase() === trimmedName.toLowerCase(),
    )
    if (isDuplicate) {
      showError(`Ya existe una carpeta llamada "${trimmedName}". Elige un nombre distinto.`)
      return
    }

    await folderService.createFolder({ name: trimmedName, color })
    setShowFolderModal(false)
    refreshFolders()
  }

  const handleRenameProject = async ({ name, color }) => {
    const trimmedName = name.trim()
    const isDuplicate = projects.some(
      (p) =>
        p.id !== renamingProject.id &&
        p.name.trim().toLowerCase() === trimmedName.toLowerCase(),
    )
    if (isDuplicate) {
      showError(`Ya existe otro proyecto llamado "${trimmedName}". Elige un nombre distinto.`)
      return
    }

    await projectService.updateProject(renamingProject.id, { name: trimmedName, color })
    setRenamingProject(null)
    refreshProjects()
  }

  const handleRenameFolder = async ({ name, color }) => {
    const trimmedName = name.trim()
    const isDuplicate = folders.some(
      (f) =>
        f.id !== renamingFolder.id &&
        f.name.trim().toLowerCase() === trimmedName.toLowerCase(),
    )
    if (isDuplicate) {
      showError(`Ya existe otra carpeta llamada "${trimmedName}". Elige un nombre distinto.`)
      return
    }

    await folderService.updateFolder(renamingFolder.id, { name: trimmedName, color })
    setRenamingFolder(null)
    refreshFolders()
  }

  const handleChangeFolderColor = async ({ color }) => {
    await folderService.updateFolder(changingColorFolder.id, { color })
    setChangingColorFolder(null)
    refreshFolders()
  }

  const handleDuplicateProject = async (project) => {
    setBusyId(project.id)
    try {
      await projectService.duplicateProject(project.id)
      refreshProjects()
    } catch (err) {
      showError(err.message)
    } finally {
      setBusyId(null)
    }
  }

  const handleDeleteProject = async (project) => {
    const confirmed = await confirmAction({
      title: '¿Eliminar este proyecto?',
      text: `Se eliminará "${project.name}" de forma permanente. Esta acción no se puede deshacer.`,
      confirmText: 'Eliminar',
      danger: true,
    })
    if (!confirmed) return

    setBusyId(project.id)
    try {
      await projectService.deleteProject(project.id)
      refreshProjects()
    } catch (err) {
      showError(err.message)
    } finally {
      setBusyId(null)
    }
  }

  const handleDeleteFolder = async (folder) => {
    const confirmed = await confirmAction({
      title: '¿Eliminar esta carpeta?',
      text: `Se eliminará la carpeta "${folder.name}". Los proyectos que contiene no se borrarán, quedarán fuera de la carpeta.`,
      confirmText: 'Eliminar',
      danger: true,
    })
    if (!confirmed) return

    setBusyId(folder.id)
    try {
      await folderService.deleteFolder(folder.id)
      refreshFolders()
    } catch (err) {
      showError(err.message)
    } finally {
      setBusyId(null)
    }
  }

  const handleMoveSubmit = async (targetFolderId) => {
    await Promise.all(
      movingProjects.map((project) => projectService.updateProject(project.id, { folder_id: targetFolderId })),
    )
    setMovingProjects(null)
    clearSelection()
    refreshProjects()
  }

  const handleBulkDelete = async () => {
    const total = selectedKeys.size
    const confirmed = await confirmAction({
      title: `¿Eliminar ${total} elemento${total === 1 ? '' : 's'}?`,
      text:
        selectedFolders.length > 0
          ? 'Las carpetas seleccionadas se eliminarán; los proyectos que contengan no se borrarán, quedarán fuera de la carpeta. Esta acción no se puede deshacer.'
          : 'Esta acción no se puede deshacer.',
      confirmText: 'Eliminar',
      danger: true,
    })
    if (!confirmed) return

    try {
      await Promise.all([
        ...selectedProjects.map((p) => projectService.deleteProject(p.id)),
        ...selectedFolders.map((f) => folderService.deleteFolder(f.id)),
      ])
      clearSelection()
      refreshProjects()
      refreshFolders()
    } catch (err) {
      showError(err.message)
    }
  }

  return (
    <div className="min-h-screen bg-[#0b0d12]">
      <header className="flex items-center justify-between border-b border-white/10 bg-[#12141c] px-6 py-4">
        <Logo />
        <div className="flex items-center gap-3">
          {!folderId && (
            <button
              type="button"
              onClick={() => setShowFolderModal(true)}
              className="inline-flex items-center gap-1.5 rounded-lg border border-white/10 px-3 py-2 text-sm font-medium text-slate-200 hover:bg-white/5"
            >
              <RiFolderAddLine size={18} />
              Nueva carpeta
            </button>
          )}
          {folderId && (
            <button
              type="button"
              onClick={() => setShowCreateModal(true)}
              className="inline-flex items-center gap-1.5 rounded-lg bg-brand-600 px-3 py-2 text-sm font-medium text-white hover:bg-brand-500"
            >
              <RiAddLine size={18} />
              Nuevo proyecto
            </button>
          )}
          <span className="hidden text-sm text-slate-400 sm:inline">{user?.email}</span>
          <Link
            to="/profile"
            title="Perfil"
            className="inline-flex items-center justify-center rounded-lg border border-white/10 p-2 text-slate-400 hover:bg-white/5 hover:text-white"
          >
            <RiUserLine size={18} />
          </Link>
          <button
            type="button"
            onClick={signOut}
            title="Cerrar sesión"
            className="inline-flex items-center justify-center rounded-lg border border-white/10 p-2 text-slate-400 hover:bg-white/5 hover:text-white"
          >
            <RiLogoutBoxLine size={18} />
          </button>
        </div>
      </header>

      <main className="mx-auto max-w-5xl px-6 py-10">
        {folderId ? (
          <div className="mb-6 flex items-center gap-2">
            <Link
              to="/dashboard"
              className="rounded-lg p-1.5 text-slate-400 hover:bg-white/5 hover:text-white"
            >
              <RiArrowLeftLine size={18} />
            </Link>
            <h2 className="text-sm font-medium text-slate-300">
              {currentFolder ? currentFolder.name : 'Cargando...'}
            </h2>
          </div>
        ) : null}

        {selectionMode ? (
          <div className="mb-6 flex items-center gap-3 rounded-lg border border-white/10 bg-[#12141c] px-3 py-2">
            <button
              type="button"
              onClick={clearSelection}
              className="rounded-lg p-1.5 text-slate-400 hover:bg-white/10 hover:text-white"
            >
              <RiCloseLine size={18} />
            </button>
            <span className="text-sm text-slate-300">
              {selectedKeys.size} seleccionado{selectedKeys.size === 1 ? '' : 's'}
            </span>
            <div className="ml-auto flex items-center gap-1">
              {selectedProjects.length === 1 && selectedFolders.length === 0 && (
                <button
                  type="button"
                  onClick={() => setSharingProject(selectedProjects[0])}
                  title="Compartir"
                  className="rounded-lg p-2 text-slate-400 hover:bg-white/10 hover:text-white"
                >
                  <RiShareLine size={18} />
                </button>
              )}
              {selectedProjects.length > 0 && selectedFolders.length === 0 && (
                <button
                  type="button"
                  onClick={() => setMovingProjects(selectedProjects)}
                  title="Mover a carpeta"
                  className="rounded-lg p-2 text-slate-400 hover:bg-white/10 hover:text-white"
                >
                  <RiFolderTransferLine size={18} />
                </button>
              )}
              <button
                type="button"
                onClick={handleBulkDelete}
                title="Eliminar"
                className="rounded-lg p-2 text-slate-400 hover:bg-white/10 hover:text-red-300"
              >
                <RiDeleteBinLine size={18} />
              </button>
            </div>
          </div>
        ) : (
          <div className="mb-6 flex items-center gap-2 rounded-lg border border-white/10 bg-[#12141c] px-3 py-2">
            <RiSearchLine size={18} className="text-slate-500" />
            <input
              type="text"
              value={search}
              onChange={(event) => setSearch(event.target.value)}
              placeholder="Buscar proyectos..."
              className="w-full bg-transparent text-sm text-slate-200 placeholder:text-slate-500 outline-none"
            />
          </div>
        )}

        {loading && (
          <div className="flex items-center justify-center gap-2 py-20 text-sm text-slate-400">
            <RiLoader4Line size={18} className="animate-spin" />
            Cargando...
          </div>
        )}

        {!loading && error && (
          <p className="rounded-lg border border-red-500/20 bg-red-500/10 px-3 py-2 text-sm text-red-300">
            No se pudieron cargar los proyectos: {error}
          </p>
        )}

        {!loading && !error && isEmpty && !query && (
          <div className="flex flex-col items-center justify-center rounded-2xl border border-dashed border-white/10 bg-[#12141c] py-20 text-center">
            <p className="text-sm text-slate-400">
              {folderId ? 'Esta carpeta está vacía.' : 'No tienes proyectos ni carpetas todavía.'}
            </p>
            <div className="mt-4 flex gap-3">
              {!folderId && (
                <button
                  type="button"
                  onClick={() => setShowFolderModal(true)}
                  className="inline-flex items-center gap-1.5 rounded-lg border border-white/10 px-3 py-2 text-sm font-medium text-slate-200 hover:bg-white/5"
                >
                  <RiFolderAddLine size={18} />
                  Nueva carpeta
                </button>
              )}
              {folderId && (
                <button
                  type="button"
                  onClick={() => setShowCreateModal(true)}
                  className="inline-flex items-center gap-1.5 rounded-lg bg-brand-600 px-3 py-2 text-sm font-medium text-white hover:bg-brand-500"
                >
                  <RiAddLine size={18} />
                  Crear proyecto
                </button>
              )}
            </div>
          </div>
        )}

        {!loading && !error && isEmpty && query && (
          <p className="py-10 text-center text-sm text-slate-500">
            Nada coincide con "{search}".
          </p>
        )}

        {!loading && !error && !isEmpty && (
          <>
            {filteredFolders.length > 0 && (
              <div className="mb-6 flex flex-col gap-2">
                {filteredFolders.map((folder) => (
                  <div key={folder.id} className={busyId === folder.id ? 'opacity-50' : ''}>
                    <FolderCard
                      folder={folder}
                      selected={selectedKeys.has(`folder:${folder.id}`)}
                      selectionMode={selectionMode}
                      onToggleSelect={toggleSelectFolder}
                      onOpen={(f) => navigate(`/dashboard/folders/${f.id}`)}
                      onRename={setRenamingFolder}
                      onChangeColor={setChangingColorFolder}
                      onDelete={handleDeleteFolder}
                    />
                  </div>
                ))}
              </div>
            )}
            {filteredProjects.length > 0 && (
              <div className="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3">
                {filteredProjects.map((project) => (
                  <div key={project.id} className={busyId === project.id ? 'opacity-50' : ''}>
                    <ProjectCard
                      project={project}
                      selected={selectedKeys.has(`project:${project.id}`)}
                      selectionMode={selectionMode}
                      onToggleSelect={toggleSelectProject}
                      onRename={setRenamingProject}
                      onDuplicate={handleDuplicateProject}
                      onMove={(p) => setMovingProjects([p])}
                      onShare={setSharingProject}
                      onDelete={handleDeleteProject}
                    />
                  </div>
                ))}
              </div>
            )}

            {!folderId && filteredSharedProjects.length > 0 && (
              <div className={filteredFolders.length > 0 || filteredProjects.length > 0 ? 'mt-10' : ''}>
                <h2 className="mb-3 text-sm font-medium text-slate-400">Compartido conmigo</h2>
                <div className="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3">
                  {filteredSharedProjects.map((project) => (
                    <ProjectCard key={project.id} project={project} />
                  ))}
                </div>
              </div>
            )}
          </>
        )}
      </main>

      {showCreateModal && (
        <ProjectModal
          title="Nuevo proyecto"
          submitLabel="Crear proyecto"
          showColor
          onSubmit={handleCreateProject}
          onClose={() => setShowCreateModal(false)}
        />
      )}

      {showFolderModal && (
        <FolderModal
          title="Nueva carpeta"
          submitLabel="Crear carpeta"
          onSubmit={handleCreateFolder}
          onClose={() => setShowFolderModal(false)}
        />
      )}

      {renamingProject && (
        <ProjectModal
          title="Renombrar proyecto"
          submitLabel="Guardar"
          initialName={renamingProject.name}
          initialColor={renamingProject.color}
          showDescription={false}
          showColor
          onSubmit={handleRenameProject}
          onClose={() => setRenamingProject(null)}
        />
      )}

      {renamingFolder && (
        <FolderModal
          title="Renombrar carpeta"
          submitLabel="Guardar"
          initialName={renamingFolder.name}
          initialColor={renamingFolder.color}
          onSubmit={handleRenameFolder}
          onClose={() => setRenamingFolder(null)}
        />
      )}

      {changingColorFolder && (
        <FolderModal
          title="Cambiar color"
          submitLabel="Guardar"
          initialName={changingColorFolder.name}
          initialColor={changingColorFolder.color}
          showName={false}
          onSubmit={handleChangeFolderColor}
          onClose={() => setChangingColorFolder(null)}
        />
      )}

      {movingProjects && (
        <MoveToFolderModal
          folders={folders}
          count={movingProjects.length}
          currentFolderId={movingProjects.length === 1 ? movingProjects[0].folder_id ?? null : undefined}
          onSubmit={handleMoveSubmit}
          onClose={() => setMovingProjects(null)}
        />
      )}

      {sharingProject && (
        <ShareModal project={sharingProject} onClose={() => setSharingProject(null)} />
      )}
    </div>
  )
}

export default Dashboard
