"use client";

import { useEffect, useMemo, useState } from "react";
import { AlertCircle, ChevronDown, ChevronUp, Pencil, Plus, Trash2, PackageX } from "lucide-react";
import { PageHeader } from "@/components/ui/PageHeader";
import { NetworkBadge } from "@/components/NetworkBadge";
import { Button } from "@/components/ui/Button";
import { Switch } from "@/components/ui/Switch";
import { Drawer } from "@/components/ui/Drawer";
import { TextField, SelectField } from "@/components/ui/Field";
import { Skeleton } from "@/components/ui/Skeleton";
import { EmptyState } from "@/components/ui/EmptyState";
import { getPackageSpecs } from "@/lib/package-specs";
import { NETWORKS, formatCurrency } from "@/lib/mock-data";
import { NetworkId } from "@/lib/types";
import { cn } from "@/lib/cn";
import {
  AdminPackage,
  PackageEditInput,
  CreatePackageInput,
  DuplicateSlugError,
  PackageInUseError,
  fetchAllPackages,
  createPackage,
  generateSlug,
  setPackageActive,
  swapPackageDisplayOrder,
  toDisplayPackage,
  updatePackageDetails,
  deletePackage,
} from "@/lib/data/packages";

// Add/Delete were reopened in schema_09 specifically for this page — see
// that migration's comments and lib/data/packages.ts. Editing, enabling/
// disabling, and reordering were always allowed here.

type FormState = {
  name: string;
  slug: string;
  price: string;
  discountedPrice: string;
  validityDays: string;
  internetGb: string;
  onNetMinutes: string;
  offNetMinutes: string;
  allNetMinutes: string;
  sms: string;
  tagline: string;
};

function packageToForm(pkg: AdminPackage): FormState {
  return {
    name: pkg.name,
    slug: pkg.slug,
    price: String(pkg.price),
    discountedPrice: pkg.discountedPrice != null ? String(pkg.discountedPrice) : "",
    validityDays: String(pkg.validityDays),
    internetGb: pkg.dataMb != null ? String(Math.round((pkg.dataMb / 1024) * 10) / 10) : "",
    onNetMinutes: pkg.onNetMinutes != null ? String(pkg.onNetMinutes) : "",
    offNetMinutes: pkg.offNetMinutes != null ? String(pkg.offNetMinutes) : "",
    allNetMinutes: pkg.allNetMinutes != null ? String(pkg.allNetMinutes) : "",
    sms: pkg.smsCount != null ? String(pkg.smsCount) : "",
    tagline: pkg.tagline ?? "",
  };
}

const EMPTY_FORM: FormState = {
  name: "",
  slug: "",
  price: "",
  discountedPrice: "",
  validityDays: "30",
  internetGb: "",
  onNetMinutes: "",
  offNetMinutes: "",
  allNetMinutes: "",
  sms: "",
  tagline: "",
};

