import { useState, useEffect } from "react";
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import {
  Settings,
  Mail,
  Webhook,
  Bell,
  User,
  Plus,
  Trash2,
  TestTube,
  Save,
  Eye,
  EyeOff,
  CheckCircle,
  XCircle,
  AlertCircle,
  Loader2,
  Edit2,
  X,
  Link2,
} from "lucide-react";
import { useAuth } from "../context/AuthContext";
import {
  getEmailConfig,
  updateEmailConfig,
  sendTestEmail,
  getWebhooks,
  createWebhook,
  updateWebhook,
  deleteWebhook,
  testWebhook,
  getMe,
  updateMyPreferences,
  getJiraConfig,
  updateJiraConfig,
  testJiraConnection,
  testTempoConnection,
  type EmailConfigUpdate,
  type WebhookCreate,
  type WebhookOut,
  type NotificationPreferences,
  type JiraConfigUpdate,
} from "../api/settings";

// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------

function Section({
  title,
  icon: Icon,
  children,
}: {
  title: string;
  icon: React.FC<{ className?: string }>;
  children: React.ReactNode;
}) {
  return (
    <div className="rounded-xl border border-gray-800 bg-gray-900 p-6">
      <h2 className="mb-6 flex items-center gap-2 text-lg font-semibold text-white">
        <Icon className="h-5 w-5 text-cyan-400" />
        {title}
      </h2>
      {children}
    </div>
  );
}

function ToggleRow({
  label,
  description,
  checked,
  onChange,
}: {
  label: string;
  description?: string;
  checked: boolean;
  onChange: (v: boolean) => void;
}) {
  return (
    <div className="flex items-center justify-between py-3 border-b border-gray-800 last:border-0">
      <div>
        <p className="text-sm font-medium text-gray-200">{label}</p>
        {description && <p className="text-xs text-gray-500">{description}</p>}
      </div>
      <button
        type="button"
        onClick={() => onChange(!checked)}
        className={`relative inline-flex h-6 w-11 items-center rounded-full transition-colors ${
          checked ? "bg-cyan-500" : "bg-gray-700"
        }`}
      >
        <span
          className={`inline-block h-4 w-4 transform rounded-full bg-white transition-transform ${
            checked ? "translate-x-6" : "translate-x-1"
          }`}
        />
      </button>
    </div>
  );
}

function Toast({
  message,
  type,
  onClose,
}: {
  message: string;
  type: "success" | "error";
  onClose: () => void;
}) {
  return (
    <div
      className={`fixed bottom-6 right-6 z-50 flex items-center gap-3 rounded-lg px-4 py-3 shadow-lg text-sm font-medium ${
        type === "success"
          ? "bg-emerald-900/90 text-emerald-300 border border-emerald-700"
          : "bg-red-900/90 text-red-300 border border-red-700"
      }`}
    >
      {type === "success" ? (
        <CheckCircle className="h-4 w-4 shrink-0" />
      ) : (
        <XCircle className="h-4 w-4 shrink-0" />
      )}
      {message}
      <button onClick={onClose} className="ml-2 opacity-60 hover:opacity-100">
        <X className="h-4 w-4" />
      </button>
    </div>
  );
}

// ---------------------------------------------------------------------------
// SMTP Email Section (admin only)
// ---------------------------------------------------------------------------

const AVAILABLE_EVENTS = [
  "test.validated",
  "test.rejected",
  "campaign.completed",
  "campaign.started",
  "mitre.synced",
  "webhook.test",
];

