"use client"

import { useEffect, useState, useCallback } from "react"
import { useRouter } from "next/navigation"
import { api, Snapshot, Dataset } from "@/lib/api"
import { Header } from "@/components/Header"
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
import { Button } from "@/components/ui/button"
import { Dialog } from "@/components/ui/dialog"
import { RefreshCw, AlertCircle, Trash2, Plus, RotateCcw, ChevronRight, ChevronDown } from "lucide-react"
import { formatBytes } from "@/lib/utils"

function formatUnix(ts: number) {
  return new Date(ts * 1000).toLocaleString()
}

export default function SnapshotsPage() {
  const router = useRouter()
  const [snapshots, setSnapshots] = useState<Snapshot[]>([])
  const [datasets, setDatasets] = useState<Dataset[]>([])
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState<string | null>(null)
  const [deleting, setDeleting] = useState<string | null>(null)
  const [filterDataset, setFilterDataset] = useState("")

  // Create dialog
  const [createOpen, setCreateOpen] = useState(false)
  const [createDataset, setCreateDataset] = useState("")
  const [createName, setCreateName] = useState("")
  const [creating, setCreating] = useState(false)

  // Rollback dialog
  const [rollbackTarget, setRollbackTarget] = useState<string | null>(null)
  const [rollingBack, setRollingBack] = useState(false)
  const [expandedDatasets, setExpandedDatasets] = useState<Set<string>>(new Set())

  const fetchSnapshots = useCallback(async (dataset?: string) => {
    try {
      setLoading(true)
      setError(null)
      const data = await api.getSnapshots(dataset || undefined)
      setSnapshots(data)
      // Auto-expand all top-level datasets so rows are visible by default
      const topDs = new Set(data.map((s) => s.name.split("@")[0].split("/")[0]))
      setExpandedDatasets(topDs)
    } catch (err) {
      setError(err instanceof Error ? err.message : "Failed to fetch snapshots")
    } finally {
      setLoading(false)
    }
  }, [])

  useEffect(() => {
    const token = localStorage.getItem("access_token")
    if (!token) { router.push("/login"); return }

    fetchSnapshots()
    api.getDatasets().then(setDatasets).catch(() => {})
    const iv = setInterval(() => fetchSnapshots(filterDataset || undefined), 60000)
    return () => clearInterval(iv)
  }, [router, fetchSnapshots, filterDataset])

  const handleFilterChange = (ds: string) => {
    setFilterDataset(ds)
    fetchSnapshots(ds || undefined)
  }

  const handleDelete = async (name: string) => {
    if (!confirm(`Delete snapshot "${name}"?\nThis cannot be undone.`)) return
    try {
      setDeleting(name)
      await api.deleteSnapshot(name)
      setSnapshots((prev) => prev.filter((s) => s.name !== name))
    } catch (err) {
      setError(err instanceof Error ? err.message : "Failed to delete snapshot")
    } finally {
      setDeleting(null)
    }
  }

  const handleCreate = async () => {
    if (!createDataset) return
    setCreating(true)
    try {
      await api.createSnapshot(createDataset, createName || undefined)
      setCreateOpen(false)
      setCreateDataset("")
      setCreateName("")
      fetchSnapshots(filterDataset || undefined)
    } catch (err) {
      setError(err instanceof Error ? err.message : "Failed to create snapshot")
    } finally {
      setCreating(false)
    }
  }

  const handleRollback = async () => {
    if (!rollbackTarget) return
    setRollingBack(true)
    try {
      await api.rollbackSnapshot(rollbackTarget)
      setRollbackTarget(null)
      fetchSnapshots(filterDataset || undefined)
    } catch (err) {
      setError(err instanceof Error ? err.message : "Rollback failed")
    } finally {
      setRollingBack(false)
    }
  }

  // Unique dataset names for filter dropdown
  const datasetNames = Array.from(
    new Set(snapshots.map((s) => s.name.split("@")[0]).filter(Boolean))
  ).sort()

  const getDatasetDepth = (name: string): number => {
    return name.split("/").length - 1
  }

  const getSnapshotsByDataset = (dsName: string): Snapshot[] => {
    return snapshots.filter((s) => s.name.split("@")[0] === dsName)
  }

  const getTopLevelDatasets = (): string[] => {
    const topLevel = new Set<string>()
    snapshots.forEach((snap) => {
      const dsName = snap.name.split("@")[0]
      const topDsName = dsName.split("/")[0]
      topLevel.add(topDsName)
    })
    return Array.from(topLevel).sort()
  }

  const getAllDatasetsByPrefix = (prefix?: string): string[] => {
    const allDs = new Set<string>()
    snapshots.forEach((snap) => {
      const dsName = snap.name.split("@")[0]
      if (!prefix) {
        if (dsName.split("/").length === 1) allDs.add(dsName)
      } else {
        const dsPrefix = prefix + "/"
        if (dsName.startsWith(dsPrefix) && dsName !== prefix) {
          const remaining = dsName.slice(dsPrefix.length)
          if (remaining.split("/").length === 1) {
            allDs.add(dsName)
          }
        }
      }
    })
    return Array.from(allDs).sort()
  }

  const toggleExpand = (name: string) => {
    const newExpanded = new Set(expandedDatasets)
    if (newExpanded.has(name)) {
      newExpanded.delete(name)
    } else {
      newExpanded.add(name)
    }
    setExpandedDatasets(newExpanded)
  }

  const renderSnapshotTree = (parentDs?: string): React.ReactNode[] => {
    const items: React.ReactNode[] = []
    const datasets = parentDs ? getAllDatasetsByPrefix(parentDs) : getTopLevelDatasets()

    datasets.forEach((dsName) => {
      const childDatasets = getAllDatasetsByPrefix(dsName)
      const isExpanded = expandedDatasets.has(dsName)
      const depth = getDatasetDepth(dsName)
      const snapshotsForDs = getSnapshotsByDataset(dsName)

      snapshotsForDs.forEach((snap, idx) => {
        const [, tag] = snap.name.split("@")
        items.push(
          <tr key={snap.name} className="border-b border-border/50 hover:bg-muted/30">
            <td className="py-3 px-4 text-muted-foreground font-mono text-xs" style={{ paddingLeft: `${depth * 24 + 16}px` }}>
              <div className="flex items-center gap-2">
                {idx === 0 && childDatasets.length > 0 && (
                  <button
                    onClick={() => toggleExpand(dsName)}
                    className="p-0 hover:bg-muted rounded"
                  >
                    {isExpanded ? (
                      <ChevronDown className="w-4 h-4" />
                    ) : (
                      <ChevronRight className="w-4 h-4" />
                    )}
                  </button>
                )}
                {(idx > 0 || childDatasets.length === 0) && <div className="w-4" />}
                <span>{idx === 0 ? dsName.split("/").pop() : ""}</span>
              </div>
            </td>
            <td className="py-3 px-4 font-mono text-xs font-medium">{tag}</td>
            <td className="py-3 px-4 text-muted-foreground">{formatUnix(snap.created)}</td>
            <td className="py-3 px-4">{formatBytes(snap.used)}</td>
            <td className="py-3 px-4">{formatBytes(snap.referenced)}</td>
            <td className="py-3 px-4 text-right">
              <div className="flex justify-end gap-1">
                <Button
                  variant="ghost"
                  size="sm"
                  title="Rollback to this snapshot"
                  onClick={() => setRollbackTarget(snap.name)}
                >
                  <RotateCcw className="w-4 h-4" />
                </Button>
                <Button
                  variant="ghost"
                  size="sm"
                  title="Delete snapshot"
                  onClick={() => handleDelete(snap.name)}
                  disabled={deleting === snap.name}
                >
                  <Trash2 className="w-4 h-4" />
                </Button>
              </div>
            </td>
          </tr>
        )
      })

      if (isExpanded && childDatasets.length > 0) {
        items.push(...renderSnapshotTree(dsName))
      }
    })

    return items
  }

  return (
    <div className="min-h-screen bg-background">
      <Header />

      <main className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
        {/* Page Header */}
        <div className="flex items-center justify-between mb-6">
          <div>
            <h1 className="text-3xl font-bold">Snapshots</h1>
            <p className="text-muted-foreground mt-1">Manage ZFS snapshots</p>
          </div>
          <div className="flex gap-2">
            <Button variant="outline" size="sm" onClick={() => fetchSnapshots(filterDataset || undefined)} disabled={loading}>
              <RefreshCw className={`w-4 h-4 mr-2 ${loading ? "animate-spin" : ""}`} />
              Refresh
            </Button>
            <Button size="sm" onClick={() => setCreateOpen(true)}>
              <Plus className="w-4 h-4 mr-2" />
              New Snapshot
            </Button>
          </div>
        </div>

        {/* Filter */}
        <div className="mb-6 flex items-center gap-3">
          <label className="text-sm text-muted-foreground">Dataset:</label>
          <select
            value={filterDataset}
            onChange={(e) => handleFilterChange(e.target.value)}
            className="text-sm bg-background border border-border rounded-md px-3 py-1.5 focus:outline-none focus:ring-2 focus:ring-ring"
          >
            <option value="">All datasets</option>
            {datasetNames.map((ds) => (
              <option key={ds} value={ds}>{ds}</option>
            ))}
          </select>
          <span className="text-sm text-muted-foreground">{snapshots.length} snapshots</span>
        </div>

        {/* Error */}
        {error && (
          <div className="mb-6 flex items-center gap-3 rounded-md border border-destructive/40 bg-destructive/10 px-4 py-3 text-sm text-destructive">
            <AlertCircle className="w-4 h-4 flex-shrink-0" />
            {error}
          </div>
        )}

        {/* Loading */}
        {loading && snapshots.length === 0 && (
          <div className="text-center py-12">
            <RefreshCw className="w-8 h-8 text-muted-foreground animate-spin mx-auto" />
            <p className="mt-4 text-muted-foreground">Loading snapshots…</p>
          </div>
        )}

        {/* Table */}
        {snapshots.length > 0 && (
          <Card>
            <CardHeader>
              <CardTitle>Snapshots</CardTitle>
            </CardHeader>
            <CardContent className="p-0">
              <div className="overflow-x-auto">
                <table className="w-full text-sm">
                  <thead className="border-b border-border bg-muted/30">
                    <tr>
                      <th className="text-left py-3 px-4 font-medium text-muted-foreground">Dataset</th>
                      <th className="text-left py-3 px-4 font-medium text-muted-foreground">Snapshot</th>
                      <th className="text-left py-3 px-4 font-medium text-muted-foreground">Created</th>
                      <th className="text-left py-3 px-4 font-medium text-muted-foreground">Used</th>
                      <th className="text-left py-3 px-4 font-medium text-muted-foreground">Referenced</th>
                      <th className="text-right py-3 px-4 font-medium text-muted-foreground">Actions</th>
                    </tr>
                  </thead>
                  <tbody>
                    {renderSnapshotTree()}
                  </tbody>
                </table>
              </div>
            </CardContent>
          </Card>
        )}

        {!loading && snapshots.length === 0 && !error && (
          <Card>
            <CardContent className="py-12 text-center text-muted-foreground">
              No snapshots found.
            </CardContent>
          </Card>
        )}
      </main>

      {/* Create Snapshot Dialog */}
      <Dialog open={createOpen} onClose={() => setCreateOpen(false)} title="Create Snapshot">
        <div className="space-y-4">
          <div>
            <label className="block text-sm font-medium mb-1">Dataset *</label>
            <select
              value={createDataset}
              onChange={(e) => setCreateDataset(e.target.value)}
              className="w-full text-sm bg-background border border-border rounded-md px-3 py-2 focus:outline-none focus:ring-2 focus:ring-ring"
            >
              <option value="">Select dataset…</option>
              {datasets.filter((d) => d.type === "filesystem").map((d) => (
                <option key={d.name} value={d.name}>{d.name}</option>
              ))}
            </select>
          </div>
          <div>
            <label className="block text-sm font-medium mb-1">
              Name <span className="text-muted-foreground font-normal">(optional, auto-generated if empty)</span>
            </label>
            <input
              type="text"
              value={createName}
              onChange={(e) => setCreateName(e.target.value)}
              placeholder="e.g. before-upgrade"
              className="w-full text-sm bg-background border border-border rounded-md px-3 py-2 focus:outline-none focus:ring-2 focus:ring-ring"
            />
          </div>
          <div className="flex justify-end gap-2 pt-2">
            <Button variant="outline" onClick={() => setCreateOpen(false)}>Cancel</Button>
            <Button onClick={handleCreate} disabled={!createDataset || creating}>
              {creating ? "Creating…" : "Create"}
            </Button>
          </div>
        </div>
      </Dialog>

      {/* Rollback Dialog */}
      <Dialog
        open={!!rollbackTarget}
        onClose={() => setRollbackTarget(null)}
        title="Rollback to Snapshot"
      >
        <div className="space-y-4">
          <div className="rounded-md border border-destructive/40 bg-destructive/10 p-3 text-sm text-destructive">
            <strong>Warning:</strong> Rollback will permanently destroy all data written after this snapshot.
            This cannot be undone.
          </div>
          <p className="text-sm">
            Roll back to: <span className="font-mono font-medium">{rollbackTarget}</span>?
          </p>
          <div className="flex justify-end gap-2 pt-2">
            <Button variant="outline" onClick={() => setRollbackTarget(null)}>Cancel</Button>
            <Button
              variant="destructive"
              onClick={handleRollback}
              disabled={rollingBack}
            >
              {rollingBack ? "Rolling back…" : "Rollback"}
            </Button>
          </div>
        </div>
      </Dialog>
    </div>
  )
}
