import { useState, useEffect, useMemo } from 'react'
import { X } from 'lucide-react'
import { foldersApi } from '@/api/folders'
import type { FolderListItem, FolderCreate, FolderUpdate } from '@/types'
import { cn } from '@/lib/utils'
import { toast } from '@/lib/toast'

// Predefined color options
const FOLDER_COLORS = [
  '#6366f1', // Indigo (default)
  '#8b5cf6', // Violet
  '#ec4899', // Pink
  '#ef4444', // Red
  '#f97316', // Orange
  '#eab308', // Yellow
  '#22c55e', // Green
  '#14b8a6', // Teal
  '#3b82f6', // Blue
  '#64748b', // Slate
]

interface FolderEditModalProps {
  folder: FolderListItem | null // null for create mode
  parentId?: string | null // Pre-selected parent for creating subfolders
  folders: FolderListItem[] // All folders for parent dropdown
  isOpen: boolean
  onClose: () => void
  onSave: () => void
}

// Get all descendant IDs of a folder (to prevent cycles)
function getDescendantIds(folders: FolderListItem[], folderId: string): Set<string> {
  const descendants = new Set<string>()
  const children = folders.filter((f) => f.parent_id === folderId)
  children.forEach((child) => {
    descendants.add(child.id)
    getDescendantIds(folders, child.id).forEach((id) => descendants.add(id))
  })
  return descendants
}

// Calculate folder depth
function getFolderDepth(folders: FolderListItem[], folderId: string | null): number {
  if (!folderId) return 0
  const folder = folders.find((f) => f.id === folderId)
  if (!folder || !folder.parent_id) return 1
  return 1 + getFolderDepth(folders, folder.parent_id)
}

// Get indented folder name for dropdown display
function getIndentedName(folders: FolderListItem[], folderId: string): string {
  const depth = getFolderDepth(folders, folderId)
  const folder = folders.find((f) => f.id === folderId)
  const indent = '  '.repeat(depth - 1)
  return indent + (depth > 1 ? '└ ' : '') + (folder?.name || '')
}

