import { useState } from 'react'
import { AlertCircle, Plus } from 'lucide-react'
import { isAxiosError } from 'axios'
import { toast } from 'sonner'
import { Button } from '@/components/ui/button'
import { Skeleton } from '@/components/ui/skeleton'
import { Switch } from '@/components/ui/switch'
import { Label } from '@/components/ui/label'
import { Alert, AlertDescription } from '@/components/ui/alert'
import { CanPerform } from '@/components/auth/CanPerform'
import { CategoryTree } from '../components/CategoryTree'
import { RubroFormDialog } from '../components/RubroFormDialog'
import { DeleteRubroDialog } from '../components/DeleteRubroDialog'
import { MoveRubroDialog } from '../components/MoveRubroDialog'
import { useRubrosTree } from '../hooks/useRubrosTree'
import { useCreateRubro } from '../hooks/useCreateRubro'
import { useUpdateRubro } from '../hooks/useUpdateRubro'
import { useDeleteRubro } from '../hooks/useDeleteRubro'
import type { Rubro } from '../types'
import type { RubroFormValues } from '../components/RubroFormDialog'

export function RubrosPage() {
  const [incluirInactivos, setIncluirInactivos] = useState(false)

  // Dialog states
  const [formOpen, setFormOpen] = useState(false)
  const [editingRubro, setEditingRubro] = useState<Rubro | undefined>(undefined)
  const [pendingParentId, setPendingParentId] = useState<number | null>(null)
  const [deleteOpen, setDeleteOpen] = useState(false)
  const [deletingRubro, setDeletingRubro] = useState<Rubro | null>(null)
  const [formError, setFormError] = useState<unknown>(null)
  const [moveTarget, setMoveTarget] = useState<Rubro | null>(null)

  const { data: tree, isLoading, isError } = useRubrosTree(incluirInactivos)
  const { mutateAsync: createRubro, isPending: creating } = useCreateRubro()
  const { mutateAsync: updateRubro, isPending: updating } = useUpdateRubro()
  const { mutateAsync: deleteRubro } = useDeleteRubro()

  function handleNewRubro() {
    setEditingRubro(undefined)
    setPendingParentId(null)
    setFormError(null)
    setFormOpen(true)
  }

  function handleAddChild(parentId: number) {
    setEditingRubro(undefined)
    setPendingParentId(parentId)
    setFormError(null)
    setFormOpen(true)
  }

  function handleEdit(rubro: Rubro) {
    setEditingRubro(rubro)
    setPendingParentId(null)
    setFormError(null)
    setFormOpen(true)
  }

  function handleDelete(rubro: Rubro) {
    setDeletingRubro(rubro)
    setDeleteOpen(true)
  }

  async function handleFormSubmit(values: RubroFormValues) {
    setFormError(null)
    try {
      const tarifarioId = values.tarifarioBaseId ?? null

      if (editingRubro) {
        await updateRubro({
          id: editingRubro.id,
          data: { nombre: values.nombre, tarifarioBaseId: tarifarioId },
        })
        toast.success('Rubro actualizado')
      } else {
        await createRubro({
          nombre: values.nombre,
          parentId: pendingParentId,
          tarifarioBaseId: tarifarioId,
        })
        toast.success('Rubro creado')
      }
      setFormOpen(false)
    } catch (err) {
      setFormError(err)
      if (!isAxiosError(err) || (err.response?.status !== 409 && err.response?.status !== 422)) {
        toast.error('Error al guardar el rubro')
      }
    }
  }

  async function handleDeleteConfirm(id: number) {
    await deleteRubro(id)
    setDeleteOpen(false)
    toast.success('Rubro desactivado')
  }

  return (
    <div className="space-y-4">
      {/* Header */}
      <div className="flex items-center justify-between">
        <h1 className="text-xl font-semibold tracking-tight">Rubros</h1>
        <div className="flex items-center gap-3">
          <div className="flex items-center gap-2">
            <Switch
              id="incluir-inactivos"
              checked={incluirInactivos}
              onCheckedChange={setIncluirInactivos}
            />
            <Label htmlFor="incluir-inactivos" className="text-sm text-muted-foreground cursor-pointer">
              Incluir inactivos
            </Label>
          </div>
          <CanPerform permission="catalogo:rubros:gestionar">
            <Button size="sm" onClick={handleNewRubro}>
              <Plus className="h-4 w-4 mr-2" />
              Nuevo rubro
            </Button>
          </CanPerform>
        </div>
      </div>

      {/* Content */}
      {isLoading ? (
        <div className="space-y-2">
          {Array.from({ length: 5 }).map((_, i) => (
            <Skeleton key={i} className="h-9 w-full rounded-md" />
          ))}
        </div>
      ) : isError ? (
        <Alert variant="destructive">
          <AlertCircle className="h-4 w-4" />
          <AlertDescription>
            Error al cargar los rubros. Intentá de nuevo.
          </AlertDescription>
        </Alert>
      ) : (
        <div className="surface rounded-lg p-2">
          <CanPerform
            permission="catalogo:rubros:gestionar"
            fallback={
              <CategoryTree
                nodes={tree ?? []}
                onEdit={() => {}}
                onDelete={() => {}}
                onAddChild={() => {}}
                onMove={() => {}}
                canEdit={false}
              />
            }
          >
            <CategoryTree
              nodes={tree ?? []}
              onEdit={handleEdit}
              onDelete={handleDelete}
              onAddChild={handleAddChild}
              onMove={(rubro) => setMoveTarget(rubro)}
              canEdit={true}
            />
          </CanPerform>
        </div>
      )}

      {/* Form dialog */}
      <RubroFormDialog
        open={formOpen}
        onOpenChange={setFormOpen}
        rubro={editingRubro}
        parentId={pendingParentId}
        onSubmit={handleFormSubmit}
        isPending={creating || updating}
        error={formError}
      />

      {/* Delete dialog */}
      {deletingRubro && (
        <DeleteRubroDialog
          open={deleteOpen}
          onOpenChange={setDeleteOpen}
          rubro={deletingRubro}
          onConfirm={handleDeleteConfirm}
        />
      )}

      {/* Move dialog */}
      <MoveRubroDialog
        open={!!moveTarget}
        onOpenChange={(o) => !o && setMoveTarget(null)}
        rubro={moveTarget}
        tree={tree ?? []}
      />
    </div>
  )
}
