import { createFileRoute, useNavigate } from "@tanstack/react-router";
import { useEffect, useState } from "react";
import { Card } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Switch } from "@/components/ui/switch";
import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs";
import { Loader2, ShieldCheck, ShieldAlert, UserRoundCog, ScrollText, Settings2, Save } from "lucide-react";
import { authApi } from "@/lib/auth";
import { useAuth } from "@/lib/auth";
import { backendApi, type AdminSettings } from "@/lib/backend-client";
import { toast } from "sonner";

export const Route = createFileRoute("/_app/admin")({
  component: AdminPage,
});

interface Row {
  id: string;
  email: string;
  role: string;
  status: string;
  created_at: string;
  last_login_at: string | null;
  delta_linked: boolean;
}

function AdminPage() {
  const { user, loading, impersonate } = useAuth();
  const nav = useNavigate();
  const [rows, setRows] = useState<Row[] | null>(null);
  const [busy, setBusy] = useState<string | null>(null);
  const [error, setError] = useState<string | null>(null);

  // Role-based guard: only real admins (not admins currently impersonating a
  // user, and not regular users) may see this route. Non-admins get a clear
  // toast and are redirected to the dashboard; admins-mid-impersonation keep
  // seeing the "exit impersonation" affordance.
  const isRealAdmin = user?.role === "admin" && !user.impersonating;
  useEffect(() => {
    if (loading || !user) return; // parent layout handles sign-in redirect
    if (user.role !== "admin") {
      toast.error("Admin access required", {
        description: "You don't have permission to view the admin panel.",
      });
      nav({ to: "/dashboard", replace: true });
    }
  }, [loading, user, nav]);

  async function load() {
    setError(null);
    try {
      setRows(await authApi.listUsers());
    } catch (e) {
      setError(e instanceof Error ? e.message : "Failed to load users");
    }
  }

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

  if (loading) {
    return (
      <Card className="glass-strong p-6">
        <div className="flex items-center gap-2 text-sm text-muted-foreground">
          <Loader2 className="h-4 w-4 animate-spin" />
          Checking permissions…
        </div>
      </Card>
    );
  }

  if (user?.role !== "admin") {
    // Redirect is in flight from the effect above; render a placeholder so the
    // old table doesn't flash for a frame.
    return (
      <Card className="glass-strong p-6">
        <div className="flex items-center gap-2 text-sm text-destructive">
          <ShieldAlert className="h-4 w-4" />
          Admin access required. Redirecting…
        </div>
      </Card>
    );
  }

  if (user.impersonating) {
    return (
      <Card className="glass-strong p-6">
        <div className="flex items-center gap-2 text-sm text-muted-foreground">
          <ShieldCheck className="h-4 w-4" />
          Admin panel is disabled during an impersonation session. Exit impersonation to manage users.
        </div>
      </Card>
    );
  }



  return (
    <Tabs defaultValue="users" className="grid gap-4">
      <TabsList className="w-fit">
        <TabsTrigger value="users"><UserRoundCog className="mr-1 h-3.5 w-3.5" />Users</TabsTrigger>
        <TabsTrigger value="audit"><ScrollText className="mr-1 h-3.5 w-3.5" />Audit log</TabsTrigger>
        <TabsTrigger value="settings"><Settings2 className="mr-1 h-3.5 w-3.5" />App Settings</TabsTrigger>
      </TabsList>

      <TabsContent value="users">
        <Card className="glass-strong p-4">
          <div className="mb-3 flex items-center justify-between">
            <div>
              <h2 className="font-display text-base font-semibold">All users</h2>
              <p className="text-xs text-muted-foreground">Impersonation sessions are <strong>read-only</strong>: you can view positions & signals but never approve, close, or modify trades on behalf of a user.</p>
            </div>
            <Button variant="outline" size="sm" onClick={load}>Refresh</Button>
          </div>
          {error && <div className="mb-3 rounded-md border border-destructive/40 bg-destructive/10 p-2 text-xs text-destructive">{error}</div>}
          <div className="overflow-x-auto">
            <table className="w-full text-sm">
              <thead className="text-xs uppercase text-muted-foreground">
                <tr className="text-left">
                  <th className="py-2">Email</th>
                  <th className="py-2">Role</th>
                  <th className="py-2">Delta</th>
                  <th className="py-2">Last login</th>
                  <th className="py-2 text-right">Action</th>
                </tr>
              </thead>
              <tbody>
                {rows === null ? (
                  <tr><td colSpan={5} className="py-6 text-center text-muted-foreground"><Loader2 className="mx-auto h-4 w-4 animate-spin" /></td></tr>
                ) : rows.length === 0 ? (
                  <tr><td colSpan={5} className="py-6 text-center text-muted-foreground">No users yet.</td></tr>
                ) : (
                  rows.map((r) => (
                    <tr key={r.id} className="border-t border-border/60">
                      <td className="py-2">
                        <span className="truncate">{r.email}</span>
                        {r.id === user.id && <span className="ml-2 rounded bg-primary/20 px-1.5 py-0.5 text-[10px] uppercase text-primary">You</span>}
                      </td>
                      <td className="py-2 capitalize">{r.role}</td>
                      <td className="py-2">
                        {r.delta_linked
                          ? <span className="rounded bg-emerald-500/15 px-2 py-0.5 text-[11px] text-emerald-300">linked</span>
                          : <span className="text-[11px] text-muted-foreground">—</span>}
                      </td>
                      <td className="py-2 text-xs text-muted-foreground">
                        {r.last_login_at ? new Date(r.last_login_at).toLocaleString() : "—"}
                      </td>
                      <td className="py-2 text-right">
                        <Button
                          size="sm"
                          variant={r.id === user.id || r.role === "admin" ? "ghost" : "outline"}
                          disabled={r.id === user.id || r.role === "admin" || busy === r.id}
                          onClick={async () => {
                            setBusy(r.id);
                            try {
                              await impersonate(r.id);
                              toast.success(`Now viewing as ${r.email}`);
                            } catch (e) {
                              toast.error(e instanceof Error ? e.message : "Impersonation failed");
                            } finally {
                              setBusy(null);
                            }
                          }}
                        >
                          {busy === r.id ? <Loader2 className="h-3.5 w-3.5 animate-spin" /> : <><UserRoundCog className="mr-1 h-3.5 w-3.5" />Impersonate</>}
                        </Button>
                      </td>
                    </tr>
                  ))
                )}
              </tbody>
            </table>
          </div>
        </Card>
      </TabsContent>

      <TabsContent value="audit">
        <AuditPanel />
      </TabsContent>

      <TabsContent value="settings">
        <AppSettingsPanel />
      </TabsContent>
    </Tabs>
  );
}