function EmailSection() {
  const qc = useQueryClient();
  const [showPw, setShowPw] = useState(false);
  const [toast, setToast] = useState<{ msg: string; type: "success" | "error" } | null>(null);
  const [testEmail, setTestEmail] = useState("");

  const { data: cfg, isLoading } = useQuery({
    queryKey: ["email-config"],
    queryFn: getEmailConfig,
  });

  const [form, setForm] = useState<EmailConfigUpdate & { password?: string }>({});
  const effective = { ...cfg, ...form };

  const saveMutation = useMutation({
    mutationFn: updateEmailConfig,
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: ["email-config"] });
      setForm({});
      setToast({ msg: "Email configuration saved", type: "success" });
    },
    onError: () => setToast({ msg: "Failed to save email configuration", type: "error" }),
  });

  const testMutation = useMutation({
    mutationFn: () => sendTestEmail(testEmail),
    onSuccess: () => setToast({ msg: `Test email sent to ${testEmail}`, type: "success" }),
    onError: () =>
      setToast({ msg: "Failed to send test email. Check SMTP settings and logs.", type: "error" }),
  });

  if (isLoading) {
    return (
      <div className="flex justify-center py-8">
        <Loader2 className="h-6 w-6 animate-spin text-cyan-400" />
      </div>
    );
  }

  const field = (
    key: keyof EmailConfigUpdate,
    label: string,
    type = "text",
    placeholder = ""
  ) => (
    <div>
      <label className="mb-1 block text-xs font-medium text-gray-400">{label}</label>
      <input
        type={type}
        value={String(form[key] ?? cfg?.[key as keyof typeof cfg] ?? "")}
        onChange={(e) =>
          setForm((prev) => ({ ...prev, [key]: e.target.value }))
        }
        placeholder={placeholder}
        className="w-full rounded-lg border border-gray-700 bg-gray-800 px-3 py-2 text-sm text-gray-200 placeholder-gray-600 focus:border-cyan-500 focus:outline-none"
      />
    </div>
  );

  return (
    <>
      {toast && (
        <Toast message={toast.msg} type={toast.type} onClose={() => setToast(null)} />
      )}
      <div className="space-y-4">
        {/* Enable toggle */}
        <ToggleRow
          label="Enable email notifications"
          description="When disabled, no emails are sent regardless of other settings"
          checked={Boolean(form.enabled !== undefined ? form.enabled : cfg?.enabled)}
          onChange={(v) => setForm((prev) => ({ ...prev, enabled: v }))}
        />

        <div className="grid grid-cols-2 gap-4 pt-2">
          {field("host", "SMTP Host", "text", "smtp.gmail.com")}
          <div>
            <label className="mb-1 block text-xs font-medium text-gray-400">SMTP Port</label>
            <input
              type="number"
              value={String(form.port ?? cfg?.port ?? 587)}
              onChange={(e) =>
                setForm((prev) => ({ ...prev, port: parseInt(e.target.value) || 587 }))
              }
              className="w-full rounded-lg border border-gray-700 bg-gray-800 px-3 py-2 text-sm text-gray-200 focus:border-cyan-500 focus:outline-none"
            />
          </div>
          {field("username", "Username / Email", "text", "you@company.com")}
          <div>
            <label className="mb-1 block text-xs font-medium text-gray-400">Password</label>
            <div className="relative">
              <input
                type={showPw ? "text" : "password"}
                value={String(form.password ?? "")}
                onChange={(e) => setForm((prev) => ({ ...prev, password: e.target.value }))}
                placeholder="Leave blank to keep current"
                className="w-full rounded-lg border border-gray-700 bg-gray-800 px-3 py-2 pr-10 text-sm text-gray-200 placeholder-gray-600 focus:border-cyan-500 focus:outline-none"
              />
              <button
                type="button"
                onClick={() => setShowPw(!showPw)}
                className="absolute right-2 top-1/2 -translate-y-1/2 text-gray-500 hover:text-gray-300"
              >
                {showPw ? <EyeOff className="h-4 w-4" /> : <Eye className="h-4 w-4" />}
              </button>
            </div>
          </div>
          {field("from_email", "From Address", "email", "aegis@company.com")}
        </div>

        <ToggleRow
          label="Use TLS (STARTTLS)"
          checked={Boolean(form.use_tls !== undefined ? form.use_tls : cfg?.use_tls)}
          onChange={(v) => setForm((prev) => ({ ...prev, use_tls: v }))}
        />

        <div className="flex items-center justify-between pt-2">
          <button
            onClick={() => {
              if (Object.keys(form).length > 0) saveMutation.mutate(form);
            }}
            disabled={saveMutation.isPending || Object.keys(form).length === 0}
            className="flex items-center gap-2 rounded-lg bg-cyan-600 px-4 py-2 text-sm font-medium text-white hover:bg-cyan-500 disabled:opacity-50 transition-colors"
          >
            {saveMutation.isPending ? (
              <Loader2 className="h-4 w-4 animate-spin" />
            ) : (
              <Save className="h-4 w-4" />
            )}
            Save Configuration
          </button>
        </div>

        {/* Test email */}
        <div className="mt-4 rounded-lg border border-gray-700 bg-gray-800/50 p-4">
          <p className="mb-3 text-sm font-medium text-gray-300">Send Test Email</p>
          <div className="flex gap-2">
            <input
              type="email"
              value={testEmail}
              onChange={(e) => setTestEmail(e.target.value)}
              placeholder="recipient@example.com"
              className="flex-1 rounded-lg border border-gray-700 bg-gray-800 px-3 py-2 text-sm text-gray-200 placeholder-gray-600 focus:border-cyan-500 focus:outline-none"
            />
            <button
              onClick={() => testEmail && testMutation.mutate()}
              disabled={testMutation.isPending || !testEmail}
              className="flex items-center gap-2 rounded-lg border border-cyan-700 px-4 py-2 text-sm font-medium text-cyan-400 hover:bg-cyan-900/30 disabled:opacity-50 transition-colors"
            >
              {testMutation.isPending ? (
                <Loader2 className="h-4 w-4 animate-spin" />
              ) : (
                <TestTube className="h-4 w-4" />
              )}
              Send Test
            </button>
          </div>
        </div>
      </div>
    </>
  );
}

// ---------------------------------------------------------------------------
// Webhooks Section (admin + leads)
// ---------------------------------------------------------------------------

function WebhookForm({
  initial,
  onSave,
  onCancel,
  isSaving,
}: {
  initial?: Partial<WebhookCreate>;
  onSave: (data: WebhookCreate) => void;
  onCancel: () => void;
  isSaving: boolean;
}) {
  const [form, setForm] = useState<WebhookCreate>({
    name: initial?.name ?? "",
    url: initial?.url ?? "",
    secret: initial?.secret ?? "",
    events: initial?.events ?? [],
    is_active: initial?.is_active ?? true,
  });

  const toggleEvent = (ev: string) => {
    setForm((prev) => ({
      ...prev,
      events: prev.events.includes(ev)
        ? prev.events.filter((e) => e !== ev)
        : [...prev.events, ev],
    }));
  };

  return (
    <div className="rounded-lg border border-cyan-800/50 bg-gray-800/50 p-4 space-y-4">
      <div className="grid grid-cols-2 gap-3">
        <div>
          <label className="mb-1 block text-xs font-medium text-gray-400">Name</label>
          <input
            value={form.name}
            onChange={(e) => setForm((p) => ({ ...p, name: e.target.value }))}
            placeholder="My Webhook"
            className="w-full rounded-lg border border-gray-700 bg-gray-800 px-3 py-2 text-sm text-gray-200 placeholder-gray-600 focus:border-cyan-500 focus:outline-none"
          />
        </div>
        <div>
          <label className="mb-1 block text-xs font-medium text-gray-400">URL</label>
          <input
            value={form.url}
            onChange={(e) => setForm((p) => ({ ...p, url: e.target.value }))}
            placeholder="https://hooks.example.com/..."
            className="w-full rounded-lg border border-gray-700 bg-gray-800 px-3 py-2 text-sm text-gray-200 placeholder-gray-600 focus:border-cyan-500 focus:outline-none"
          />
        </div>
        <div className="col-span-2">
          <label className="mb-1 block text-xs font-medium text-gray-400">
            Secret (optional — used for HMAC-SHA256 signature)
          </label>
          <input
            value={form.secret ?? ""}
            onChange={(e) => setForm((p) => ({ ...p, secret: e.target.value }))}
            placeholder="supersecretkey"
            className="w-full rounded-lg border border-gray-700 bg-gray-800 px-3 py-2 text-sm text-gray-200 placeholder-gray-600 focus:border-cyan-500 focus:outline-none"
          />
        </div>
      </div>
      <div>
        <label className="mb-2 block text-xs font-medium text-gray-400">Events</label>
        <div className="flex flex-wrap gap-2">
          {AVAILABLE_EVENTS.map((ev) => (
            <button
              key={ev}
              type="button"
              onClick={() => toggleEvent(ev)}
              className={`rounded-full px-3 py-1 text-xs font-medium transition-colors ${
                form.events.includes(ev)
                  ? "bg-cyan-600 text-white"
                  : "bg-gray-700 text-gray-400 hover:bg-gray-600"
              }`}
            >
              {ev}
            </button>
          ))}
        </div>
      </div>
      <ToggleRow
        label="Active"
        checked={form.is_active ?? true}
        onChange={(v) => setForm((p) => ({ ...p, is_active: v }))}
      />
      <div className="flex gap-2 pt-1">
        <button
          onClick={() => onSave(form)}
          disabled={isSaving || !form.name || !form.url || form.events.length === 0}
          className="flex items-center gap-2 rounded-lg bg-cyan-600 px-4 py-2 text-sm font-medium text-white hover:bg-cyan-500 disabled:opacity-50 transition-colors"
        >
          {isSaving ? <Loader2 className="h-4 w-4 animate-spin" /> : <Save className="h-4 w-4" />}
          Save
        </button>
        <button
          onClick={onCancel}
          className="rounded-lg border border-gray-700 px-4 py-2 text-sm font-medium text-gray-400 hover:text-gray-200 hover:border-gray-500 transition-colors"
        >
          Cancel
        </button>
      </div>
    </div>
  );
}

