import { useState, useEffect } from "react";
import { useLocation } from "wouter";
import { useQuery } from "@tanstack/react-query";
import { useCart } from "../hooks/use-cart";
import { apiRequest } from "../lib/queryClient";
import { toast } from "../hooks/use-toast";
import { Shield, Lock, CreditCard } from "lucide-react";

declare global {
  interface Window {
    Accept: {
      dispatchData: (secureData: any, callback: (response: any) => void) => void;
    };
  }
}

interface StoreConfig {
  authorizeNetClientKey: string;
  authorizeNetApiLoginId: string;
  authorizeNetSandbox: boolean;
  stripePublishableKey?: string;
  stripeEnabled: boolean;
}

interface Address {
  firstName: string;
  lastName: string;
  address1: string;
  address2?: string;
  city: string;
  state: string;
  zip: string;
  country: string;
}

const US_STATES = [
  "AL","AK","AZ","AR","CA","CO","CT","DE","FL","GA","HI","ID","IL","IN","IA",
  "KS","KY","LA","ME","MD","MA","MI","MN","MS","MO","MT","NE","NV","NH","NJ",
  "NM","NY","NC","ND","OH","OK","OR","PA","RI","SC","SD","TN","TX","UT","VT",
  "VA","WA","WV","WI","WY","DC",
];

function AddressForm({ prefix, value, onChange }: {
  prefix: string;
  value: Address;
  onChange: (v: Address) => void;
}) {
  const field = (name: keyof Address, label: string, required = true, type = "text") => (
    <div>
      <label className="block text-xs font-medium text-muted-foreground mb-1">{label}</label>
      <input
        type={type}
        value={value[name] || ""}
        onChange={(e) => onChange({ ...value, [name]: e.target.value })}
        required={required}
        className="w-full px-3 py-2 border border-border rounded-md text-sm bg-background focus:outline-none focus:ring-2 focus:ring-primary/30"
        data-testid={`input-${prefix}-${name}`}
      />
    </div>
  );

  return (
    <div className="grid grid-cols-2 gap-3">
      {field("firstName", "First name")}
      {field("lastName", "Last name")}
      <div className="col-span-2">{field("address1", "Address")}</div>
      <div className="col-span-2">{field("address2", "Apt, suite, etc.", false)}</div>
      {field("city", "City")}
      <div>
        <label className="block text-xs font-medium text-muted-foreground mb-1">State</label>
        <select
          value={value.state}
          onChange={(e) => onChange({ ...value, state: e.target.value })}
          required
          className="w-full px-3 py-2 border border-border rounded-md text-sm bg-background focus:outline-none focus:ring-2 focus:ring-primary/30"
          data-testid={`input-${prefix}-state`}
        >
          <option value="">State</option>
          {US_STATES.map((s) => <option key={s} value={s}>{s}</option>)}
        </select>
      </div>
      {field("zip", "ZIP code")}
    </div>
  );
}