export default function PackagesPage() {
  const [packages, setPackages] = useState<AdminPackage[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [networkFilter, setNetworkFilter] = useState<NetworkId | "all">("all");

  const [editing, setEditing] = useState<AdminPackage | null>(null);
  const [creating, setCreating] = useState(false);
  const [createNetwork, setCreateNetwork] = useState<NetworkId>(NETWORKS[0].id);
  const [slugTouched, setSlugTouched] = useState(false);
  const [form, setForm] = useState<FormState | null>(null);
  const [formError, setFormError] = useState<string | null>(null);
  const [saving, setSaving] = useState(false);

  const [togglingId, setTogglingId] = useState<string | null>(null);
  const [reorderingId, setReorderingId] = useState<string | null>(null);
  const [confirmingDeleteId, setConfirmingDeleteId] = useState<string | null>(null);
  const [deleting, setDeleting] = useState(false);

  async function load() {
    try {
      const result = await fetchAllPackages();
      setPackages(result);
      setError(null);
    } catch (err) {
      setError(err instanceof Error ? err.message : "Couldn't load packages.");
    } finally {
      setLoading(false);
    }
  }

  useEffect(() => {
    load();
  }, []);

  const filtered = useMemo(
    () => packages.filter((p) => networkFilter === "all" || p.networkId === networkFilter),
    [packages, networkFilter]
  );

  function networkGroup(networkId: NetworkId) {
    return packages
      .filter((p) => p.networkId === networkId)
      .sort((a, b) => a.displayOrder - b.displayOrder);
  }

  function openEdit(pkg: AdminPackage) {
    setEditing(pkg);
    setCreating(false);
    setForm(packageToForm(pkg));
    setFormError(null);
    setConfirmingDeleteId(null);
  }

  function openCreate() {
    setEditing(null);
    setCreating(true);
    setCreateNetwork(networkFilter !== "all" ? networkFilter : NETWORKS[0].id);
    setSlugTouched(false);
    setForm(EMPTY_FORM);
    setFormError(null);
  }

  function closeDrawer() {
    setEditing(null);
    setCreating(false);
    setForm(null);
    setFormError(null);
  }

  async function toggleActive(pkg: AdminPackage) {
    setTogglingId(pkg.dbId);
    try {
      await setPackageActive(pkg.dbId, !pkg.isActive);
      await load();
    } catch (err) {
      setError(err instanceof Error ? err.message : "Couldn't update that package.");
    } finally {
      setTogglingId(null);
    }
  }

  async function move(pkg: AdminPackage, direction: "up" | "down") {
    const group = networkGroup(pkg.networkId);
    const index = group.findIndex((p) => p.dbId === pkg.dbId);
    const swapWith = direction === "up" ? group[index - 1] : group[index + 1];
    if (!swapWith) return;

    setReorderingId(pkg.dbId);
    try {
      await swapPackageDisplayOrder(pkg, swapWith);
      await load();
    } catch (err) {
      setError(err instanceof Error ? err.message : "Couldn't reorder that package.");
    } finally {
      setReorderingId(null);
    }
  }

  async function handleDelete(pkg: AdminPackage) {
    if (confirmingDeleteId !== pkg.dbId) {
      setConfirmingDeleteId(pkg.dbId);
      return;
    }
    setDeleting(true);
    try {
      await deletePackage(pkg.dbId);
      await load();
      setConfirmingDeleteId(null);
    } catch (err) {
      setError(
        err instanceof PackageInUseError || err instanceof Error
          ? err.message
          : "Couldn't delete that package."
      );
      setConfirmingDeleteId(null);
    } finally {
      setDeleting(false);
    }
  }

  function validateForm(f: FormState): string | null {
    if (!f.name.trim()) return "Package name is required.";
    if (creating && !f.slug.trim()) return "Slug is required.";
    const price = Number(f.price);
    if (!f.price.trim() || Number.isNaN(price) || price < 0) return "Enter a valid price.";
    if (f.discountedPrice.trim()) {
      const discounted = Number(f.discountedPrice);
      if (Number.isNaN(discounted) || discounted < 0) return "Enter a valid discounted price.";
      if (discounted >= price) return "Discounted price must be lower than the original price.";
    }
    const validity = Number(f.validityDays);
    if (!f.validityDays.trim() || Number.isNaN(validity) || validity <= 0) {
      return "Enter a valid validity in days.";
    }
    const hasInternet = f.internetGb.trim() !== "";
    const hasOnNet = f.onNetMinutes.trim() !== "";
    const hasAllNet = f.allNetMinutes.trim() !== "";
    if (!hasInternet && !hasOnNet && !hasAllNet) {
      return "Needs at least one of Internet Data, On-Net Minutes, or All-Net Minutes.";
    }
    return null;
  }

  async function handleSave() {
    if (!form) return;
    const validationError = validateForm(form);
    if (validationError) {
      setFormError(validationError);
      return;
    }

    setFormError(null);
    setSaving(true);
    try {
      const shared: PackageEditInput = {
        name: form.name.trim(),
        price: Math.round(Number(form.price)),
        discountedPrice: form.discountedPrice.trim() ? Math.round(Number(form.discountedPrice)) : null,
        validityDays: Math.round(Number(form.validityDays)),
        dataMb: form.internetGb.trim() ? Math.round(Number(form.internetGb) * 1024) : null,
        onNetMinutes: form.onNetMinutes.trim() ? Math.round(Number(form.onNetMinutes)) : null,
        offNetMinutes: form.offNetMinutes.trim() ? Math.round(Number(form.offNetMinutes)) : null,
        allNetMinutes: form.allNetMinutes.trim() ? Math.round(Number(form.allNetMinutes)) : null,
        smsCount: form.sms.trim() ? Math.round(Number(form.sms)) : null,
        tagline: form.tagline.trim() || null,
      };

      if (creating) {
        const input: CreatePackageInput = {
          ...shared,
          networkId: createNetwork,
          slug: form.slug.trim(),
        };
        await createPackage(input);
      } else if (editing) {
        await updatePackageDetails(editing.dbId, shared);
      }
      await load();
      closeDrawer();
    } catch (err) {
      setFormError(
        err instanceof DuplicateSlugError || err instanceof Error
          ? err.message
          : "Couldn't save changes."
      );
    } finally {
      setSaving(false);
    }
  }

  return (
    <div>
      <PageHeader
        title="Packages"
        subtitle="The products your customers buy — add, edit, disable, or remove them anytime"
      />

      {error && (
        <div className="mb-4 flex items-center gap-2 rounded-xl bg-danger/10 px-4 py-3 text-sm text-danger">
          <AlertCircle size={16} /> {error}
        </div>
      )}

      <div className="mb-4 flex items-center justify-between gap-3">
        <div className="flex gap-1.5">
          {(["all", ...NETWORKS.map((n) => n.id)] as const).map((id) => (
            <button
              key={id}
              onClick={() => setNetworkFilter(id)}
              className={cn(
                "rounded-xl px-3.5 py-2 text-sm font-medium capitalize transition-colors",
                networkFilter === id
                  ? "bg-gold text-ink font-semibold"
                  : "panel !shadow-none text-muted hover:text-ink dark:hover:text-paper"
              )}
            >
              {id === "all" ? "All Networks" : NETWORKS.find((n) => n.id === id)?.label}
            </button>
          ))}
        </div>
        <Button size="sm" onClick={openCreate}>
          <Plus size={14} /> Add Package
        </Button>
      </div>

      {loading ? (
        <div className="grid grid-cols-1 gap-4 sm:grid-cols-2 xl:grid-cols-3">
          {Array.from({ length: 6 }).map((_, i) => (
            <Skeleton key={i} className="h-48 w-full" />
          ))}
        </div>
      ) : filtered.length === 0 ? (
        <EmptyState
          icon={PackageX}
          title="No packages found"
          description="Try a different network filter, or add a new package."
          action={
            <Button size="sm" onClick={openCreate}>
              <Plus size={14} /> Add Package
            </Button>
          }
        />
      ) : (
        <div className="grid grid-cols-1 gap-4 sm:grid-cols-2 xl:grid-cols-3">
          {filtered.map((pkg) => {
            const specs = getPackageSpecs(toDisplayPackage(pkg));
            const group = networkGroup(pkg.networkId);
            const index = group.findIndex((p) => p.dbId === pkg.dbId);
            const isFirst = index === 0;
            const isLast = index === group.length - 1;
            const isReordering = reorderingId === pkg.dbId;
            const hasDiscount = pkg.discountedPrice != null && pkg.discountedPrice < pkg.price;
            const discountPct = hasDiscount
              ? Math.round(((pkg.price - pkg.discountedPrice!) / pkg.price) * 100)
              : null;

            return (
              <div
                key={pkg.dbId}
                className={cn("panel flex flex-col gap-4 p-4", !pkg.isActive && "opacity-60")}
              >
                <div className="flex items-start justify-between gap-2">
                  <div className="flex items-center gap-3">
                    <NetworkBadge network={pkg.networkId} size="sm" />
                    <div>
                      <p className="text-[13px] font-semibold leading-tight">{pkg.name}</p>
                      <p className="text-[11px] text-muted">{pkg.validityDays} Days</p>
                    </div>
                  </div>
                  <Switch
                    checked={pkg.isActive}
                    onChange={() => toggleActive(pkg)}
                    label={pkg.isActive ? "Disable package" : "Enable package"}
                    disabled={togglingId === pkg.dbId}
                  />
                </div>

                <div className="flex flex-wrap gap-1.5">
                  {specs.map((s) => (
                    <span
                      key={s.key}
                      className="rounded-lg bg-black/[0.03] px-2 py-1 text-[11px] font-medium text-muted dark:bg-white/[0.05]"
                    >
                      {s.value} {s.label}
                    </span>
                  ))}
                  {hasDiscount && (
                    <span className="rounded-lg bg-danger/10 px-2 py-1 text-[11px] font-semibold text-danger">
                      {discountPct}% OFF
                    </span>
                  )}
                </div>

                <div className="flex items-center justify-between border-t border-black/[0.06] pt-3 dark:border-white/[0.06]">
                  <div>
                    {hasDiscount ? (
                      <div className="flex items-baseline gap-2">
                        <p className="tnum font-display text-lg font-bold text-danger">
                          {formatCurrency(pkg.discountedPrice!)}
                        </p>
                        <p className="tnum text-xs text-muted line-through">{formatCurrency(pkg.price)}</p>
                      </div>
                    ) : (
                      <p className="tnum font-display text-lg font-bold">{formatCurrency(pkg.price)}</p>
                    )}
                  </div>
                  <div className="flex items-center gap-1">
                    <button
                      onClick={() => move(pkg, "up")}
                      disabled={isFirst || isReordering}
                      title="Move up"
                      className="flex h-8 w-8 items-center justify-center rounded-lg hover:bg-black/5 disabled:opacity-30 dark:hover:bg-white/5"
                    >
                      <ChevronUp size={14} className="text-muted" />
                    </button>
                    <button
                      onClick={() => move(pkg, "down")}
                      disabled={isLast || isReordering}
                      title="Move down"
                      className="flex h-8 w-8 items-center justify-center rounded-lg hover:bg-black/5 disabled:opacity-30 dark:hover:bg-white/5"
                    >
                      <ChevronDown size={14} className="text-muted" />
                    </button>
                    <button
                      onClick={() => openEdit(pkg)}
                      title="Edit package"
                      className="flex h-8 w-8 items-center justify-center rounded-lg hover:bg-black/5 dark:hover:bg-white/5"
                    >
                      <Pencil size={14} className="text-muted" />
                    </button>
                    <button
                      onClick={() => handleDelete(pkg)}
                      disabled={deleting && confirmingDeleteId === pkg.dbId}
                      title={confirmingDeleteId === pkg.dbId ? "Confirm delete" : "Delete package"}
                      className={cn(
                        "flex h-8 w-8 items-center justify-center rounded-lg disabled:opacity-50",
                        confirmingDeleteId === pkg.dbId
                          ? "bg-danger/10 text-danger"
                          : "hover:bg-black/5 text-muted dark:hover:bg-white/5"
                      )}
                    >
                      <Trash2 size={14} />
                    </button>
                  </div>
                </div>
                {confirmingDeleteId === pkg.dbId && (
                  <p className="text-[11px] text-danger">
                    Tap delete again to confirm — this can't be undone.
                  </p>
                )}
              </div>
            );
          })}
        </div>
      )}

      <Drawer
        open={creating || editing !== null}
        onClose={closeDrawer}
        title={creating ? "Add Package" : "Edit Package"}
        subtitle={creating ? undefined : editing?.slug}
        footer={
          <Button
            fullWidth
            onClick={handleSave}
            disabled={saving || !form?.name.trim() || !form?.price.trim()}
          >
            {saving ? "Saving…" : creating ? "Add Package" : "Save Changes"}
          </Button>
        }
      >
        {form && (
          <div className="flex flex-col gap-4">
            {creating ? (
              <SelectField
                label="Network"
                value={createNetwork}
                options={NETWORKS.map((n) => ({ value: n.id, label: n.label }))}
                onChange={(e) => {
                  const nid = e.target.value as NetworkId;
                  setCreateNetwork(nid);
                  if (!slugTouched) {
                    setForm((f) => f && { ...f, slug: generateSlug(nid, f.name) });
                  }
                }}
              />
            ) : (
              <div className="flex items-center gap-3 rounded-xl border border-black/[0.06] px-3.5 py-3 dark:border-white/[0.06]">
                <NetworkBadge network={editing!.networkId} size="sm" />
                <div>
                  <p className="text-xs text-muted">Network</p>
                  <p className="text-sm font-medium">
                    {NETWORKS.find((n) => n.id === editing!.networkId)?.label}
                  </p>
                </div>
              </div>
            )}

            <TextField
              label="Package Name"
              value={form.name}
              onChange={(e) => {
                const name = e.target.value;
                setForm((f) => f && { ...f, name });
                if (creating && !slugTouched) {
                  setForm((f) => f && { ...f, name, slug: generateSlug(createNetwork, name) });
                }
              }}
            />

            {creating && (
              <TextField
                label="Slug (used in the app's URL — must be unique)"
                value={form.slug}
                onChange={(e) => {
                  setSlugTouched(true);
                  setForm((f) => f && { ...f, slug: e.target.value });
                }}
              />
            )}

            <div className="grid grid-cols-2 gap-3">
              <TextField
                label="Price (Rs)"
                type="number"
                value={form.price}
                onChange={(e) => setForm((f) => f && { ...f, price: e.target.value })}
              />
              <TextField
                label="Validity (Days)"
                type="number"
                value={form.validityDays}
                onChange={(e) => setForm((f) => f && { ...f, validityDays: e.target.value })}
              />
            </div>

            <div>
              <TextField
                label="Discounted Price (Rs, optional)"
                type="number"
                placeholder="Leave blank for no discount"
                value={form.discountedPrice}
                onChange={(e) => setForm((f) => f && { ...f, discountedPrice: e.target.value })}
              />
              {form.discountedPrice.trim() &&
                !Number.isNaN(Number(form.discountedPrice)) &&
                !Number.isNaN(Number(form.price)) &&
                Number(form.discountedPrice) > 0 &&
                Number(form.discountedPrice) < Number(form.price) && (
                  <p className="mt-1.5 text-[11px] text-muted">
                    Customers will see{" "}
                    <span className="font-semibold text-danger">
                      Rs {(Number(form.price) - Number(form.discountedPrice)).toLocaleString()} OFF
                    </span>{" "}
                    &middot;{" "}
                    <span className="font-semibold text-danger">
                      {Math.round(
                        ((Number(form.price) - Number(form.discountedPrice)) / Number(form.price)) * 100
                      )}
                      % OFF
                    </span>{" "}
                    — calculated automatically, you only set the price above.
                  </p>
                )}
            </div>

            <TextField
              label="Internet Data (GB, optional)"
              type="number"
              value={form.internetGb}
              onChange={(e) => setForm((f) => f && { ...f, internetGb: e.target.value })}
            />
            <div className="grid grid-cols-2 gap-3">
              <TextField
                label="On-Net Minutes (optional)"
                type="number"
                value={form.onNetMinutes}
                onChange={(e) => setForm((f) => f && { ...f, onNetMinutes: e.target.value })}
              />
              <TextField
                label="Off-Net Minutes (optional)"
                type="number"
                value={form.offNetMinutes}
                onChange={(e) => setForm((f) => f && { ...f, offNetMinutes: e.target.value })}
              />
            </div>
            <TextField
              label="All-Net Minutes (optional, for call-only bundles)"
              type="number"
              value={form.allNetMinutes}
              onChange={(e) => setForm((f) => f && { ...f, allNetMinutes: e.target.value })}
            />
            <TextField
              label="SMS (optional)"
              type="number"
              value={form.sms}
              onChange={(e) => setForm((f) => f && { ...f, sms: e.target.value })}
            />
            <TextField
              label="Tagline (optional)"
              value={form.tagline}
              onChange={(e) => setForm((f) => f && { ...f, tagline: e.target.value })}
            />

            {formError && (
              <div className="flex items-start gap-2 rounded-xl bg-danger/10 px-3.5 py-3 text-sm text-danger">
                <AlertCircle size={16} className="mt-0.5 shrink-0" /> {formError}
              </div>
            )}
          </div>
        )}
      </Drawer>
    </div>
  );
}