export function FolderEditModal({
  folder,
  parentId: initialParentId,
  folders,
  isOpen,
  onClose,
  onSave,
}: FolderEditModalProps) {
  const [name, setName] = useState('')
  const [color, setColor] = useState(FOLDER_COLORS[0])
  const [parentId, setParentId] = useState<string | null>(null)
  const [isSubmitting, setIsSubmitting] = useState(false)

  const isEditMode = folder !== null

  // Build list of valid parent options
  const parentOptions = useMemo(() => {
    // Can't be own parent, can't create cycles
    const invalidIds = new Set<string>()

    if (folder) {
      // Exclude self and all descendants
      invalidIds.add(folder.id)
      getDescendantIds(folders, folder.id).forEach((id) => invalidIds.add(id))
    }

    // Filter to valid parents only (max depth 2 so that new folder is at depth 3)
    return folders
      .filter((f) => !invalidIds.has(f.id))
      .filter((f) => {
        const depth = getFolderDepth(folders, f.id)
        // If creating new folder, parent can be at depth 1 or 2 (new folder at 2 or 3)
        // If editing, we need to check if moving would exceed depth limit
        if (folder) {
          // Get max depth of folder's subtree
          const getMaxSubtreeDepth = (folderId: string): number => {
            const children = folders.filter((c) => c.parent_id === folderId)
            if (children.length === 0) return 0
            return 1 + Math.max(...children.map((c) => getMaxSubtreeDepth(c.id)))
          }
          const subtreeDepth = getMaxSubtreeDepth(folder.id)
          // New parent depth + 1 (for this folder) + subtree must be <= 3
          return depth + 1 + subtreeDepth <= 3
        }
        return depth < 3 // Can add child to folders at depth 1 or 2
      })
      .sort((a, b) => {
        // Sort by hierarchy for better UX
        const aPath = getPath(folders, a.id)
        const bPath = getPath(folders, b.id)
        return aPath.localeCompare(bPath)
      })
  }, [folder, folders])

  // Get path string for sorting
  function getPath(allFolders: FolderListItem[], folderId: string): string {
    const f = allFolders.find((x) => x.id === folderId)
    if (!f) return ''
    if (!f.parent_id) return f.name
    return getPath(allFolders, f.parent_id) + '/' + f.name
  }

  useEffect(() => {
    if (folder) {
      setName(folder.name)
      setColor(folder.color)
      setParentId(folder.parent_id || null)
    } else {
      setName('')
      setColor(FOLDER_COLORS[0])
      setParentId(initialParentId || null)
    }
  }, [folder, initialParentId, isOpen])

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault()

    if (!name.trim()) {
      toast.error('Folder name is required')
      return
    }

    setIsSubmitting(true)
    try {
      if (isEditMode && folder) {
        const updateData: FolderUpdate = { name, color }
        // Only include parent_id if it changed
        if (parentId !== folder.parent_id) {
          updateData.parent_id = parentId
        }
        await foldersApi.update(folder.id, updateData)
        toast.success('Folder updated successfully')
      } else {
        const createData: FolderCreate = { name, color }
        if (parentId) {
          createData.parent_id = parentId
        }
        await foldersApi.create(createData)
        toast.success('Folder created successfully')
      }
      onSave()
      onClose()
      // Dispatch event to refresh folder list
      window.dispatchEvent(new Event('folder-changed'))
    } catch (err) {
      const errorMessage = err instanceof Error && 'response' in err
        ? (err as { response?: { data?: { detail?: string } } }).response?.data?.detail
        : undefined
      toast.error(errorMessage || 'Failed to save folder')
    } finally {
      setIsSubmitting(false)
    }
  }

  if (!isOpen) return null

  return (
    <div className="fixed inset-0 z-50 flex items-center justify-center">
      {/* Backdrop */}
      <div className="absolute inset-0 bg-black/80 backdrop-blur-sm" onClick={onClose} />

      {/* Modal */}
      <div className="relative z-10 w-full max-w-md bg-card border border-border rounded-2xl p-6 shadow-lg">
        <div className="mb-4 flex items-center justify-between">
          <h2 className="text-lg font-semibold text-foreground">
            {isEditMode ? 'Edit Folder' : initialParentId ? 'Create Subfolder' : 'Create Folder'}
          </h2>
          <button onClick={onClose} className="rounded-md p-1 text-muted-foreground hover:bg-accent/50 hover:text-foreground">
            <X className="h-5 w-5" />
          </button>
        </div>

        <form onSubmit={handleSubmit}>
          {/* Name input */}
          <div className="mb-4">
            <label htmlFor="folder-name" className="block text-sm font-medium text-foreground">
              Name
            </label>
            <input
              id="folder-name"
              type="text"
              value={name}
              onChange={(e) => setName(e.target.value)}
              placeholder="e.g., Citrix Issues"
              className={cn(
                'mt-1 block w-full rounded-md border px-3 py-2 text-sm',
                'bg-card text-foreground placeholder:text-muted-foreground',
                'focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary/20',
                'border-border'
              )}
              autoFocus
            />
          </div>

          {/* Parent folder dropdown */}
          <div className="mb-4">
            <label htmlFor="folder-parent" className="block text-sm font-medium text-foreground">
              Parent Folder
            </label>
            <select
              id="folder-parent"
              value={parentId || ''}
              onChange={(e) => setParentId(e.target.value || null)}
              className={cn(
                'mt-1 block w-full rounded-md border px-3 py-2 text-sm',
                'bg-card text-foreground',
                'focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary/20',
                'border-border'
              )}
            >
              <option value="">None (root level)</option>
              {parentOptions.map((f) => (
                <option key={f.id} value={f.id}>
                  {getIndentedName(folders, f.id)}
                </option>
              ))}
            </select>
            <p className="mt-1 text-xs text-muted-foreground">
              Folders can be nested up to 3 levels deep.
            </p>
          </div>

          {/* Color picker */}
          <div className="mb-6">
            <label className="block text-sm font-medium text-foreground">Color</label>
            <div className="mt-2 flex flex-wrap gap-2">
              {FOLDER_COLORS.map((c) => (
                <button
                  key={c}
                  type="button"
                  onClick={() => setColor(c)}
                  className={cn(
                    'h-8 w-8 rounded-full transition-transform',
                    color === c && 'ring-2 ring-offset-2 ring-offset-black ring-white/50 scale-110'
                  )}
                  style={{ backgroundColor: c }}
                  title={c}
                />
              ))}
            </div>
          </div>

          {/* Actions */}
          <div className="flex justify-end gap-3">
            <button
              type="button"
              onClick={onClose}
              className={cn('rounded-md border border-border px-4 py-2 text-sm text-muted-foreground', 'hover:bg-accent hover:text-foreground')}
            >
              Cancel
            </button>
            <button
              type="submit"
              disabled={isSubmitting}
              className={cn(
                'rounded-md bg-gradient-brand px-4 py-2 text-sm font-medium text-white shadow-lg shadow-primary/20',
                'hover:opacity-90',
                'disabled:opacity-50'
              )}
            >
              {isSubmitting ? 'Saving...' : isEditMode ? 'Save Changes' : 'Create Folder'}
            </button>
          </div>
        </form>
      </div>
    </div>
  )
}

export default FolderEditModal