function WebhooksSection() {
  const qc = useQueryClient();
  const [toast, setToast] = useState<{ msg: string; type: "success" | "error" } | null>(null);
  const [creating, setCreating] = useState(false);
  const [editingId, setEditingId] = useState<string | null>(null);

  const { data: webhooks = [], isLoading } = useQuery({
    queryKey: ["webhooks"],
    queryFn: getWebhooks,
  });

  const createMut = useMutation({
    mutationFn: createWebhook,
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: ["webhooks"] });
      setCreating(false);
      setToast({ msg: "Webhook created", type: "success" });
    },
    onError: () => setToast({ msg: "Failed to create webhook", type: "error" }),
  });

  const updateMut = useMutation({
    mutationFn: ({ id, data }: { id: string; data: Partial<WebhookCreate> }) =>
      updateWebhook(id, data),
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: ["webhooks"] });
      setEditingId(null);
      setToast({ msg: "Webhook updated", type: "success" });
    },
    onError: () => setToast({ msg: "Failed to update webhook", type: "error" }),
  });

  const deleteMut = useMutation({
    mutationFn: deleteWebhook,
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: ["webhooks"] });
      setToast({ msg: "Webhook deleted", type: "success" });
    },
    onError: () => setToast({ msg: "Failed to delete webhook", type: "error" }),
  });

  const testMut = useMutation({
    mutationFn: testWebhook,
    onSuccess: () => setToast({ msg: "Test ping dispatched", type: "success" }),
    onError: () => setToast({ msg: "Ping failed", type: "error" }),
  });

  if (isLoading) {
    return (
      <div className="flex justify-center py-8">
        <Loader2 className="h-6 w-6 animate-spin text-cyan-400" />
      </div>
    );
  }

  return (
    <>
      {toast && (
        <Toast message={toast.msg} type={toast.type} onClose={() => setToast(null)} />
      )}
      <div className="space-y-3">
        {webhooks.length === 0 && !creating && (
          <p className="text-center py-6 text-sm text-gray-500">No webhooks configured yet.</p>
        )}

        {webhooks.map((wh) =>
          editingId === wh.id ? (
            <WebhookForm
              key={wh.id}
              initial={{
                name: wh.name,
                url: wh.url,
                events: wh.events,
                is_active: wh.is_active,
              }}
              onSave={(data) => updateMut.mutate({ id: wh.id, data })}
              onCancel={() => setEditingId(null)}
              isSaving={updateMut.isPending}
            />
          ) : (
            <WebhookRow
              key={wh.id}
              wh={wh}
              onEdit={() => setEditingId(wh.id)}
              onDelete={() => deleteMut.mutate(wh.id)}
              onTest={() => testMut.mutate(wh.id)}
              isDeleting={deleteMut.isPending}
              isTesting={testMut.isPending}
            />
          )
        )}

        {creating && (
          <WebhookForm
            onSave={(data) => createMut.mutate(data)}
            onCancel={() => setCreating(false)}
            isSaving={createMut.isPending}
          />
        )}

        {!creating && (
          <button
            onClick={() => setCreating(true)}
            className="flex items-center gap-2 rounded-lg border border-dashed border-gray-700 px-4 py-2.5 text-sm font-medium text-gray-500 hover:border-cyan-700 hover:text-cyan-400 transition-colors w-full justify-center"
          >
            <Plus className="h-4 w-4" />
            Add Webhook
          </button>
        )}
      </div>
    </>
  );
}

