"use client";

import * as React from "react";
import { MinusIcon, PlusIcon } from "lucide-react";

import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { cn } from "@/lib/utils";

const fmt0 = new Intl.NumberFormat("en-US", { maximumFractionDigits: 0 });
const fmt2 = new Intl.NumberFormat("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 });

const SIZE = {
  sm: "text-xs",
  md: "text-sm",
  lg: "text-lg font-semibold",
  till: "text-4xl font-semibold tracking-tight",
} as const;

/** KES amount with tabular figures. `till` is the large tender-size read-out. */
export function Money({
  amount,
  size = "md",
  decimals = true,
  negative = false,
  className,
}: {
  amount: number;
  size?: keyof typeof SIZE;
  decimals?: boolean;
  negative?: boolean;
  className?: string;
}) {
  return (
    <span className={cn("inline-flex items-baseline gap-1 tabular-nums", SIZE[size], className)}>
      <span className={cn("font-normal text-muted-foreground", size === "till" ? "text-base" : size === "lg" ? "text-xs" : "text-[0.7em]")}>KES</span>
      <span>
        {negative ? "-" : ""}
        {(decimals ? fmt2 : fmt0).format(amount)}
      </span>
    </span>
  );
}

function toNumber(raw: string): number | null {
  const cleaned = raw.replace(/[^0-9.]/g, "");
  if (!cleaned || cleaned === ".") return null;
  const n = Number(cleaned);
  return Number.isFinite(n) ? n : null;
}

/** Money entry: digits only, grouped on blur, KES prefix. `size="till"` for the tendered field. */
export function CurrencyInput({
  defaultValue = null,
  size = "md",
  invalid,
  disabled,
  id,
  "aria-label": ariaLabel,
}: {
  defaultValue?: number | null;
  size?: "md" | "till";
  invalid?: boolean;
  disabled?: boolean;
  id?: string;
  "aria-label"?: string;
}) {
  const [text, setText] = React.useState(defaultValue == null ? "" : fmt2.format(defaultValue));
  return (
    <div className="relative flex items-center">
      <span className={cn("pointer-events-none absolute left-2.5 text-muted-foreground", size === "till" ? "text-sm" : "text-xs")}>KES</span>
      <Input
        id={id}
        aria-label={ariaLabel}
        inputMode="decimal"
        disabled={disabled}
        aria-invalid={invalid || undefined}
        value={text}
        placeholder="0.00"
        onChange={(e) => setText(e.target.value.replace(/[^0-9.,]/g, ""))}
        onBlur={() => {
          const n = toNumber(text);
          setText(n == null ? "" : fmt2.format(n));
        }}
        className={cn("pl-10 text-right tabular-nums", size === "till" && "h-14 pl-12 text-3xl font-semibold")}
      />
    </div>
  );
}

/** Plain numeric field with optional unit suffix and min/max clamping on blur. */
export function NumberInput({
  defaultValue = null,
  min,
  max,
  unit,
  invalid,
  disabled,
  id,
  "aria-label": ariaLabel,
}: {
  defaultValue?: number | null;
  min?: number;
  max?: number;
  unit?: string;
  invalid?: boolean;
  disabled?: boolean;
  id?: string;
  "aria-label"?: string;
}) {
  const [text, setText] = React.useState(defaultValue == null ? "" : String(defaultValue));
  return (
    <div className="relative flex items-center">
      <Input
        id={id}
        aria-label={ariaLabel}
        inputMode="numeric"
        disabled={disabled}
        aria-invalid={invalid || undefined}
        value={text}
        onChange={(e) => setText(e.target.value.replace(/[^0-9]/g, ""))}
        onBlur={() => {
          const n = toNumber(text);
          if (n == null) return setText("");
          setText(String(Math.min(max ?? Infinity, Math.max(min ?? -Infinity, n))));
        }}
        className={cn("text-right tabular-nums", unit && "pr-12")}
      />
      {unit ? <span className="pointer-events-none absolute right-2.5 text-xs text-muted-foreground">{unit}</span> : null}
    </div>
  );
}

/** Minus / value / plus. Disables each end at the limit. */
export function QuantityStepper({
  defaultValue = 1,
  min = 1,
  max = 999,
  size = "md",
  disabled,
}: {
  defaultValue?: number;
  min?: number;
  max?: number;
  size?: "sm" | "md";
  disabled?: boolean;
}) {
  const [value, setValue] = React.useState(defaultValue);
  const btn = size === "sm" ? "icon-xs" : "icon-sm";
  return (
    <div className="inline-flex items-center gap-1 rounded-lg border border-border bg-background p-0.5">
      <Button variant="ghost" size={btn} aria-label="Decrease quantity" disabled={disabled || value <= min} onClick={() => setValue((v) => Math.max(min, v - 1))}>
        <MinusIcon />
      </Button>
      <span className={cn("min-w-8 text-center font-medium tabular-nums", size === "sm" ? "text-xs" : "text-sm", disabled && "text-muted-foreground")} aria-live="polite">
        {value}
      </span>
      <Button variant="ghost" size={btn} aria-label="Increase quantity" disabled={disabled || value >= max} onClick={() => setValue((v) => Math.min(max, v + 1))}>
        <PlusIcon />
      </Button>
    </div>
  );
}

function normalisePhone(raw: string) {
  let d = raw.replace(/\D/g, "");
  if (d.startsWith("254")) d = d.slice(3);
  if (d.startsWith("0")) d = d.slice(1);
  return d.slice(0, 9);
}
const groupPhone = (d: string) => [d.slice(0, 3), d.slice(3, 6), d.slice(6, 9)].filter(Boolean).join(" ");

/** Kenyan mobile number: fixed +254 prefix, 9 national digits, grouped 712 345 678. */
export function PhoneInput({
  defaultValue = "",
  invalid,
  disabled,
  id,
  "aria-label": ariaLabel,
}: {
  defaultValue?: string;
  invalid?: boolean;
  disabled?: boolean;
  id?: string;
  "aria-label"?: string;
}) {
  const [text, setText] = React.useState(groupPhone(normalisePhone(defaultValue)));
  return (
    <div className="relative flex items-center">
      <span className="pointer-events-none absolute left-2.5 text-sm text-muted-foreground tabular-nums">+254</span>
      <Input
        id={id}
        aria-label={ariaLabel ?? "Phone number"}
        type="tel"
        inputMode="tel"
        disabled={disabled}
        aria-invalid={invalid || undefined}
        placeholder="712 345 678"
        value={text}
        onChange={(e) => setText(groupPhone(normalisePhone(e.target.value)))}
        className="pl-12 tabular-nums"
      />
    </div>
  );
}