// ---------------- App Settings Panel ----------------

function AppSettingsPanel() {
  const [s, setS] = useState<AdminSettings | null>(null);
  const [busy, setBusy] = useState(false);
  const [secrets, setSecrets] = useState<Record<"google" | "facebook" | "x", string>>({ google: "", facebook: "", x: "" });

  useEffect(() => {
    backendApi.getAdminSettings().then(setS).catch((e) => toast.error(e instanceof Error ? e.message : "Load failed"));
  }, []);

  if (!s) {
    return (
      <Card className="glass-strong p-6">
        <Loader2 className="mx-auto h-5 w-5 animate-spin text-muted-foreground" />
      </Card>
    );
  }

  async function save() {
    setBusy(true);
    try {
      const patch = {
        branding: s!.branding,
        features: s!.features,
        oauth: {
          google: { client_id: s!.oauth.google.client_id, redirect_uri: s!.oauth.google.redirect_uri, ...(secrets.google ? { client_secret: secrets.google } : {}) },
          facebook: { client_id: s!.oauth.facebook.client_id, redirect_uri: s!.oauth.facebook.redirect_uri, ...(secrets.facebook ? { client_secret: secrets.facebook } : {}) },
          x: { client_id: s!.oauth.x.client_id, redirect_uri: s!.oauth.x.redirect_uri, ...(secrets.x ? { client_secret: secrets.x } : {}) },
        },
      };
      const next = await backendApi.saveAdminSettings(patch);
      setS(next);
      setSecrets({ google: "", facebook: "", x: "" });
      toast.success("Settings saved — reload to apply branding");
    } catch (e) {
      toast.error(e instanceof Error ? e.message : "Save failed");
    } finally {
      setBusy(false);
    }
  }

  const updateBranding = (k: keyof AdminSettings["branding"], v: string) =>
    setS({ ...s, branding: { ...s.branding, [k]: v } });
  const updateFeature = (k: keyof AdminSettings["features"], v: boolean) =>
    setS({ ...s, features: { ...s.features, [k]: v } });
  const updateOAuth = (p: "google" | "facebook" | "x", k: "client_id" | "redirect_uri", v: string) =>
    setS({ ...s, oauth: { ...s.oauth, [p]: { ...s.oauth[p], [k]: v } } });

  return (
    <div className="grid gap-4">
      <Card className="glass-strong p-5">
        <h3 className="font-display text-base font-semibold">Branding</h3>
        <p className="mb-4 text-xs text-muted-foreground">Applied globally on next load.</p>
        <div className="grid gap-4 md:grid-cols-2">
          <div className="grid gap-1.5"><Label>App title</Label><Input value={s.branding.app_title} onChange={(e) => updateBranding("app_title", e.target.value)} /></div>
          <div className="grid gap-1.5"><Label>Meta description</Label><Input value={s.branding.app_description} onChange={(e) => updateBranding("app_description", e.target.value)} /></div>
          <div className="grid gap-1.5"><Label>Logo URL</Label><Input value={s.branding.logo_url} onChange={(e) => updateBranding("logo_url", e.target.value)} placeholder="https://…/logo.png" /></div>
          <div className="grid gap-1.5"><Label>Favicon URL</Label><Input value={s.branding.favicon_url} onChange={(e) => updateBranding("favicon_url", e.target.value)} /></div>
          <div className="grid gap-1.5"><Label>Primary color</Label><div className="flex gap-2"><Input type="color" value={s.branding.primary_color} onChange={(e) => updateBranding("primary_color", e.target.value)} className="h-10 w-14 p-1" /><Input value={s.branding.primary_color} onChange={(e) => updateBranding("primary_color", e.target.value)} /></div></div>
          <div className="grid gap-1.5"><Label>Accent color</Label><div className="flex gap-2"><Input type="color" value={s.branding.accent_color} onChange={(e) => updateBranding("accent_color", e.target.value)} className="h-10 w-14 p-1" /><Input value={s.branding.accent_color} onChange={(e) => updateBranding("accent_color", e.target.value)} /></div></div>
        </div>
      </Card>

      <Card className="glass-strong p-5">
        <h3 className="font-display text-base font-semibold">Feature toggles</h3>
        <p className="mb-4 text-xs text-muted-foreground">Master switches for auth providers and app features.</p>
        <div className="grid gap-3">
          <ToggleRow label="Allow new user registration" checked={s.features.registration_enabled} onChange={(v) => updateFeature("registration_enabled", v)} />
          <ToggleRow label="Auto-approve trade signals (skip manual review)" checked={s.features.auto_approve_trades} onChange={(v) => updateFeature("auto_approve_trades", v)} />
          <ToggleRow label="Google login" checked={s.features.google_login_enabled} onChange={(v) => updateFeature("google_login_enabled", v)} />
          <ToggleRow label="Facebook login" checked={s.features.facebook_login_enabled} onChange={(v) => updateFeature("facebook_login_enabled", v)} />
          <ToggleRow label="X (Twitter) login" checked={s.features.x_login_enabled} onChange={(v) => updateFeature("x_login_enabled", v)} />
        </div>
      </Card>

      {(["google", "facebook", "x"] as const).map((p) => (
        <Card key={p} className="glass-strong p-5">
          <h3 className="font-display text-base font-semibold capitalize">{p === "x" ? "X (Twitter)" : p} OAuth</h3>
          <p className="mb-4 text-xs text-muted-foreground">Add the credentials from the provider's developer console. Redirect URI must match exactly.</p>
          <div className="grid gap-4 md:grid-cols-2">
            <div className="grid gap-1.5"><Label>Client ID</Label><Input value={s.oauth[p].client_id} onChange={(e) => updateOAuth(p, "client_id", e.target.value)} /></div>
            <div className="grid gap-1.5"><Label>Redirect URI</Label><Input value={s.oauth[p].redirect_uri} onChange={(e) => updateOAuth(p, "redirect_uri", e.target.value)} placeholder={`https://api.example.com/api/auth/oauth/${p}/callback`} /></div>
            <div className="grid gap-1.5 md:col-span-2">
              <Label>Client secret {s.oauth[p].has_secret && <span className="ml-2 text-[10px] uppercase text-emerald-400">saved</span>}</Label>
              <Input type="password" value={secrets[p]} onChange={(e) => setSecrets({ ...secrets, [p]: e.target.value })} placeholder={s.oauth[p].has_secret ? "•••••• (leave blank to keep existing)" : "Paste secret"} />
            </div>
          </div>
        </Card>
      ))}

      <div className="flex justify-end">
        <Button onClick={save} disabled={busy}>
          {busy ? <Loader2 className="mr-2 h-4 w-4 animate-spin" /> : <Save className="mr-2 h-4 w-4" />}
          Save all settings
        </Button>
      </div>
    </div>
  );
}