function WebhookRow({
  wh,
  onEdit,
  onDelete,
  onTest,
  isDeleting,
  isTesting,
}: {
  wh: WebhookOut;
  onEdit: () => void;
  onDelete: () => void;
  onTest: () => void;
  isDeleting: boolean;
  isTesting: boolean;
}) {
  return (
    <div className="rounded-lg border border-gray-800 bg-gray-800/30 p-4">
      <div className="flex items-start justify-between gap-4">
        <div className="min-w-0 flex-1">
          <div className="flex items-center gap-2">
            <span className="font-medium text-sm text-gray-200">{wh.name}</span>
            <span
              className={`text-[10px] font-semibold uppercase rounded-full px-2 py-0.5 ${
                wh.is_active
                  ? "bg-emerald-900/50 text-emerald-400"
                  : "bg-gray-700 text-gray-500"
              }`}
            >
              {wh.is_active ? "active" : "inactive"}
            </span>
            {wh.failure_count > 0 && (
              <span className="text-[10px] font-semibold uppercase rounded-full px-2 py-0.5 bg-red-900/50 text-red-400 flex items-center gap-1">
                <AlertCircle className="h-3 w-3" />
                {wh.failure_count} failures
              </span>
            )}
          </div>
          <p className="mt-0.5 text-xs text-gray-500 truncate">{wh.url}</p>
          <div className="mt-1.5 flex flex-wrap gap-1">
            {wh.events.map((ev) => (
              <span
                key={ev}
                className="text-[10px] rounded-full bg-gray-700 px-2 py-0.5 text-gray-400"
              >
                {ev}
              </span>
            ))}
          </div>
        </div>
        <div className="flex items-center gap-1.5 shrink-0">
          <button
            onClick={onTest}
            disabled={isTesting}
            title="Send test ping"
            className="p-1.5 rounded-lg text-gray-500 hover:text-cyan-400 hover:bg-cyan-900/20 transition-colors disabled:opacity-40"
          >
            {isTesting ? (
              <Loader2 className="h-4 w-4 animate-spin" />
            ) : (
              <TestTube className="h-4 w-4" />
            )}
          </button>
          <button
            onClick={onEdit}
            title="Edit"
            className="p-1.5 rounded-lg text-gray-500 hover:text-gray-200 hover:bg-gray-700 transition-colors"
          >
            <Edit2 className="h-4 w-4" />
          </button>
          <button
            onClick={onDelete}
            disabled={isDeleting}
            title="Delete"
            className="p-1.5 rounded-lg text-gray-500 hover:text-red-400 hover:bg-red-900/20 transition-colors disabled:opacity-40"
          >
            <Trash2 className="h-4 w-4" />
          </button>
        </div>
      </div>
    </div>
  );
}

// ---------------------------------------------------------------------------
// Notification Preferences Section (all users)
// ---------------------------------------------------------------------------

const PREF_DEFS: {
  key: keyof NotificationPreferences;
  label: string;
  description?: string;
  roles: string[]; // roles that see this pref
}[] = [
  {
    key: "email_on_test_validated",
    label: "Email on test validated",
    description: "Receive an email when a test you're involved with gets validated",
    roles: ["admin", "red_lead", "blue_lead", "red_tech", "blue_tech", "viewer"],
  },
  {
    key: "email_on_test_rejected",
    label: "Email on test rejected",
    description: "Receive an email when a test you submitted gets rejected",
    roles: ["admin", "red_lead", "blue_lead", "red_tech", "blue_tech"],
  },
  {
    key: "email_on_campaign_completed",
    label: "Email on campaign completed",
    roles: ["admin", "red_lead", "blue_lead", "red_tech", "blue_tech"],
  },
  {
    key: "email_on_new_mitre_techniques",
    label: "Email on new MITRE techniques",
    description: "Get notified when the MITRE ATT&CK sync adds new techniques",
    roles: ["admin", "red_lead", "blue_lead"],
  },
  {
    key: "email_on_stale_coverage",
    label: "Email on stale coverage alert",
    description: "Notified when techniques haven't been tested in a long time",
    roles: ["admin", "red_lead", "blue_lead"],
  },
  {
    key: "email_on_assigned_to_campaign",
    label: "Email when assigned to a campaign",
    roles: ["admin", "red_lead", "blue_lead", "red_tech", "blue_tech"],
  },
  {
    key: "email_on_test_state_change",
    label: "Email on test state change",
    description: "Notified when tests move through the validation workflow",
    roles: ["admin", "red_lead", "blue_lead", "red_tech", "blue_tech"],
  },
  {
    key: "email_on_all_team_validations",
    label: "Email on all team validations",
    description: "Lead-level: receive email for every validation in your team",
    roles: ["admin", "red_lead", "blue_lead"],
  },
  {
    key: "email_on_webhook_failures",
    label: "Email on webhook delivery failures",
    roles: ["admin", "red_lead", "blue_lead"],
  },
  {
    key: "email_on_new_users",
    label: "Email on new user registration",
    roles: ["admin"],
  },
  {
    key: "email_on_system_errors",
    label: "Email on system errors",
    description: "Critical errors in background jobs and integrations",
    roles: ["admin"],
  },
  {
    key: "in_app_all",
    label: "In-app notifications",
    description: "Show notification bell alerts inside Aegis",
    roles: ["admin", "red_lead", "blue_lead", "red_tech", "blue_tech", "viewer"],
  },
];

const DEFAULT_PREFS: NotificationPreferences = {
  email_on_test_validated: true,
  email_on_test_rejected: true,
  email_on_campaign_completed: true,
  email_on_new_mitre_techniques: false,
  email_on_stale_coverage: false,
  email_on_assigned_to_campaign: true,
  email_on_test_state_change: true,
  email_on_all_team_validations: false,
  email_on_webhook_failures: true,
  email_on_new_users: false,
  email_on_system_errors: true,
  in_app_all: true,
};

function NotificationSection() {
  const qc = useQueryClient();
  const { user } = useAuth();
  const role = user?.role ?? "viewer";

  const [toast, setToast] = useState<{ msg: string; type: "success" | "error" } | null>(null);

  const { data: me, isLoading } = useQuery({
    queryKey: ["me-prefs"],
    queryFn: getMe,
  });

  const [localPrefs, setLocalPrefs] = useState<Partial<NotificationPreferences>>({});
  const [jiraAccountId, setJiraAccountId] = useState<string>("");
  const [jiraIdDirty, setJiraIdDirty] = useState(false);

  const effectivePrefs: NotificationPreferences = {
    ...DEFAULT_PREFS,
    ...(me?.notification_preferences ?? {}),
    ...localPrefs,
  };

  const saveMut = useMutation({
    mutationFn: updateMyPreferences,
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: ["me-prefs"] });
      setLocalPrefs({});
      setJiraIdDirty(false);
      setToast({ msg: "Preferences saved", type: "success" });
    },
    onError: () => setToast({ msg: "Failed to save preferences", type: "error" }),
  });

  const handleSave = () => {
    const payload: Parameters<typeof updateMyPreferences>[0] = {};
    if (Object.keys(localPrefs).length > 0) {
      payload.notification_preferences = {
        ...(me?.notification_preferences ?? {}),
        ...localPrefs,
      };
    }
    if (jiraIdDirty) {
      payload.jira_account_id = jiraAccountId || null;
    }
    if (Object.keys(payload).length > 0) {
      saveMut.mutate(payload);
    }
  };

  const isDirty = Object.keys(localPrefs).length > 0 || jiraIdDirty;

  if (isLoading) {
    return (
      <div className="flex justify-center py-8">
        <Loader2 className="h-6 w-6 animate-spin text-cyan-400" />
      </div>
    );
  }

  const visiblePrefs = PREF_DEFS.filter((d) => d.roles.includes(role));

  return (
    <>
      {toast && (
        <Toast message={toast.msg} type={toast.type} onClose={() => setToast(null)} />
      )}
      <div className="space-y-1">
        {visiblePrefs.map((def) => (
          <ToggleRow
            key={def.key}
            label={def.label}
            description={def.description}
            checked={Boolean(effectivePrefs[def.key])}
            onChange={(v) => setLocalPrefs((prev) => ({ ...prev, [def.key]: v }))}
          />
        ))}
      </div>

      <div className="mt-4 flex justify-end">
        <button
          onClick={handleSave}
          disabled={saveMut.isPending || !isDirty}
          className="flex items-center gap-2 rounded-lg bg-cyan-600 px-4 py-2 text-sm font-medium text-white hover:bg-cyan-500 disabled:opacity-50 transition-colors"
        >
          {saveMut.isPending ? (
            <Loader2 className="h-4 w-4 animate-spin" />
          ) : (
            <Save className="h-4 w-4" />
          )}
          Save Preferences
        </button>
      </div>
    </>
  );
}

