import { useState, useRef } from "react"
import { useTranslation } from "react-i18next"
import { Plus, Pencil, Trash2, Check, X } from "lucide-react"
import { toast } from "sonner"
import { useTemplate } from "@/hooks/useTemplate"
import { useCategories } from "@/hooks/useCategories"
import type { TemplateItem, CategoryType } from "@/lib/types"
import { categoryColors } from "@/lib/palette"
import { formatCurrency } from "@/lib/format"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import { Badge } from "@/components/ui/badge"
import { Skeleton } from "@/components/ui/skeleton"
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog"
import {
  Select,
  SelectContent,
  SelectGroup,
  SelectItem,
  SelectLabel,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select"
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table"

// ---------------------------------------------------------------------------
// Constants
// ---------------------------------------------------------------------------

const CATEGORY_TYPES: CategoryType[] = [
  "income",
  "bill",
  "variable_expense",
  "debt",
  "saving",
  "investment",
]

const TIERS: TemplateItem["item_tier"][] = ["fixed", "variable"]

// ---------------------------------------------------------------------------
// Sub-components
// ---------------------------------------------------------------------------

/** Inline-editable template name heading. */
function TemplateName({
  name,
  onSave,
}: {
  name: string
  onSave: (next: string) => Promise<void>
}) {
  const [editing, setEditing] = useState(false)
  const [draft, setDraft] = useState(name)
  const inputRef = useRef<HTMLInputElement>(null)

  function startEdit() {
    setDraft(name)
    setEditing(true)
    // Let React commit the input before focusing.
    setTimeout(() => inputRef.current?.select(), 0)
  }

  async function commit() {
    if (draft.trim() && draft.trim() !== name) {
      await onSave(draft.trim())
    }
    setEditing(false)
  }

  function cancel() {
    setDraft(name)
    setEditing(false)
  }

  if (editing) {
    return (
      <div className="flex items-center gap-2">
        <Input
          ref={inputRef}
          value={draft}
          onChange={(e) => setDraft(e.target.value)}
          className="h-8 text-xl font-semibold"
          onKeyDown={(e) => {
            if (e.key === "Enter") void commit()
            if (e.key === "Escape") cancel()
          }}
        />
        <Button variant="ghost" size="icon" onClick={() => void commit()}>
          <Check className="size-4" />
        </Button>
        <Button variant="ghost" size="icon" onClick={cancel}>
          <X className="size-4" />
        </Button>
      </div>
    )
  }

  return (
    <button
      type="button"
      onClick={startEdit}
      className="group flex items-center gap-2 text-left"
      aria-label="Edit template name"
    >
      <h1 className="text-2xl font-semibold tracking-tight group-hover:underline">{name}</h1>
      <Pencil className="size-4 text-muted-foreground opacity-0 transition-opacity group-hover:opacity-100" />
    </button>
  )
}

// ---------------------------------------------------------------------------
// Dialog state types
// ---------------------------------------------------------------------------

type DialogMode = "create" | "edit"

interface DialogState {
  mode: DialogMode
  item?: TemplateItem
  categoryId: string
  tier: TemplateItem["item_tier"]
  amount: string
}

const DEFAULT_DIALOG: DialogState = {
  mode: "create",
  categoryId: "",
  tier: "fixed",
  amount: "",
}

// ---------------------------------------------------------------------------
// Main page
// ---------------------------------------------------------------------------

export default function TemplatePage() {
  const { t } = useTranslation()
  const { template, items, loading, updateName, createItem, updateItem, deleteItem } =
    useTemplate()
  const { categories } = useCategories()

  const [dialogOpen, setDialogOpen] = useState(false)
  const [dialog, setDialog] = useState<DialogState>(DEFAULT_DIALOG)

  // ------------------------------------------------------------------
  // Dialog helpers
  // ------------------------------------------------------------------

  function openCreate() {
    setDialog({ ...DEFAULT_DIALOG, mode: "create" })
    setDialogOpen(true)
  }

  function openEdit(item: TemplateItem) {
    setDialog({
      mode: "edit",
      item,
      categoryId: item.category_id,
      tier: item.item_tier,
      amount: String(item.budgeted_amount),
    })
    setDialogOpen(true)
  }

  function closeDialog() {
    setDialogOpen(false)
  }

  async function handleSave() {
    const parsed = parseFloat(dialog.amount)
    if (!dialog.categoryId || isNaN(parsed) || parsed < 0) return

    try {
      if (dialog.mode === "edit" && dialog.item) {
        await updateItem.mutateAsync({
          id: dialog.item.id,
          item_tier: dialog.tier,
          budgeted_amount: parsed,
        })
      } else {
        await createItem.mutateAsync({
          category_id: dialog.categoryId,
          item_tier: dialog.tier,
          budgeted_amount: parsed,
        })
      }
      closeDialog()
    } catch {
      toast.error(t("common.error"))
    }
  }

  async function handleDelete(id: string) {
    try {
      await deleteItem.mutateAsync(id)
    } catch {
      toast.error(t("common.error"))
    }
  }

  async function handleNameSave(name: string) {
    try {
      await updateName.mutateAsync(name)
    } catch {
      toast.error(t("common.error"))
    }
  }

  // ------------------------------------------------------------------
  // Derived data: group items by the category type
  // ------------------------------------------------------------------

  const grouped = CATEGORY_TYPES.map((type) => ({
    type,
    items: items.filter((item) => item.category?.type === type),
  })).filter((g) => g.items.length > 0)

  // Categories already belonging to a template item (for the "create"
  // dialog we still allow duplicates, as the spec doesn't forbid them).
  const isSaving =
    createItem.isPending || updateItem.isPending || deleteItem.isPending

  // ------------------------------------------------------------------
  // Render
  // ------------------------------------------------------------------

  if (loading) return (
    <div className="flex flex-col gap-6">
      <div className="flex items-start justify-between gap-4">
        <Skeleton className="h-8 w-48" />
        <Skeleton className="h-9 w-24" />
      </div>
      <div className="space-y-6">
        {[1, 2].map((i) => (
          <div key={i} className="space-y-2">
            <div className="flex items-center gap-3 rounded-sm border-l-4 border-muted bg-muted/30 px-3 py-2">
              <Skeleton className="h-4 w-28" />
            </div>
            {[1, 2, 3].map((j) => (
              <div key={j} className="flex items-center gap-4 px-4 py-2.5 border-b border-border">
                <Skeleton className="h-4 w-36" />
                <Skeleton className="h-5 w-16 rounded-full" />
                <Skeleton className="ml-auto h-4 w-20" />
                <Skeleton className="h-7 w-7 rounded-md" />
              </div>
            ))}
          </div>
        ))}
      </div>
    </div>
  )

  return (
    <div className="flex flex-col gap-6">
      {/* Header — mirrors PageShell's flex items-start justify-between gap-4 layout */}
      <div className="flex items-start justify-between gap-4">
        <TemplateName
          name={template?.name ?? t("template.title")}
          onSave={handleNameSave}
        />
        <div className="shrink-0">
          <Button onClick={openCreate} size="sm" disabled={isSaving}>
            <Plus className="mr-1 size-4" />
            {t("template.addItem")}
          </Button>
        </div>
      </div>

      {/* Empty state */}
      {items.length === 0 ? (
        <p className="text-muted-foreground">{t("template.empty")}</p>
      ) : (
        <div className="space-y-6">
          {grouped.map(({ type, items: groupItems }) => (
            <div key={type}>
              {/* Group heading */}
              <div
                className="mb-2 flex items-center gap-3 rounded-sm border-l-4 bg-muted/30 px-3 py-2"
                style={{ borderLeftColor: categoryColors[type] }}
              >
                <span className="text-sm font-semibold">{t(`categories.types.${type}`)}</span>
              </div>

              <Table>
                <TableHeader>
                  <TableRow>
                    <TableHead>{t("categories.name")}</TableHead>
                    <TableHead>{t("categories.type")}</TableHead>
                    <TableHead className="text-right">
                      {t("template.budgetedAmount")}
                    </TableHead>
                    <TableHead className="w-24" />
                  </TableRow>
                </TableHeader>
                <TableBody>
                  {groupItems.map((item) => (
                    <TableRow key={item.id}>
                      <TableCell className="font-medium">
                        {item.category?.name ?? item.category_id}
                      </TableCell>
                      <TableCell>
                        <TierBadge tier={item.item_tier} t={t} />
                      </TableCell>
                      <TableCell className="text-right tabular-nums">
                        {formatCurrency(item.budgeted_amount)}
                      </TableCell>
                      <TableCell className="text-right">
                        <div className="flex justify-end gap-1">
                          <Button
                            variant="ghost"
                            size="icon"
                            aria-label={t("common.edit")}
                            onClick={() => openEdit(item)}
                            disabled={isSaving}
                          >
                            <Pencil className="size-4" />
                          </Button>
                          <Button
                            variant="ghost"
                            size="icon"
                            aria-label={t("common.delete")}
                            onClick={() => void handleDelete(item.id)}
                            disabled={isSaving}
                          >
                            <Trash2 className="size-4 text-destructive" />
                          </Button>
                        </div>
                      </TableCell>
                    </TableRow>
                  ))}
                </TableBody>
              </Table>
            </div>
          ))}
        </div>
      )}

      {/* Add / Edit dialog */}
      <Dialog open={dialogOpen} onOpenChange={setDialogOpen}>
        <DialogContent>
          <DialogHeader>
            <DialogTitle>
              {dialog.mode === "edit"
                ? t("common.edit")
                : t("template.addItem")}
            </DialogTitle>
          </DialogHeader>

          <div className="space-y-4">
            {/* Category picker — only shown when creating */}
            {dialog.mode === "create" && (
              <div className="space-y-2">
                <Label>{t("categories.name")}</Label>
                <Select
                  value={dialog.categoryId}
                  onValueChange={(v) =>
                    setDialog((prev) => ({ ...prev, categoryId: v }))
                  }
                >
                  <SelectTrigger>
                    <SelectValue placeholder={t("quickAdd.pickCategory")} />
                  </SelectTrigger>
                  <SelectContent>
                    {CATEGORY_TYPES.map((type) => {
                      const filtered = categories.filter((c) => c.type === type)
                      if (filtered.length === 0) return null
                      return (
                        <SelectGroup key={type}>
                          <SelectLabel className="flex items-center gap-1.5">
                            <div
                              className="size-2 rounded-full"
                              style={{ backgroundColor: categoryColors[type] }}
                            />
                            {t(`categories.types.${type}`)}
                          </SelectLabel>
                          {filtered.map((cat) => (
                            <SelectItem key={cat.id} value={cat.id}>
                              {cat.name}
                            </SelectItem>
                          ))}
                        </SelectGroup>
                      )
                    })}
                  </SelectContent>
                </Select>
              </div>
            )}

            {/* Tier */}
            <div className="space-y-2">
              <Label>{t("categories.type")}</Label>
              <Select
                value={dialog.tier}
                onValueChange={(v) =>
                  setDialog((prev) => ({
                    ...prev,
                    tier: v as TemplateItem["item_tier"],
                  }))
                }
              >
                <SelectTrigger>
                  <SelectValue />
                </SelectTrigger>
                <SelectContent>
                  {TIERS.map((tier) => (
                    <SelectItem key={tier} value={tier}>
                      {t(`template.${tier}`)}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>

            {/* Budgeted amount */}
            <div className="space-y-2">
              <Label>{t("template.budgetedAmount")}</Label>
              <Input
                type="number"
                min="0"
                step="0.01"
                value={dialog.amount}
                onChange={(e) =>
                  setDialog((prev) => ({ ...prev, amount: e.target.value }))
                }
                placeholder="0.00"
              />
            </div>

            <div className="flex justify-end gap-2">
              <Button variant="outline" onClick={closeDialog}>
                {t("common.cancel")}
              </Button>
              <Button
                onClick={() => void handleSave()}
                disabled={
                  !dialog.categoryId ||
                  !dialog.amount ||
                  isNaN(parseFloat(dialog.amount)) ||
                  createItem.isPending ||
                  updateItem.isPending
                }
              >
                {t("common.save")}
              </Button>
            </div>
          </div>
        </DialogContent>
      </Dialog>
    </div>
  )
}

// ---------------------------------------------------------------------------
// Small helper component
// ---------------------------------------------------------------------------

function TierBadge({
  tier,
  t,
}: {
  tier: TemplateItem["item_tier"]
  t: (key: string) => string
}) {
  return (
    <Badge variant={tier === "fixed" ? "default" : "secondary"}>
      {t(`template.${tier}`)}
    </Badge>
  )
}
