"use client";

import { useState } from "react";
import { useRouter } from "next/navigation";
import { useTranslations } from "next-intl";
import { Card, CardHeader } from "@/components/ui/card";
import type { PlatformPricing, SkillPricing } from "@/types";

interface CatalogEntry {
  id: string;
  name: string;
  category: string;
}

interface Props {
  initialPricing: PlatformPricing;
  initialSkillPricing: SkillPricing[];
  catalog: CatalogEntry[];
}

/**
 * Two-card layout:
 *   1. Platform pricing form (4 inputs, save = PUT to /pricing).
 *   2. Skill pricing table — list of priced skills, "Add skill"
 *      picker below.
 *
 * No optimistic updates — every save round-trips and we
 * router.refresh() afterwards so the server-side render stays
 * the source of truth.
 */
export function PricingEditor({
  initialPricing,
  initialSkillPricing,
  catalog,
}: Props) {
  const t = useTranslations("adminBilling");
  const tPackages = useTranslations("packages");
  const router = useRouter();

  // -- Platform pricing form ----------------------------------------------
  const [monthly, setMonthly] = useState(
    String(initialPricing.tenantMonthlyFeeChf)
  );
  const [setup, setSetup] = useState(String(initialPricing.tenantSetupFeeChf));
  const [threema, setThreema] = useState(
    String(initialPricing.threemaMessageChf)
  );
  const [vat, setVat] = useState(String(initialPricing.vatRateChli));
  const [savingPricing, setSavingPricing] = useState(false);
  const [pricingError, setPricingError] = useState("");
  const [pricingSaved, setPricingSaved] = useState(false);

  const savePricing = async (e: React.FormEvent) => {
    e.preventDefault();
    setSavingPricing(true);
    setPricingError("");
    setPricingSaved(false);
    try {
      const res = await fetch("/api/admin/billing/pricing", {
        method: "PUT",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          tenantMonthlyFeeChf: Number(monthly),
          tenantSetupFeeChf: Number(setup),
          threemaMessageChf: Number(threema),
          vatRateChli: Number(vat),
        }),
      });
      if (!res.ok) {
        const j = await res.json().catch(() => ({}));
        throw new Error(j.error || `HTTP ${res.status}`);
      }
      setPricingSaved(true);
      router.refresh();
    } catch (e: any) {
      setPricingError(e.message);
    } finally {
      setSavingPricing(false);
    }
  };

  // -- Package pricing ----------------------------------------------------
  // Server is authoritative — we don't keep an editable local copy of the
  // table; instead each action posts to the API and we router.refresh().
  //
  // Naming carry-over: the underlying DB table is `skill_pricing` and the
  // column is `skill_id`, dating from when only skills were priced. The
  // model now applies to any PackageDef in the catalog regardless of
  // category — core, channel, or skill. The state variable names below
  // (newSkill*, addingSkill, etc.) retain the legacy "skill" prefix
  // because renaming the entire surface for purely cosmetic reasons
  // would create churn for no functional gain. Treat "skill" here as
  // shorthand for "priced package".
  const [newSkillId, setNewSkillId] = useState(catalog[0]?.id ?? "");
  const [newSkillPrice, setNewSkillPrice] = useState("0.10");
  const [newSkillSetupFee, setNewSkillSetupFee] = useState("0");
  const [addingSkill, setAddingSkill] = useState(false);
  const [skillError, setSkillError] = useState("");

  // Core upsert — used by both the "add new skill" form and the inline
  // editors on existing rows. Kept event-free so callers can invoke it
  // without synthesizing a fake form event. Both `dailyPriceChf` and
  // `setupFeeChf` are written together because the API does a full
  // upsert; partial updates would silently zero the other field.
  const upsertSkillPrice = async (
    skillId: string,
    dailyPriceChf: number,
    setupFeeChf: number
  ) => {
    setAddingSkill(true);
    setSkillError("");
    try {
      const res = await fetch("/api/admin/billing/skill-pricing", {
        method: "PUT",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ skillId, dailyPriceChf, setupFeeChf }),
      });
      if (!res.ok) {
        const j = await res.json().catch(() => ({}));
        throw new Error(j.error || `HTTP ${res.status}`);
      }
      router.refresh();
    } catch (e: any) {
      setSkillError(e.message);
    } finally {
      setAddingSkill(false);
    }
  };

  const onAddNewSkill = (e: React.FormEvent) => {
    e.preventDefault();
    if (!newSkillId) return;
    void upsertSkillPrice(
      newSkillId,
      Number(newSkillPrice),
      Number(newSkillSetupFee)
    );
  };

  const deleteSkill = async (skillId: string) => {
    if (!confirm(t("confirmDeleteSkillPrice", { skill: skillId }))) return;
    setSkillError("");
    try {
      const res = await fetch(
        `/api/admin/billing/skill-pricing/${encodeURIComponent(skillId)}`,
        { method: "DELETE" }
      );
      if (!res.ok) {
        const j = await res.json().catch(() => ({}));
        throw new Error(j.error || `HTTP ${res.status}`);
      }
      router.refresh();
    } catch (e: any) {
      setSkillError(e.message);
    }
  };

  // Pricing applies to any catalog entry regardless of category. Grouped
  // dropdown sorts options by category for visual scanning — core,
  // channel, and skill in a single picker.
  const skillCatalogOptions = [...catalog].sort((a, b) => {
    const order = { core: 0, channel: 1, skill: 2 } as Record<string, number>;
    const ca = order[a.category] ?? 99;
    const cb = order[b.category] ?? 99;
    if (ca !== cb) return ca - cb;
    return a.name.localeCompare(b.name);
  });
  const catalogIndex = new Map(catalog.map((c) => [c.id, c]));
  const pricedIds = new Set(initialSkillPricing.map((s) => s.skillId));

  return (
    <div className="space-y-6">
      <Card>
        <CardHeader>{t("platformPricingTitle")}</CardHeader>
        <form onSubmit={savePricing} className="space-y-4">
          <div className="grid grid-cols-2 gap-4">
            <label className="block">
              <span className="text-sm text-text-secondary">
                {t("monthlyFeeLabel")} (CHF)
              </span>
              <input
                type="number"
                step="0.01"
                min="0"
                value={monthly}
                onChange={(e) => setMonthly(e.target.value)}
                className="mt-1 w-full px-3 py-2 rounded-md border border-border bg-surface-2 text-sm"
                required
              />
            </label>
            <label className="block">
              <span className="text-sm text-text-secondary">
                {t("setupFeeLabel")} (CHF)
              </span>
              <input
                type="number"
                step="0.01"
                min="0"
                value={setup}
                onChange={(e) => setSetup(e.target.value)}
                className="mt-1 w-full px-3 py-2 rounded-md border border-border bg-surface-2 text-sm"
                required
              />
            </label>
            <label className="block">
              <span className="text-sm text-text-secondary">
                {t("threemaMessageLabel")} (CHF)
              </span>
              <input
                type="number"
                step="0.0001"
                min="0"
                value={threema}
                onChange={(e) => setThreema(e.target.value)}
                className="mt-1 w-full px-3 py-2 rounded-md border border-border bg-surface-2 text-sm"
                required
              />
            </label>
            <label className="block">
              <span className="text-sm text-text-secondary">
                {t("vatRateLabel")} (%)
              </span>
              <input
                type="number"
                step="0.01"
                min="0"
                max="100"
                value={vat}
                onChange={(e) => setVat(e.target.value)}
                className="mt-1 w-full px-3 py-2 rounded-md border border-border bg-surface-2 text-sm"
                required
              />
            </label>
          </div>
          <div className="flex items-center gap-3">
            <button
              type="submit"
              disabled={savingPricing}
              className="px-4 py-2 rounded-md bg-accent text-white text-sm disabled:opacity-50"
            >
              {savingPricing ? t("saving") : t("save")}
            </button>
            {pricingSaved && (
              <span className="text-sm text-success">{t("savedOk")}</span>
            )}
            {pricingError && (
              <span className="text-sm text-error">{pricingError}</span>
            )}
          </div>
        </form>
      </Card>

      <Card>
        <CardHeader>{t("skillPricingTitle")}</CardHeader>
        <p className="text-sm text-text-muted mb-4">{t("skillPricingDesc")}</p>

        {initialSkillPricing.length > 0 ? (
          <table className="w-full text-sm mb-6">
            <thead className="text-xs text-text-muted text-left">
              <tr>
                <th className="pb-2">{t("skillCol")}</th>
                <th className="pb-2 text-right">{t("dailyPriceCol")}</th>
                <th className="pb-2 text-right">{t("setupFeeCol")}</th>
                <th className="pb-2 text-right">{t("actionsCol")}</th>
              </tr>
            </thead>
            <tbody>
              {initialSkillPricing.map((sp) => {
                const entry = catalogIndex.get(sp.skillId);
                return (
                  <tr
                    key={sp.skillId}
                    className="border-t border-border align-top"
                  >
                    <td className="py-2">
                      <div className="font-mono text-xs">{sp.skillId}</div>
                      {entry && (
                        <div className="text-xs text-text-muted flex items-center gap-2">
                          <span>{entry.name}</span>
                          <span className="text-[10px] uppercase tracking-wider bg-surface-3 px-1.5 py-0.5 rounded">
                            {entry.category}
                          </span>
                        </div>
                      )}
                    </td>
                    <td className="py-2 text-right">
                      {/* Inline edits write daily + setup together (full
                          upsert on the API side). The other field is
                          held constant from the snapshot here. */}
                      <InlinePriceEditor
                        skillId={sp.skillId}
                        initialPrice={sp.dailyPriceChf}
                        decimals={4}
                        onSave={(price) =>
                          upsertSkillPrice(sp.skillId, price, sp.setupFeeChf)
                        }
                      />
                    </td>
                    <td className="py-2 text-right">
                      <InlinePriceEditor
                        skillId={`${sp.skillId}-setup`}
                        initialPrice={sp.setupFeeChf}
                        decimals={2}
                        onSave={(fee) =>
                          upsertSkillPrice(sp.skillId, sp.dailyPriceChf, fee)
                        }
                      />
                    </td>
                    <td className="py-2 text-right">
                      <button
                        onClick={() => deleteSkill(sp.skillId)}
                        className="text-xs text-error hover:underline"
                      >
                        {t("remove")}
                      </button>
                    </td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        ) : (
          <p className="text-sm text-text-muted italic mb-4">{t("noSkillsPriced")}</p>
        )}

        <form onSubmit={onAddNewSkill} className="flex items-end gap-3">
          <label className="flex-grow">
            <span className="text-xs text-text-muted">{t("addSkillLabel")}</span>
            <select
              value={newSkillId}
              onChange={(e) => setNewSkillId(e.target.value)}
              className="mt-1 w-full px-3 py-2 rounded-md border border-border bg-surface-2 text-sm"
            >
              {(() => {
                // Group available options by category for the picker.
                // Already-priced packages are filtered out (admin
                // edits those inline above).
                const available = skillCatalogOptions.filter(
                  (c) => !pricedIds.has(c.id)
                );
                const byCat = new Map<string, typeof available>();
                for (const c of available) {
                  if (!byCat.has(c.category)) byCat.set(c.category, []);
                  byCat.get(c.category)!.push(c);
                }
                // Labels for the optgroups. Reuse the existing
                // packages.categories.* scope which already has
                // translations in all four locales.
                const labels: Record<string, string> = {
                  core: tPackages("categories.core"),
                  channel: tPackages("categories.channels"),
                  skill: tPackages("categories.skills"),
                };
                const order: Array<"core" | "channel" | "skill"> = [
                  "core",
                  "channel",
                  "skill",
                ];
                return order.map((cat) => {
                  const items = byCat.get(cat);
                  if (!items || items.length === 0) return null;
                  return (
                    <optgroup key={cat} label={labels[cat] ?? cat}>
                      {items.map((c) => (
                        <option key={c.id} value={c.id}>
                          {c.name} ({c.id})
                        </option>
                      ))}
                    </optgroup>
                  );
                });
              })()}
            </select>
          </label>
          <label className="w-28">
            <span className="text-xs text-text-muted">
              {t("dailyPriceLabel")}
            </span>
            <input
              type="number"
              step="0.01"
              min="0"
              value={newSkillPrice}
              onChange={(e) => setNewSkillPrice(e.target.value)}
              className="mt-1 w-full px-3 py-2 rounded-md border border-border bg-surface-2 text-sm"
            />
          </label>
          <label className="w-28">
            <span className="text-xs text-text-muted">
              {t("skillSetupFeeLabel")}
            </span>
            <input
              type="number"
              step="0.01"
              min="0"
              value={newSkillSetupFee}
              onChange={(e) => setNewSkillSetupFee(e.target.value)}
              className="mt-1 w-full px-3 py-2 rounded-md border border-border bg-surface-2 text-sm"
            />
          </label>
          <button
            type="submit"
            disabled={addingSkill || !newSkillId}
            className="px-4 py-2 rounded-md bg-accent text-white text-sm disabled:opacity-50"
          >
            {addingSkill ? t("saving") : t("add")}
          </button>
        </form>
        {skillError && (
          <p className="text-sm text-error mt-2">{skillError}</p>
        )}
      </Card>
    </div>
  );
}

/**
 * Tiny inline editor for a single numeric price/fee. Mounts in
 * "view" mode showing the current value as a clickable badge;
 * clicking turns it into an input + save/cancel buttons.
 *
 * `decimals` controls the display precision in view mode AND the
 * step granularity of the input (daily prices use 4dp, setup fees
 * use 2dp).
 */
function InlinePriceEditor({
  skillId,
  initialPrice,
  decimals = 2,
  onSave,
}: {
  skillId: string;
  initialPrice: number;
  decimals?: number;
  onSave: (price: number) => Promise<void> | void;
}) {
  const t = useTranslations("adminBilling");
  const [editing, setEditing] = useState(false);
  const [value, setValue] = useState(String(initialPrice));
  const [busy, setBusy] = useState(false);
  const step = decimals === 4 ? "0.0001" : "0.01";

  if (!editing) {
    return (
      <button
        onClick={() => setEditing(true)}
        className="text-sm font-mono hover:underline"
        title={t("clickToEdit")}
      >
        CHF {initialPrice.toFixed(decimals)}
      </button>
    );
  }
  return (
    <span className="inline-flex items-center gap-1">
      <input
        type="number"
        step={step}
        min="0"
        value={value}
        onChange={(e) => setValue(e.target.value)}
        className="w-20 px-2 py-1 text-sm border border-border bg-surface-2 rounded"
        autoFocus
      />
      <button
        onClick={async () => {
          setBusy(true);
          try {
            await onSave(Number(value));
            setEditing(false);
          } finally {
            setBusy(false);
          }
        }}
        disabled={busy}
        className="text-xs px-2 py-1 bg-accent text-white rounded"
      >
        {busy ? "…" : "✓"}
      </button>
      <button
        onClick={() => {
          setValue(String(initialPrice));
          setEditing(false);
        }}
        className="text-xs px-2 py-1 border border-border rounded"
      >
        ✕
      </button>
    </span>
  );
}