// ---------------------------------------------------------------------------
// Profile / Jira Section (all users)
// ---------------------------------------------------------------------------

function ProfileSection() {
  const qc = useQueryClient();
  const [toast, setToast] = useState<{ msg: string; type: "success" | "error" } | null>(null);
  const { user } = useAuth();
  // Blue team roles have no Jira/Tempo access — hide those settings for them
  const showJiraTempoSettings = !["blue_lead", "blue_tech"].includes(user?.role ?? "");

  const { data: me, isLoading } = useQuery({
    queryKey: ["me-prefs"],
    queryFn: getMe,
  });

  const [jiraAccountId, setJiraAccountId] = useState<string>("");
  const [jiraEmail, setJiraEmail] = useState<string>("");
  const [jiraApiToken, setJiraApiToken] = useState<string>("");
  const [showToken, setShowToken] = useState(false);
  const [tempoApiToken, setTempoApiToken] = useState<string>("");
  const [showTempoToken, setShowTempoToken] = useState(false);
  const [tempoTestResult, setTempoTestResult] = useState<string | null>(null);
  const [tempoTestError, setTempoTestError] = useState<string | null>(null);
  const [dirty, setDirty] = useState(false);

  // Initialise editable fields from server on first successful load
  useEffect(() => {
    if (me) {
      setJiraAccountId(me.jira_account_id ?? "");
      setJiraEmail(me.jira_email ?? "");
      // Never pre-fill the token — we only know whether it is set, not its value
    }
  // Only run when `me` transitions from undefined → data (i.e., first load)
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [!!me]);

  const saveMut = useMutation({
    mutationFn: updateMyPreferences,
    onSuccess: (updatedMe) => {
      // Update cache immediately with the response — no extra round-trip needed
      qc.setQueryData(["me-prefs"], updatedMe);
      setDirty(false);
      setJiraApiToken("");   // clear token fields after save — they're persisted
      setTempoApiToken("");
      setToast({ msg: "Profile settings saved", type: "success" });
    },
    onError: () => setToast({ msg: "Failed to save", type: "error" }),
  });

  const tempoTestMut = useMutation({
    mutationFn: testTempoConnection,
    onSuccess: (data) => {
      if (data.status === "ok") {
        setTempoTestResult(data.message ?? "Connected");
        setTempoTestError(null);
      } else {
        setTempoTestError(data.message ?? "Tempo test failed");
        setTempoTestResult(null);
      }
    },
    onError: (err: Error) => {
      setTempoTestError(err.message || "Tempo test failed");
      setTempoTestResult(null);
    },
  });

  const handleSave = () => {
    const payload: Parameters<typeof updateMyPreferences>[0] = {
      jira_account_id: jiraAccountId || null,
      jira_email: jiraEmail || null,
    };
    // Only send tokens when the user has typed something new
    // (empty field = "keep current token unchanged")
    if (jiraApiToken.trim() !== "") {
      payload.jira_api_token = jiraApiToken.trim();
    }
    if (tempoApiToken.trim() !== "") {
      payload.tempo_api_token = tempoApiToken.trim();
    }
    saveMut.mutate(payload);
  };

  if (isLoading) {
    return (
      <div className="flex justify-center py-8">
        <Loader2 className="h-6 w-6 animate-spin text-cyan-400" />
      </div>
    );
  }

  return (
    <>
      {toast && (
        <Toast message={toast.msg} type={toast.type} onClose={() => setToast(null)} />
      )}
      <div className="space-y-4">
        <div className="grid grid-cols-2 gap-4 text-sm">
          <div>
            <p className="text-xs text-gray-500 mb-1">Username</p>
            <p className="text-gray-300 font-medium">{me?.username}</p>
          </div>
          <div>
            <p className="text-xs text-gray-500 mb-1">Role</p>
            <p className="text-gray-300 font-medium capitalize">{me?.role?.replace("_", " ")}</p>
          </div>
          <div>
            <p className="text-xs text-gray-500 mb-1">Email</p>
            <p className="text-gray-300">{me?.email ?? "—"}</p>
          </div>
          <div>
            <p className="text-xs text-gray-500 mb-1">Last Login</p>
            <p className="text-gray-300">
              {me?.last_login
                ? new Date(me.last_login).toLocaleString("en-US", {
                    timeZone: "UTC",
                    year: "numeric",
                    month: "short",
                    day: "numeric",
                    hour: "2-digit",
                    minute: "2-digit",
                  }) + " UTC"
                : "—"}
            </p>
          </div>
        </div>

        {showJiraTempoSettings && <div className="border-t border-gray-800 pt-4">
          <p className="text-sm font-semibold text-gray-300 mb-1">Jira Integration (personal settings)</p>
          <p className="text-xs text-gray-500 mb-4">
            Configure your personal Atlassian credentials for Jira integration.
          </p>

          <div className="space-y-4">
            {/* Jira email */}
            <div>
              <label className="mb-1 block text-xs font-medium text-cyan-400">
                Atlassian / Jira Email
              </label>
              <input
                type="email"
                value={jiraEmail}
                onChange={(e) => { setJiraEmail(e.target.value); setDirty(true); }}
                placeholder={me?.email ?? "your@company.com"}
                className="w-full rounded-lg border border-gray-700 bg-gray-800 px-3 py-2 text-sm text-gray-200 placeholder-gray-600 focus:border-cyan-500 focus:outline-none"
              />
              <p className="mt-1 text-xs text-gray-600">
                Email used to authenticate with Atlassian.
                {me?.email && !me?.jira_email && (
                  <span className="text-gray-500"> Currently using Aegis email: <span className="text-gray-400">{me.email}</span></span>
                )}
              </p>
            </div>

            {/* API Token */}
            <div>
              <label className="mb-1 block text-xs font-medium text-cyan-400">
                Jira API Token (Atlassian personal token)
              </label>
              <div className="relative">
                <input
                  type={showToken ? "text" : "password"}
                  value={jiraApiToken}
                  onChange={(e) => {
                    setJiraApiToken(e.target.value);
                    setDirty(true);
                  }}
                  placeholder={me?.jira_token_set ? "Leave blank to keep current token" : "Paste your Atlassian API token here"}
                  className="w-full rounded-lg border border-gray-700 bg-gray-800 px-3 py-2 pr-10 text-sm text-gray-200 placeholder-gray-600 focus:border-cyan-500 focus:outline-none"
                />
                <button
                  type="button"
                  onClick={() => setShowToken(!showToken)}
                  className="absolute right-2 top-1/2 -translate-y-1/2 text-gray-500 hover:text-gray-300"
                >
                  {showToken ? <EyeOff className="h-4 w-4" /> : <Eye className="h-4 w-4" />}
                </button>
              </div>
              <div className="mt-1.5 flex items-center gap-2">
                {me?.jira_token_set ? (
                  <span className="inline-flex items-center gap-1 rounded-full bg-emerald-900/50 px-2 py-0.5 text-[11px] font-medium text-emerald-400">
                    <CheckCircle className="h-3 w-3" />
                    Token configured
                  </span>
                ) : (
                  <span className="inline-flex items-center gap-1 rounded-full bg-amber-900/50 px-2 py-0.5 text-[11px] font-medium text-amber-400">
                    <AlertCircle className="h-3 w-3" />
                    Not configured
                  </span>
                )}
                <a
                  href="https://id.atlassian.com/manage-profile/security/api-tokens"
                  target="_blank"
                  rel="noopener noreferrer"
                  className="text-[11px] text-cyan-500 hover:text-cyan-400 underline"
                >
                  Create token at id.atlassian.com →
                </a>
              </div>
            </div>

            {/* Account ID */}
            <div>
              <label className="mb-1 block text-xs font-medium text-cyan-400">
                Jira Account ID (required for Tempo time tracking)
              </label>
              <input
                value={jiraAccountId}
                onChange={(e) => {
                  setJiraAccountId(e.target.value);
                  setDirty(true);
                }}
                placeholder="e.g. 5abcdef1234567890abcdef1"
                className="w-full max-w-sm rounded-lg border border-gray-700 bg-gray-800 px-3 py-2 text-sm text-gray-200 placeholder-gray-600 focus:border-cyan-500 focus:outline-none"
              />
              <p className="mt-1 text-xs text-gray-600">
                Your Atlassian account ID. Found in your Jira profile URL.
              </p>
            </div>
          </div>
        </div>}

        {/* ── Tempo Integration ─────────────────────────────────── */}
        {showJiraTempoSettings && <div className="border-t border-gray-800 pt-4">
          <p className="text-sm font-semibold text-gray-300 mb-1">Tempo Integration (personal settings)</p>
          <p className="text-xs text-gray-500 mb-4">
            Your personal Tempo API token logs work time on Jira tickets automatically.
          </p>

          <div className="space-y-4">
            {/* Tempo API Token */}
            <div>
              <label className="mb-1 block text-xs font-medium text-purple-400">
                Tempo API Token
              </label>
              <div className="relative">
                <input
                  type={showTempoToken ? "text" : "password"}
                  value={tempoApiToken}
                  onChange={(e) => {
                    setTempoApiToken(e.target.value);
                    setDirty(true);
                  }}
                  placeholder={me?.tempo_token_set ? "Leave blank to keep current token" : "Paste your Tempo API token here"}
                  className="w-full rounded-lg border border-gray-700 bg-gray-800 px-3 py-2 pr-10 text-sm text-gray-200 placeholder-gray-600 focus:border-purple-500 focus:outline-none"
                />
                <button
                  type="button"
                  onClick={() => setShowTempoToken(!showTempoToken)}
                  className="absolute right-2 top-1/2 -translate-y-1/2 text-gray-500 hover:text-gray-300"
                >
                  {showTempoToken ? <EyeOff className="h-4 w-4" /> : <Eye className="h-4 w-4" />}
                </button>
              </div>
              <div className="mt-1.5 flex items-center gap-2">
                {me?.tempo_token_set ? (
                  <span className="inline-flex items-center gap-1 rounded-full bg-emerald-900/50 px-2 py-0.5 text-[11px] font-medium text-emerald-400">
                    <CheckCircle className="h-3 w-3" />
                    Token configured
                  </span>
                ) : (
                  <span className="inline-flex items-center gap-1 rounded-full bg-amber-900/50 px-2 py-0.5 text-[11px] font-medium text-amber-400">
                    <AlertCircle className="h-3 w-3" />
                    Not configured
                  </span>
                )}
                <span className="text-[11px] text-gray-500">
                  Get it at: Jira → Apps → Tempo → Settings → API Integration
                </span>
              </div>
            </div>

            {/* Test Tempo connection */}
            <div className="rounded-lg border border-gray-700 bg-gray-800/50 p-3 space-y-2">
              <button
                onClick={() => {
                  setTempoTestResult(null);
                  setTempoTestError(null);
                  tempoTestMut.mutate();
                }}
                disabled={tempoTestMut.isPending || !me?.tempo_token_set}
                className="flex items-center gap-2 rounded-lg border border-purple-700 px-3 py-1.5 text-sm font-medium text-purple-400 hover:bg-purple-900/30 disabled:opacity-50 transition-colors"
              >
                {tempoTestMut.isPending ? (
                  <Loader2 className="h-4 w-4 animate-spin" />
                ) : (
                  <TestTube className="h-4 w-4" />
                )}
                Test Tempo Connection
              </button>
              {tempoTestResult && (
                <div className="flex items-center gap-2 rounded-md bg-emerald-900/30 border border-emerald-800/50 px-3 py-2 text-sm text-emerald-300">
                  <CheckCircle className="h-4 w-4 shrink-0" />
                  {tempoTestResult}
                </div>
              )}
              {tempoTestError && (
                <div className="flex items-center gap-2 rounded-md bg-red-900/30 border border-red-800/50 px-3 py-2 text-sm text-red-300">
                  <XCircle className="h-4 w-4 shrink-0" />
                  {tempoTestError}
                </div>
              )}
            </div>

            <div>
              <button
                onClick={handleSave}
                disabled={saveMut.isPending || !dirty}
                className="flex items-center gap-2 rounded-lg bg-cyan-600 px-4 py-2 text-sm font-medium text-white hover:bg-cyan-500 disabled:opacity-50 transition-colors"
              >
                {saveMut.isPending ? (
                  <Loader2 className="h-4 w-4 animate-spin" />
                ) : (
                  <Save className="h-4 w-4" />
                )}
                Save
              </button>
            </div>
          </div>
        </div>}
      </div>
    </>
  );
}

// ---------------------------------------------------------------------------
// Jira Admin Config Section (admin only)
// ---------------------------------------------------------------------------

function JiraConfigSection() {
  const qc = useQueryClient();
  const [toast, setToast] = useState<{ msg: string; type: "success" | "error" } | null>(null);
  const [testResult, setTestResult] = useState<{ connectedAs: string; url: string } | null>(null);
  const [testError, setTestError] = useState<string | null>(null);

  const { data: cfg, isLoading } = useQuery({
    queryKey: ["jira-config"],
    queryFn: getJiraConfig,
  });

  const [form, setForm] = useState<JiraConfigUpdate>({});
  const effective = { ...cfg, ...form };

  const saveMut = useMutation({
    mutationFn: updateJiraConfig,
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: ["jira-config"] });
      setForm({});
      setToast({ msg: "Jira configuration saved", type: "success" });
    },
    onError: () => setToast({ msg: "Failed to save Jira configuration", type: "error" }),
  });

  const testMut = useMutation({
    mutationFn: testJiraConnection,
    onSuccess: (data) => {
      // Backend always returns HTTP 200; status field tells us if it worked
      if (data.status === "ok") {
        setTestResult({ connectedAs: data.connected_as ?? "", url: data.jira_url ?? "" });
        setTestError(null);
      } else {
        setTestError((data as { message?: string }).message ?? "Connection failed");
        setTestResult(null);
      }
    },
    onError: (err: Error) => {
      setTestError(err.message || "Connection failed");
      setTestResult(null);
    },
  });

  if (isLoading) {
    return (
      <div className="flex justify-center py-8">
        <Loader2 className="h-6 w-6 animate-spin text-cyan-400" />
      </div>
    );
  }

  return (
    <>
      {toast && (
        <Toast message={toast.msg} type={toast.type} onClose={() => setToast(null)} />
      )}
      <div className="space-y-4">
        <ToggleRow
          label="Enable Jira Integration"
          description="Automatically create and update Jira tickets for tests"
          checked={Boolean(form.enabled !== undefined ? form.enabled : cfg?.enabled)}
          onChange={(v) => setForm((prev) => ({ ...prev, enabled: v }))}
        />

        <div className="grid grid-cols-2 gap-4 pt-2">
          <div className="col-span-2">
            <label className="mb-1 block text-xs font-medium text-cyan-400">Jira URL</label>
            <input
              type="text"
              value={String(form.url !== undefined ? form.url : (cfg?.url ?? ""))}
              onChange={(e) => setForm((prev) => ({ ...prev, url: e.target.value }))}
              placeholder="https://yourcompany.atlassian.net"
              className="w-full rounded-lg border border-gray-700 bg-gray-800 px-3 py-2 text-sm text-gray-200 placeholder-gray-600 focus:border-cyan-500 focus:outline-none"
            />
            <p className="mt-1 text-xs text-gray-600">Base URL of your Jira instance</p>
          </div>

          <div>
            <label className="mb-1 block text-xs font-medium text-cyan-400">Default Project Key</label>
            <input
              type="text"
              value={String(form.project_key !== undefined ? form.project_key : (cfg?.project_key ?? ""))}
              onChange={(e) => setForm((prev) => ({ ...prev, project_key: e.target.value }))}
              placeholder="SEC"
              className="w-full rounded-lg border border-gray-700 bg-gray-800 px-3 py-2 text-sm text-gray-200 placeholder-gray-600 focus:border-cyan-500 focus:outline-none"
            />
            <p className="mt-1 text-xs text-gray-600">Jira project where test tickets will be created</p>
          </div>

          <div>
            <label className="mb-1 block text-xs font-medium text-cyan-400">Parent Ticket (optional)</label>
            <input
              type="text"
              value={String(form.parent_ticket !== undefined ? form.parent_ticket : (cfg?.parent_ticket ?? ""))}
              onChange={(e) => setForm((prev) => ({ ...prev, parent_ticket: e.target.value }))}
              placeholder="OFS-20795"
              className="w-full rounded-lg border border-gray-700 bg-gray-800 px-3 py-2 text-sm text-gray-200 placeholder-gray-600 focus:border-cyan-500 focus:outline-none"
            />
            <p className="mt-1 text-xs text-gray-600">
              Campaigns are created directly under this issue
            </p>
          </div>

          <div>
            <label className="mb-1 block text-xs font-medium text-cyan-400">Standalone Tests Parent Ticket (optional)</label>
            <input
              type="text"
              value={String(form.parent_ticket_standalone !== undefined ? form.parent_ticket_standalone : (cfg?.parent_ticket_standalone ?? ""))}
              onChange={(e) => setForm((prev) => ({ ...prev, parent_ticket_standalone: e.target.value }))}
              placeholder="OFS-20798"
              className="w-full rounded-lg border border-gray-700 bg-gray-800 px-3 py-2 text-sm text-gray-200 placeholder-gray-600 focus:border-cyan-500 focus:outline-none"
            />
            <p className="mt-1 text-xs text-gray-600">
              Standalone tests (not in a campaign) are nested under this issue. Falls back to Campaign Parent if not set.
            </p>
          </div>
        </div>

        <div className="flex items-center pt-2">
          <button
            onClick={() => {
              if (Object.keys(form).length > 0) saveMut.mutate(form);
            }}
            disabled={saveMut.isPending || Object.keys(form).length === 0}
            className="flex items-center gap-2 rounded-lg bg-cyan-600 px-4 py-2 text-sm font-medium text-white hover:bg-cyan-500 disabled:opacity-50 transition-colors"
          >
            {saveMut.isPending ? (
              <Loader2 className="h-4 w-4 animate-spin" />
            ) : (
              <Save className="h-4 w-4" />
            )}
            Save Configuration
          </button>
        </div>

        {/* Test Jira connection */}
        <div className="mt-4 rounded-lg border border-gray-700 bg-gray-800/50 p-4 space-y-3">
          <p className="text-sm font-medium text-gray-300">Test Jira Connection</p>
          <div className="rounded-md bg-blue-900/20 border border-blue-800/50 px-3 py-2 text-xs text-blue-300">
            Uses your personal Jira API token (configured in the Profile tab)
          </div>
          <button
            onClick={() => {
              setTestResult(null);
              setTestError(null);
              testMut.mutate();
            }}
            disabled={testMut.isPending}
            className="flex items-center gap-2 rounded-lg border border-cyan-700 px-4 py-2 text-sm font-medium text-cyan-400 hover:bg-cyan-900/30 disabled:opacity-50 transition-colors"
          >
            {testMut.isPending ? (
              <Loader2 className="h-4 w-4 animate-spin" />
            ) : (
              <TestTube className="h-4 w-4" />
            )}
            Test Jira Connection
          </button>

          {testResult && (
            <div className="flex items-center gap-2 rounded-md bg-emerald-900/30 border border-emerald-800/50 px-3 py-2 text-sm text-emerald-300">
              <CheckCircle className="h-4 w-4 shrink-0" />
              Connected as: {testResult.connectedAs}
            </div>
          )}
          {testError && (
            <div className="flex items-center gap-2 rounded-md bg-red-900/30 border border-red-800/50 px-3 py-2 text-sm text-red-300">
              <XCircle className="h-4 w-4 shrink-0" />
              {testError}
            </div>
          )}
        </div>

      </div>
    </>
  );
}

