import { ChangeEvent, ReactNode, useEffect, useMemo, useRef, useState } from "react";
import { Head } from "@inertiajs/react";
import { useQuery, useQueryClient } from "@tanstack/react-query";
import AdminLayout from "@/layouts/AdminLayout";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { toast } from "sonner";
import { Loader2, ExternalLink, Star, CreditCard, Upload } from "lucide-react";
import { useAuth } from "@/hooks/useAuth";

const csrfToken = () =>
  (document.querySelector('meta[name="csrf-token"]') as HTMLMetaElement | null)?.content ?? "";

async function api(path: string, method = "GET", body?: unknown) {
  const res = await fetch(path, {
    method,
    headers: {
      "Content-Type": "application/json",
      Accept: "application/json",
      "X-Requested-With": "XMLHttpRequest",
      "X-CSRF-TOKEN": csrfToken(),
    },
    body: body ? JSON.stringify(body) : undefined,
  });
  const ct = res.headers.get("content-type") || "";
  const data = ct.includes("application/json") ? await res.json() : null;
  if (!res.ok) throw new Error(data?.error || `Request failed (${res.status})`);
  return data;
}

interface Branding {
  subdomain: string | null;
  logo_url: string | null;
  primary_color: string | null;
  secondary_color: string | null;
  background_color: string | null;
  font_color: string | null;
  card_color: string | null;
  card_font_color: string | null;
  hero_image_url: string | null;
  tagline: string | null;
  contact_email: string | null;
  contact_phone: string | null;
  contact_address: string | null;
  is_active: boolean;
  stripe_connected: boolean;
}

const TextField = ({ label, value, onChange, placeholder }: {
  label: string; value: string; onChange: (v: string) => void; placeholder?: string;
}) => (
  <div>
    <Label className="text-xs">{label}</Label>
    <Input value={value ?? ""} onChange={(e) => onChange(e.target.value)} placeholder={placeholder} />
  </div>
);