export default function CheckoutPage() {
  const { items, subtotal, isLoading: cartLoading } = useCart();
  const [, setLocation] = useLocation();
  const [step, setStep] = useState<"info" | "payment">("info");
  const [submitting, setSubmitting] = useState(false);
  const [processor, setProcessor] = useState<"authorizenet" | "stripe">("authorizenet");
  const [email, setEmail] = useState("");
  const [shipping, setShipping] = useState<Address>({ firstName: "", lastName: "", address1: "", city: "", state: "", zip: "", country: "US" });
  const [sameAsBilling, setSameAsBilling] = useState(true);
  const [billing, setBilling] = useState<Address>({ firstName: "", lastName: "", address1: "", city: "", state: "", zip: "", country: "US" });
  const [cardNumber, setCardNumber] = useState("");
  const [expiry, setExpiry] = useState("");
  const [cvv, setCvv] = useState("");
  const [discountCode, setDiscountCode] = useState("");
  const [discountApplied, setDiscountApplied] = useState<{ code: string; type: string; value: string } | null>(null);
  const [applyingDiscount, setApplyingDiscount] = useState(false);

  const { data: config } = useQuery<StoreConfig>({
    queryKey: ["/api/config"],
    queryFn: async () => { const r = await fetch("/api/config"); return r.json(); },
  });

  useEffect(() => {
    if (config && !config.stripeEnabled) setProcessor("authorizenet");
  }, [config]);

  useEffect(() => {
    if (config?.authorizeNetSandbox === false) {
      const existing = document.getElementById("anet-js");
      if (!existing) {
        const script = document.createElement("script");
        script.id = "anet-js";
        script.src = "https://js.authorize.net/v1/Accept.js";
        script.async = true;
        document.head.appendChild(script);
      }
    } else if (config) {
      const existing = document.getElementById("anet-js");
      if (!existing) {
        const script = document.createElement("script");
        script.id = "anet-js";
        script.src = "https://jstest.authorize.net/v1/Accept.js";
        script.async = true;
        document.head.appendChild(script);
      }
    }
  }, [config]);

  if (cartLoading) return <div className="max-w-3xl mx-auto px-4 py-16 text-center text-muted-foreground">Loading...</div>;
  if (items.length === 0) {
    setLocation("/");
    return null;
  }

  const calcDiscount = () => {
    if (!discountApplied) return 0;
    if (discountApplied.type === "percentage") return subtotal * (parseFloat(discountApplied.value) / 100);
    return Math.min(parseFloat(discountApplied.value), subtotal);
  };
  const discount = calcDiscount();
  const total = Math.max(0, subtotal - discount);

  const handleApplyDiscount = async () => {
    if (!discountCode.trim()) return;
    setApplyingDiscount(true);
    try {
      const res = await apiRequest("POST", "/api/cart/discount", { code: discountCode.trim() });
      const data = await res.json();
      setDiscountApplied(data.discount);
      toast({ title: "Discount applied!", description: `${data.discount.code} is active.` });
    } catch (err: any) {
      toast({ title: "Invalid code", description: err.message, variant: "destructive" });
    } finally {
      setApplyingDiscount(false);
    }
  };

  const handleAuthorizeNetSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    if (!config?.authorizeNetApiLoginId || !config?.authorizeNetClientKey) {
      toast({ title: "Payment not configured", variant: "destructive" });
      return;
    }
    setSubmitting(true);

    const secureData = {
      authData: { clientKey: config.authorizeNetClientKey, apiLoginID: config.authorizeNetApiLoginId },
      cardData: {
        cardNumber: cardNumber.replace(/\s/g, ""),
        month: expiry.split("/")[0]?.trim(),
        year: `20${expiry.split("/")[1]?.trim()}`,
        cardCode: cvv,
      },
    };

    window.Accept.dispatchData(secureData, async (response) => {
      if (response.messages.resultCode === "Error") {
        toast({ title: "Card error", description: response.messages.message[0]?.text, variant: "destructive" });
        setSubmitting(false);
        return;
      }

      try {
        const res = await apiRequest("POST", "/api/checkout/authorizenet", {
          dataDescriptor: response.opaqueData.dataDescriptor,
          dataValue: response.opaqueData.dataValue,
          email,
          firstName: shipping.firstName,
          lastName: shipping.lastName,
          shippingAddress: shipping,
          billingAddress: sameAsBilling ? shipping : billing,
        });
        const data = await res.json();
        setLocation(`/order-confirmation?order=${data.orderNumber}`);
      } catch (err: any) {
        toast({ title: "Payment failed", description: err.message, variant: "destructive" });
        setSubmitting(false);
      }
    });
  };

  return (
    <div className="max-w-5xl mx-auto px-4 py-10" data-testid="checkout-page">
      <h1 className="text-2xl font-bold mb-8">Checkout</h1>

      <div className="grid md:grid-cols-5 gap-8">
        <div className="md:col-span-3 space-y-6">
          {step === "info" && (
            <form onSubmit={(e) => { e.preventDefault(); setStep("payment"); }} className="space-y-6">
              <section className="border border-border rounded-xl p-5">
                <h2 className="font-semibold mb-4">Contact</h2>
                <div>
                  <label className="block text-xs font-medium text-muted-foreground mb-1">Email address</label>
                  <input
                    type="email" value={email} onChange={(e) => setEmail(e.target.value)} required
                    className="w-full px-3 py-2 border border-border rounded-md text-sm bg-background focus:outline-none focus:ring-2 focus:ring-primary/30"
                    data-testid="input-email"
                  />
                </div>
              </section>

              <section className="border border-border rounded-xl p-5">
                <h2 className="font-semibold mb-4">Shipping address</h2>
                <AddressForm prefix="shipping" value={shipping} onChange={setShipping} />
              </section>

              <section className="border border-border rounded-xl p-5">
                <h2 className="font-semibold mb-4">Discount code</h2>
                <div className="flex gap-2">
                  <input
                    value={discountCode}
                    onChange={(e) => setDiscountCode(e.target.value)}
                    placeholder="Enter code"
                    className="flex-1 px-3 py-2 border border-border rounded-md text-sm bg-background focus:outline-none focus:ring-2 focus:ring-primary/30"
                    data-testid="input-discount-code"
                  />
                  <button type="button" onClick={handleApplyDiscount} disabled={applyingDiscount || !discountCode.trim()}
                    className="px-4 py-2 border border-border rounded-md text-sm hover:bg-muted transition-colors disabled:opacity-50">
                    Apply
                  </button>
                </div>
                {discountApplied && (
                  <p className="text-sm text-green-600 mt-2">✓ {discountApplied.code} applied — {discountApplied.type === "percentage" ? `${discountApplied.value}% off` : `$${discountApplied.value} off`}</p>
                )}
              </section>

              <button type="submit" className="w-full bg-primary text-primary-foreground py-3 rounded-md font-semibold hover:bg-primary/90 transition-colors" data-testid="button-continue-to-payment">
                Continue to payment
              </button>
            </form>
          )}

          {step === "payment" && (
            <form onSubmit={handleAuthorizeNetSubmit} className="space-y-6">
              {config?.stripeEnabled && (
                <section className="border border-border rounded-xl p-5">
                  <h2 className="font-semibold mb-4">Payment method</h2>
                  <div className="flex gap-3">
                    <button type="button" onClick={() => setProcessor("authorizenet")}
                      className={`flex-1 py-2 px-4 border rounded-md text-sm font-medium transition-colors ${processor === "authorizenet" ? "border-primary bg-primary/5" : "border-border hover:border-primary/50"}`}>
                      Credit / Debit Card
                    </button>
                    <button type="button" onClick={() => setProcessor("stripe")}
                      className={`flex-1 py-2 px-4 border rounded-md text-sm font-medium transition-colors ${processor === "stripe" ? "border-primary bg-primary/5" : "border-border hover:border-primary/50"}`}>
                      Stripe
                    </button>
                  </div>
                </section>
              )}

              {processor === "authorizenet" && (
                <section className="border border-border rounded-xl p-5">
                  <div className="flex items-center gap-2 mb-4">
                    <CreditCard size={18} />
                    <h2 className="font-semibold">Card details</h2>
                    <span className="ml-auto flex items-center gap-1 text-xs text-muted-foreground"><Lock size={11} /> Secure</span>
                  </div>
                  <div className="space-y-3">
                    <div>
                      <label className="block text-xs font-medium text-muted-foreground mb-1">Card number</label>
                      <input
                        value={cardNumber} onChange={(e) => setCardNumber(e.target.value.replace(/\D/g, "").replace(/(.{4})/g, "$1 ").trim())}
                        placeholder="1234 5678 9012 3456" maxLength={19} required
                        className="w-full px-3 py-2 border border-border rounded-md text-sm bg-background font-mono focus:outline-none focus:ring-2 focus:ring-primary/30"
                        data-testid="input-card-number"
                      />
                    </div>
                    <div className="grid grid-cols-2 gap-3">
                      <div>
                        <label className="block text-xs font-medium text-muted-foreground mb-1">Expiry (MM / YY)</label>
                        <input
                          value={expiry} onChange={(e) => { let v = e.target.value.replace(/\D/g, ""); if (v.length >= 3) v = v.slice(0, 2) + " / " + v.slice(2, 4); setExpiry(v); }}
                          placeholder="MM / YY" maxLength={7} required
                          className="w-full px-3 py-2 border border-border rounded-md text-sm bg-background font-mono focus:outline-none focus:ring-2 focus:ring-primary/30"
                          data-testid="input-expiry"
                        />
                      </div>
                      <div>
                        <label className="block text-xs font-medium text-muted-foreground mb-1">Security code</label>
                        <input
                          value={cvv} onChange={(e) => setCvv(e.target.value.replace(/\D/g, "").slice(0, 4))}
                          placeholder="CVV" maxLength={4} required
                          className="w-full px-3 py-2 border border-border rounded-md text-sm bg-background font-mono focus:outline-none focus:ring-2 focus:ring-primary/30"
                          data-testid="input-cvv"
                        />
                      </div>
                    </div>
                  </div>
                </section>
              )}

              <section className="border border-border rounded-xl p-5">
                <div className="flex items-center gap-2 mb-4">
                  <h2 className="font-semibold">Billing address</h2>
                  <label className="ml-auto flex items-center gap-2 text-sm cursor-pointer">
                    <input type="checkbox" checked={sameAsBilling} onChange={(e) => setSameAsBilling(e.target.checked)} />
                    Same as shipping
                  </label>
                </div>
                {!sameAsBilling && <AddressForm prefix="billing" value={billing} onChange={setBilling} />}
              </section>

              <div className="flex gap-3">
                <button type="button" onClick={() => setStep("info")} className="px-4 py-3 border border-border rounded-md text-sm hover:bg-muted transition-colors">
                  ← Back
                </button>
                <button type="submit" disabled={submitting}
                  className="flex-1 bg-primary text-primary-foreground py-3 rounded-md font-semibold hover:bg-primary/90 transition-colors disabled:opacity-60 flex items-center justify-center gap-2"
                  data-testid="button-place-order">
                  <Shield size={16} />
                  {submitting ? "Processing..." : `Pay $${total.toFixed(2)}`}
                </button>
              </div>
            </form>
          )}
        </div>

        <div className="md:col-span-2">
          <div className="bg-muted/30 rounded-xl border border-border p-5 sticky top-24">
            <h3 className="font-semibold mb-4">Order summary</h3>
            <div className="space-y-3 mb-4">
              {items.map((item) => (
                <div key={item.id} className="flex gap-3" data-testid={`order-item-${item.id}`}>
                  <div className="relative flex-shrink-0">
                    <div className="w-12 h-12 bg-muted rounded-md overflow-hidden border border-border">
                      {item.imageUrl && <img src={item.imageUrl} alt={item.title} className="w-full h-full object-cover" />}
                    </div>
                    <span className="absolute -top-1.5 -right-1.5 bg-primary text-primary-foreground text-xs rounded-full w-4 h-4 flex items-center justify-center">{item.quantity}</span>
                  </div>
                  <div className="flex-1 min-w-0">
                    <p className="text-sm font-medium truncate">{item.title}</p>
                    {item.variantTitle && item.variantTitle !== "Default Title" && <p className="text-xs text-muted-foreground">{item.variantTitle}</p>}
                  </div>
                  <span className="text-sm font-medium">${(parseFloat(item.price) * item.quantity).toFixed(2)}</span>
                </div>
              ))}
            </div>
            <div className="border-t border-border pt-4 space-y-2">
              <div className="flex justify-between text-sm">
                <span className="text-muted-foreground">Subtotal</span>
                <span>${subtotal.toFixed(2)}</span>
              </div>
              {discount > 0 && (
                <div className="flex justify-between text-sm text-green-600">
                  <span>Discount</span>
                  <span>-${discount.toFixed(2)}</span>
                </div>
              )}
              <div className="flex justify-between text-sm">
                <span className="text-muted-foreground">Shipping</span>
                <span>Calculated at next step</span>
              </div>
              <div className="flex justify-between font-semibold pt-2 border-t border-border">
                <span>Total</span>
                <span data-testid="checkout-total">${total.toFixed(2)}</span>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}