function ToggleRow({ label, checked, onChange }: { label: string; checked: boolean; onChange: (v: boolean) => void }) {
  return (
    <div className="flex items-center justify-between rounded-md border border-border/50 bg-background/30 px-3 py-2">
      <span className="text-sm">{label}</span>
      <Switch checked={checked} onCheckedChange={onChange} />
    </div>
  );
}

interface AuditRow {
  id: string;
  actor_email: string | null;
  subject_email: string | null;
  impersonating: boolean;
  action: string;
  meta: Record<string, unknown>;
  ts: string;
}

function AuditPanel() {
  const [rows, setRows] = useState<AuditRow[] | null>(null);
  const [error, setError] = useState<string | null>(null);
  const [filter, setFilter] = useState("");

  async function load() {
    setError(null);
    try { setRows((await backendApi.listAudit({ limit: 300 })) as unknown as AuditRow[]); }
    catch (e) { setError(e instanceof Error ? e.message : "Failed to load audit log"); }
  }
  useEffect(() => { load(); }, []);

  const filtered = (rows ?? []).filter((r) => {
    if (!filter.trim()) return true;
    const q = filter.toLowerCase();
    return (
      r.action.toLowerCase().includes(q) ||
      (r.actor_email ?? "").toLowerCase().includes(q) ||
      (r.subject_email ?? "").toLowerCase().includes(q)
    );
  });

  return (
    <Card className="glass-strong p-4">
      <div className="mb-3 flex flex-wrap items-center justify-between gap-2">
        <div>
          <h2 className="font-display text-base font-semibold">Audit trail</h2>
          <p className="text-xs text-muted-foreground">Every impersonation session and trade modification, in order.</p>
        </div>
        <div className="flex items-center gap-2">
          <input
            value={filter} onChange={(e) => setFilter(e.target.value)}
            placeholder="Filter by action or email…"
            className="h-9 w-64 rounded-md border border-border/60 bg-transparent px-3 text-sm outline-none focus:border-primary"
          />
          <Button variant="outline" size="sm" onClick={load}>Refresh</Button>
        </div>
      </div>
      {error && <div className="mb-3 rounded-md border border-destructive/40 bg-destructive/10 p-2 text-xs text-destructive">{error}</div>}
      <div className="overflow-x-auto">
        <table className="w-full text-sm">
          <thead className="text-xs uppercase text-muted-foreground">
            <tr className="text-left">
              <th className="py-2">When</th>
              <th className="py-2">Actor</th>
              <th className="py-2">Subject</th>
              <th className="py-2">Action</th>
              <th className="py-2">Details</th>
            </tr>
          </thead>
          <tbody>
            {rows === null ? (
              <tr><td colSpan={5} className="py-6 text-center text-muted-foreground"><Loader2 className="mx-auto h-4 w-4 animate-spin" /></td></tr>
            ) : filtered.length === 0 ? (
              <tr><td colSpan={5} className="py-6 text-center text-muted-foreground">No matching entries.</td></tr>
            ) : (
              filtered.map((r) => (
                <tr key={r.id} className="border-t border-border/60 align-top">
                  <td className="py-2 whitespace-nowrap text-xs text-muted-foreground">{new Date(r.ts).toLocaleString()}</td>
                  <td className="py-2">
                    {r.actor_email ?? <span className="text-muted-foreground">—</span>}
                    {r.impersonating && <span className="ml-2 rounded bg-amber-500/15 px-1.5 py-0.5 text-[10px] uppercase text-amber-300">impersonating</span>}
                  </td>
                  <td className="py-2">{r.subject_email ?? <span className="text-muted-foreground">—</span>}</td>
                  <td className="py-2"><code className="rounded bg-muted/40 px-1.5 py-0.5 text-[11px]">{r.action}</code></td>
                  <td className="py-2 text-xs text-muted-foreground">
                    <code className="whitespace-pre-wrap break-all">{JSON.stringify(r.meta)}</code>
                  </td>
                </tr>
              ))
            )}
          </tbody>
        </table>
      </div>
    </Card>
  );
}