const ColorField = ({ label, value, onChange }: { label: string; value: string; onChange: (v: string) => void }) => (
  <div>
    <Label className="text-xs">{label}</Label>
    <div className="flex gap-2 items-center">
      <input
        type="color"
        value={/^#[0-9a-fA-F]{6}$/.test(value || "") ? value : "#000000"}
        onChange={(e) => onChange(e.target.value)}
        className="h-9 w-12 rounded border border-border bg-transparent"
      />
      <Input value={value ?? ""} onChange={(e) => onChange(e.target.value)} placeholder="#1E40AF" className="flex-1" />
    </div>
  </div>
);

// Uploads a file to the shared admin image endpoint and returns its public URL.
async function uploadImage(file: File): Promise<string> {
  const fd = new FormData();
  fd.append("file", file);
  fd.append("folder", "company-site");
  const res = await fetch("/api/admin/upload/image", {
    method: "POST",
    headers: { Accept: "application/json", "X-Requested-With": "XMLHttpRequest", "X-CSRF-TOKEN": csrfToken() },
    body: fd,
  });
  const data = await res.json().catch(() => null);
  if (!res.ok) throw new Error(data?.error || data?.message || `Upload failed (${res.status})`);
  return data.url as string;
}

// Image picker: preview + click-to-upload, with the URL still editable for
// anyone who'd rather paste a link.
const ImageField = ({ label, value, onChange, hint }: {
  label: string; value: string; onChange: (v: string) => void; hint?: string;
}) => {
  const fileRef = useRef<HTMLInputElement>(null);
  const [uploading, setUploading] = useState(false);

  const onPick = async (e: ChangeEvent<HTMLInputElement>) => {
    const file = e.target.files?.[0];
    e.target.value = ""; // let the same file be re-selected later
    if (!file) return;
    setUploading(true);
    try {
      onChange(await uploadImage(file));
      toast.success("Image uploaded");
    } catch (err: any) {
      toast.error(err.message);
    } finally {
      setUploading(false);
    }
  };

  return (
    <div>
      <Label className="text-xs">{label}</Label>
      <div className="flex items-start gap-3 mt-1">
        <div className="h-16 w-16 shrink-0 rounded border border-border bg-muted/40 overflow-hidden flex items-center justify-center">
          {value ? (
            <img src={value} alt={label} className="h-full w-full object-contain" />
          ) : (
            <span className="text-[10px] text-muted-foreground">No image</span>
          )}
        </div>
        <div className="flex-1 space-y-2 min-w-0">
          <div className="flex gap-2">
            <input ref={fileRef} type="file" accept="image/*" className="hidden" onChange={onPick} />
            <Button type="button" variant="outline" size="sm" onClick={() => fileRef.current?.click()} disabled={uploading}>
              {uploading ? <><Loader2 className="h-3.5 w-3.5 mr-1.5 animate-spin" />Uploading…</> : <><Upload className="h-3.5 w-3.5 mr-1.5" />Upload</>}
            </Button>
            {value && <Button type="button" variant="ghost" size="sm" onClick={() => onChange("")}>Remove</Button>}
          </div>
          <Input value={value ?? ""} onChange={(e) => onChange(e.target.value)} placeholder="or paste an image URL" className="h-8 text-xs" />
        </div>
      </div>
      {hint && <p className="text-[11px] text-muted-foreground mt-1">{hint}</p>}
    </div>
  );
};

const CompanySiteIndex = () => {
  const { companyId, hasRole } = useAuth();
  const isManager = hasRole("company_manager") && !!companyId;
  const base = `/api/company-site/${companyId}`;
  const qc = useQueryClient();

  // Storefronts only exist for training/hybrid companies — the API 403s for
  // customer companies. Check eligibility up front so we never render the tabs
  // (which would otherwise fire a burst of failing /company-site requests).
  const { data: companyType, isLoading: typeLoading } = useQuery<{ company_type: string } | null>({
    queryKey: ["company-site-eligibility", companyId],
    enabled: isManager,
    retry: false,
    queryFn: async () => {
      const res = await fetch(`/api/companies/${companyId}/type`);
      if (!res.ok) return null;
      return res.json();
    },
  });
  const eligible = companyType?.company_type === "training_company" || companyType?.company_type === "hybrid";

  if (!isManager) {
    return (
      <>
        <Head title="Storefront Settings" />
        <div className="text-center py-12">
          <h1 className="text-2xl font-bold text-foreground mb-3">Storefront Settings</h1>
          <p className="text-muted-foreground">This area is only available to company managers of a training or hybrid company.</p>
        </div>
      </>
    );
  }

  if (typeLoading) {
    return (
      <>
        <Head title="Storefront Settings" />
        <div className="py-12 flex justify-center"><Loader2 className="h-6 w-6 animate-spin text-primary" /></div>
      </>
    );
  }

  if (!eligible) {
    return (
      <>
        <Head title="Storefront Settings" />
        <div className="text-center py-12 max-w-lg mx-auto">
          <h1 className="text-2xl font-bold text-foreground mb-3">Storefront Settings</h1>
          <p className="text-muted-foreground">
            Your company isn't set up as a training provider, so it doesn't have a storefront. If you'd like to list and sell your own courses, contact support to enable a training or hybrid account.
          </p>
        </div>
      </>
    );
  }

  return (
    <>
      <Head title="Storefront Settings" />
      <div className="w-full">
        <h1 className="text-2xl font-bold text-foreground mb-1">Storefront Settings</h1>
        <p className="text-muted-foreground mb-8 text-sm">Brand your subdomain site, choose courses, connect Stripe and go live.</p>

        <Tabs defaultValue="branding">
          <TabsList className="mb-6 flex-wrap h-auto">
            <TabsTrigger value="branding">Branding</TabsTrigger>
            <TabsTrigger value="featured">Featured</TabsTrigger>
            <TabsTrigger value="payments">Payments &amp; Publish</TabsTrigger>
          </TabsList>

          <TabsContent value="branding"><BrandingTab base={base} onSaved={() => qc.invalidateQueries({ queryKey: ["site-branding", base] })} /></TabsContent>
          <TabsContent value="featured"><FeaturedTab base={base} /></TabsContent>
          <TabsContent value="payments"><PaymentsTab base={base} /></TabsContent>
        </Tabs>
      </div>
    </>
  );
};

/* ── Branding ── */
const BrandingTab = ({ base, onSaved }: { base: string; onSaved: () => void }) => {
  const { data, isLoading } = useQuery<Branding>({
    queryKey: ["site-branding", base],
    queryFn: () => api(`${base}/branding`),
    retry: false,
  });
  const [form, setForm] = useState<Partial<Branding>>({});
  const [saving, setSaving] = useState(false);
  useEffect(() => { if (data) setForm(data); }, [data]);

  const set = (k: keyof Branding, v: string) => setForm((p) => ({ ...p, [k]: v }));

  const save = async () => {
    setSaving(true);
    try {
      await api(`${base}/branding`, "PATCH", {
        subdomain: form.subdomain || null,
        logo_url: form.logo_url || null,
        primary_color: form.primary_color || null,
        secondary_color: form.secondary_color || null,
        background_color: form.background_color || null,
        font_color: form.font_color || null,
        card_color: form.card_color || null,
        card_font_color: form.card_font_color || null,
        hero_image_url: form.hero_image_url || null,
        tagline: form.tagline || null,
        contact_email: form.contact_email || null,
        contact_phone: form.contact_phone || null,
        contact_address: form.contact_address || null,
      });
      toast.success("Branding saved");
      onSaved();
    } catch (e: any) {
      toast.error(e.message);
    } finally {
      setSaving(false);
    }
  };

  if (isLoading) return <Loader2 className="h-6 w-6 animate-spin text-primary" />;

  return (
    <div className="space-y-5">
      <div className="grid sm:grid-cols-2 gap-4">
        <TextField label="Subdomain" value={form.subdomain ?? ""} onChange={(v) => set("subdomain", v)} placeholder="acme" />
        <TextField label="Tagline" value={form.tagline ?? ""} onChange={(v) => set("tagline", v)} placeholder="Expert-led training" />
      </div>
      <div className="grid sm:grid-cols-2 gap-4">
        <ImageField label="Logo" value={form.logo_url ?? ""} onChange={(v) => set("logo_url", v)} hint="Shown in your storefront header — a PNG/SVG with a transparent background works best." />
        <ImageField label="Hero image" value={form.hero_image_url ?? ""} onChange={(v) => set("hero_image_url", v)} hint="Large banner across the top of your storefront homepage." />
      </div>
      <div className="grid sm:grid-cols-3 gap-4">
        <ColorField label="Primary" value={form.primary_color ?? ""} onChange={(v) => set("primary_color", v)} />
        <ColorField label="Secondary" value={form.secondary_color ?? ""} onChange={(v) => set("secondary_color", v)} />
        <ColorField label="Background" value={form.background_color ?? ""} onChange={(v) => set("background_color", v)} />
        <ColorField label="Font" value={form.font_color ?? ""} onChange={(v) => set("font_color", v)} />
        <ColorField label="Card" value={form.card_color ?? ""} onChange={(v) => set("card_color", v)} />
        <ColorField label="Card font" value={form.card_font_color ?? ""} onChange={(v) => set("card_font_color", v)} />
      </div>
      <div className="grid sm:grid-cols-3 gap-4">
        <TextField label="Contact email" value={form.contact_email ?? ""} onChange={(v) => set("contact_email", v)} />
        <TextField label="Contact phone" value={form.contact_phone ?? ""} onChange={(v) => set("contact_phone", v)} />
        <TextField label="Contact address" value={form.contact_address ?? ""} onChange={(v) => set("contact_address", v)} />
      </div>
      <Button variant="hero" onClick={save} disabled={saving}>
        {saving ? <><Loader2 className="h-4 w-4 animate-spin mr-2" />Saving…</> : "Save branding"}
      </Button>
    </div>
  );
};

/* ── Featured (curate shared catalog) ── */
interface CatalogCourse { id: string; title: string; category: string; price_cents: number; owner_company_id: string | null; }
interface FeaturedRow { id: string; course_id: string; title: string; }
const FeaturedTab = ({ base }: { base: string }) => {
  const qc = useQueryClient();
  const { data: catalog = [] } = useQuery<CatalogCourse[]>({ queryKey: ["site-catalog", base], queryFn: () => api(`${base}/catalog`), retry: false });
  const { data: featured = [] } = useQuery<FeaturedRow[]>({ queryKey: ["site-featured", base], queryFn: () => api(`${base}/featured`), retry: false });
  const featuredIds = useMemo(() => new Set(featured.map((f) => f.course_id)), [featured]);

  const refresh = () => {
    qc.invalidateQueries({ queryKey: ["site-featured", base] });
  };
  const toggle = async (course: CatalogCourse) => {
    try {
      if (featuredIds.has(course.id)) await api(`${base}/featured/${course.id}`, "DELETE");
      else await api(`${base}/featured`, "POST", { course_id: course.id });
      refresh();
    } catch (e: any) { toast.error(e.message); }
  };

  return (
    <div className="space-y-2">
      <p className="text-sm text-muted-foreground mb-3">Choose which shared UTC courses appear on your storefront (your own courses always appear).</p>
      {catalog.map((c) => {
        const on = featuredIds.has(c.id);
        return (
          <div key={c.id} className="flex items-center justify-between bg-card border border-border rounded-lg px-4 py-3">
            <div>
              <div className="font-medium text-sm text-foreground">{c.title}</div>
              <div className="text-xs text-muted-foreground">{c.category} · £{(c.price_cents / 100).toFixed(2)}{c.owner_company_id ? " · your course" : ""}</div>
            </div>
            <Button size="sm" variant={on ? "default" : "outline"} onClick={() => toggle(c)} className="gap-1">
              <Star className={`h-3.5 w-3.5 ${on ? "fill-current" : ""}`} /> {on ? "Featured" : "Feature"}
            </Button>
          </div>
        );
      })}
    </div>
  );
};

/* ── Payments & Publish ── */
const PaymentsTab = ({ base }: { base: string }) => {
  const qc = useQueryClient();
  const { data, isLoading } = useQuery<Branding>({ queryKey: ["site-branding", base], queryFn: () => api(`${base}/branding`), retry: false });
  const { data: stripeCfg } = useQuery<{ publishable_key: string | null; secret_set: boolean }>({
    queryKey: ["site-stripe-config", base], queryFn: () => api(`${base}/stripe-config`), retry: false,
  });
  const [busy, setBusy] = useState(false);
  const [savingKeys, setSavingKeys] = useState(false);
  const [pk, setPk] = useState("");
  const [sk, setSk] = useState("");

  // Prefill the publishable key (it's public); the secret is never sent back.
  useEffect(() => { if (stripeCfg?.publishable_key) setPk(stripeCfg.publishable_key); }, [stripeCfg]);

  const saveKeys = async () => {
    if (!pk.trim() || !sk.trim()) { toast.error("Both the publishable and secret keys are required."); return; }
    setSavingKeys(true);
    try {
      await api(`${base}/stripe-config`, "POST", { stripe_publishable_key: pk.trim(), stripe_secret_key: sk.trim() });
      toast.success("Stripe keys saved");
      setSk("");
      qc.invalidateQueries({ queryKey: ["site-stripe-config", base] });
    } catch (e: any) { toast.error(e.message); } finally { setSavingKeys(false); }
  };

  const togglePublish = async (next: boolean) => {
    setBusy(true);
    try {
      await api(`${base}/publish`, "POST", { is_active: next });
      toast.success(next ? "Your site is live!" : "Your site is now hidden");
      qc.invalidateQueries({ queryKey: ["site-branding", base] });
    } catch (e: any) { toast.error(e.message); } finally { setBusy(false); }
  };

  if (isLoading || !data) return <Loader2 className="h-6 w-6 animate-spin text-primary" />;

  const storefrontUrl = data.subdomain ? `https://${data.subdomain}.${window.location.host.replace(/^[^.]+\./, "")}` : null;
  const configured = !!stripeCfg?.secret_set && !!pk;

  return (
    <div className="space-y-6">
      <div className="bg-card border border-border rounded-lg p-5 space-y-4">
        <div className="flex items-center gap-2"><CreditCard className="h-5 w-5 text-primary" /><h3 className="font-semibold">Stripe payments</h3></div>
        <p className="text-sm text-muted-foreground">
          Add your own Stripe API keys so card payments on your storefront go straight to your Stripe account.
          Find them in your{" "}
          <a href="https://dashboard.stripe.com/apikeys" target="_blank" rel="noreferrer" className="text-primary underline inline-flex items-center gap-0.5">
            Stripe Dashboard → Developers → API keys <ExternalLink className="h-3 w-3" />
          </a>.
        </p>
        <ul className="text-xs text-muted-foreground list-disc pl-5 space-y-1">
          <li><span className="font-medium text-foreground">Publishable key</span> — starts with <code className="text-[11px] bg-muted px-1 rounded">pk_live_</code> (or <code className="text-[11px] bg-muted px-1 rounded">pk_test_</code>). Safe to share.</li>
          <li><span className="font-medium text-foreground">Secret key</span> — starts with <code className="text-[11px] bg-muted px-1 rounded">sk_live_</code> (or <code className="text-[11px] bg-muted px-1 rounded">sk_test_</code>). Keep it private — we store it securely and never display it again.</li>
        </ul>

        <div className="grid sm:grid-cols-2 gap-4">
          <div>
            <Label className="text-xs">Publishable key</Label>
            <Input value={pk} onChange={(e) => setPk(e.target.value)} placeholder="pk_live_…" />
          </div>
          <div>
            <Label className="text-xs">
              Secret key{stripeCfg?.secret_set && <span className="text-green-600"> — saved; enter a new one to replace</span>}
            </Label>
            <Input type="password" value={sk} onChange={(e) => setSk(e.target.value)} placeholder={stripeCfg?.secret_set ? "•••••••• (hidden)" : "sk_live_…"} />
          </div>
        </div>

        <div className="flex items-center gap-3">
          <Button onClick={saveKeys} disabled={savingKeys}>
            {savingKeys ? <><Loader2 className="h-4 w-4 mr-1.5 animate-spin" />Saving…</> : "Save Stripe keys"}
          </Button>
          {configured && <span className="text-sm text-green-600">✓ Stripe is configured — your storefront can take card payments.</span>}
        </div>
      </div>

      <div className="bg-card border border-border rounded-lg p-5 space-y-3">
        <h3 className="font-semibold">Publish</h3>
        {data.is_active ? (
          <div className="flex items-center justify-between">
            <div className="text-sm">
              <span className="text-green-600 font-medium">Live</span>
              {storefrontUrl && (
                <a href={storefrontUrl} target="_blank" rel="noreferrer" className="ml-2 text-primary inline-flex items-center gap-1">
                  {storefrontUrl} <ExternalLink className="h-3 w-3" />
                </a>
              )}
            </div>
            <Button variant="outline" size="sm" onClick={() => togglePublish(false)} disabled={busy}>Unpublish</Button>
          </div>
        ) : (
          <div className="space-y-2">
            <p className="text-sm text-muted-foreground">Your storefront is hidden. Set a subdomain and add your Stripe keys, then publish.</p>
            <Button variant="hero" onClick={() => togglePublish(true)} disabled={busy}>Publish my site</Button>
          </div>
        )}
      </div>
    </div>
  );
};

CompanySiteIndex.layout = (page: ReactNode) => <AdminLayout>{page}</AdminLayout>;

export default CompanySiteIndex;