// ---------------------------------------------------------------------------
// Main SettingsPage
// ---------------------------------------------------------------------------

type Tab = "profile" | "notifications" | "webhooks" | "email" | "jira";

export default function SettingsPage() {
  const { user } = useAuth();
  const role = user?.role ?? "viewer";
  const isAdmin = role === "admin";
  const isLead = ["admin", "red_lead", "blue_lead"].includes(role);

  const [activeTab, setActiveTab] = useState<Tab>("profile");

  const tabs: { id: Tab; label: string; icon: React.FC<{ className?: string }>; show: boolean }[] =
    [
      { id: "profile", label: "Profile", icon: User, show: true },
      { id: "notifications", label: "Notifications", icon: Bell, show: true },
      {
        id: "webhooks",
        label: "Webhooks",
        icon: Webhook,
        show: isLead,
      },
      { id: "email", label: "Email / SMTP", icon: Mail, show: isAdmin },
      { id: "jira", label: "Jira", icon: Link2, show: isAdmin },
    ];

  const visibleTabs = tabs.filter((t) => t.show);

  return (
    <div className="min-h-screen bg-gray-950 px-6 py-8">
      <div className="mx-auto max-w-4xl">
        {/* Header */}
        <div className="mb-8 flex items-center gap-3">
          <Settings className="h-7 w-7 text-cyan-400" />
          <div>
            <h1 className="text-2xl font-bold text-white">Settings</h1>
            <p className="text-sm text-gray-500">
              Manage your preferences, integrations, and system configuration
            </p>
          </div>
        </div>

        <div className="flex gap-6">
          {/* Sidebar tabs */}
          <nav className="w-44 shrink-0 space-y-1">
            {visibleTabs.map((tab) => (
              <button
                key={tab.id}
                onClick={() => setActiveTab(tab.id)}
                className={`flex w-full items-center gap-3 rounded-lg px-3 py-2.5 text-sm font-medium transition-colors ${
                  activeTab === tab.id
                    ? "bg-cyan-500/10 text-cyan-400"
                    : "text-gray-400 hover:bg-gray-800 hover:text-gray-200"
                }`}
              >
                <tab.icon className="h-4 w-4" />
                {tab.label}
              </button>
            ))}
          </nav>

          {/* Content */}
          <div className="flex-1">
            {activeTab === "profile" && (
              <Section title="Profile & Jira" icon={User}>
                <ProfileSection />
              </Section>
            )}
            {activeTab === "notifications" && (
              <Section title="Notification Preferences" icon={Bell}>
                <NotificationSection />
              </Section>
            )}
            {activeTab === "webhooks" && isLead && (
              <Section title="Webhook Configuration" icon={Webhook}>
                <WebhooksSection />
              </Section>
            )}
            {activeTab === "email" && isAdmin && (
              <Section title="Email / SMTP Configuration" icon={Mail}>
                <EmailSection />
              </Section>
            )}
            {activeTab === "jira" && isAdmin && (
              <Section title="Jira Integration" icon={Link2}>
                <JiraConfigSection />
              </Section>
            )}
          </div>
        </div>
      </div>
    </div>
  );
}
