/* ========================================================================
   supabase-browser.jsx — optional Supabase persistence with local fallback
   ====================================================================== */

const BoltKitSupabase = (() => {
  let configPromise = null;
  let clientPromise = null;
  let lastStatus = { configured: false, reason: "Not checked yet" };

  const slug = (value) => String(value || "file")
    .toLowerCase()
    .replace(/[^a-z0-9._-]+/g, "-")
    .replace(/^-|-$/g, "") || "file";

  const safeJson = async (response) => {
    try { return await response.json(); }
    catch (e) { return {}; }
  };

  const postJson = async (url, payload) => {
    const response = await fetch(url, {
      method: "POST",
      headers: { "Content-Type": "application/json", Accept: "application/json" },
      body: JSON.stringify(payload || {})
    });
    const data = await safeJson(response);
    if (!response.ok) {
      return {
        ok: false,
        skipped: Boolean(data.skipped || response.status === 503),
        error: data.error || "Server persistence request failed"
      };
    }
    return data;
  };

  const fileToBase64 = (file) => new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = () => resolve(String(reader.result || "").split(",")[1] || "");
    reader.onerror = () => reject(reader.error || new Error("File read failed"));
    reader.readAsDataURL(file);
  });

  const getConfig = async () => {
    if (configPromise) return configPromise;
    configPromise = (async () => {
      const localUrl = localStorage.getItem("boltkit.supabaseUrl") || "";
      const localAnon = localStorage.getItem("boltkit.supabaseAnonKey") || "";
      let remote = {};
      try {
        const response = await fetch("/api/public-config", { headers: { Accept: "application/json" } });
        remote = await safeJson(response);
      } catch (e) {
        remote = {};
      }
      const supabase = remote.supabase || {};
      return {
        url: localUrl || supabase.url || "",
        anonKey: localAnon || supabase.anonKey || "",
        assetsBucket: supabase.assetsBucket || "boltkit-assets",
        instagramBucket: supabase.instagramBucket || "instagram-media"
      };
    })();
    return configPromise;
  };

  const getClient = async () => {
    if (clientPromise) return clientPromise;
    clientPromise = (async () => {
      const cfg = await getConfig();
      if (!cfg.url || !cfg.anonKey) {
        lastStatus = { configured: false, reason: "Supabase URL/anon key are not configured" };
        return null;
      }
      if (!window.supabase?.createClient) {
        lastStatus = { configured: false, reason: "Supabase browser client did not load" };
        return null;
      }
      lastStatus = { configured: true, reason: "Supabase configured" };
      return window.supabase.createClient(cfg.url, cfg.anonKey);
    })();
    return clientPromise;
  };

  const rowToProject = (row) => ({
    id: row.client_id || row.id,
    name: row.name,
    tagline: row.description || "",
    description: row.description || "",
    url: row.url || "",
    status: row.status || "draft",
    audience: row.target_audience || "",
    target_audience: row.target_audience || "",
    tone: row.tone_of_voice || "",
    tone_of_voice: row.tone_of_voice || "",
    feature_notes: row.feature_notes || "",
    summary: row.description || "",
    updated_at: row.updated_at,
    icon: { letter: String(row.name || "B").slice(0, 1).toUpperCase(), gradient: "linear-gradient(135deg, #EFFF00, #0B0B0B)" },
    statusVariant: row.status === "Ready" ? "green" : "blue",
    readiness: 60,
    missing: 0,
    lastPack: "Not generated yet",
    lastGen: "Never",
    packs: 0,
  });

  const projectToRow = (project) => ({
    client_id: String(project.id || `project-${Date.now()}`),
    name: project.name || "Untitled project",
    description: project.description || project.tagline || project.summary || "",
    url: project.url || "",
    status: project.status || "draft",
    target_audience: project.target_audience || project.audience || "",
    tone_of_voice: project.tone_of_voice || project.tone || "",
    feature_notes: Array.isArray(project.features) ? project.features.join("\n") : project.feature_notes || "",
    updated_at: new Date().toISOString()
  });

  const saveProject = async (project) => {
    const serverResult = await postJson("/api/supabase-projects", { action: "save", project });
    if (serverResult.ok || serverResult.skipped) return serverResult;
    const client = await getClient();
    if (!client) return { ok: false, skipped: true, error: lastStatus.reason };
    const { data, error } = await client
      .from("projects")
      .upsert(projectToRow(project), { onConflict: "client_id" })
      .select("*")
      .single();
    if (error) {
      const rlsLocked = String(error.message || "").toLowerCase().includes("row-level security");
      return {
        ok: false,
        skipped: rlsLocked,
        error: rlsLocked ? "Supabase secure mode is on. Add Auth or server persistence to sync projects." : error.message
      };
    }
    return { ok: true, project: rowToProject(data) };
  };

  const loadProjects = async () => {
    const serverResult = await postJson("/api/supabase-projects", { action: "load" });
    if (serverResult.ok || serverResult.skipped) return serverResult;
    const client = await getClient();
    if (!client) return { ok: false, skipped: true, error: lastStatus.reason, projects: [] };
    const { data, error } = await client
      .from("projects")
      .select("*")
      .order("updated_at", { ascending: false })
      .limit(50);
    if (error) {
      const rlsLocked = String(error.message || "").toLowerCase().includes("row-level security");
      return {
        ok: false,
        skipped: rlsLocked,
        error: rlsLocked ? "Supabase secure mode is on. Add Auth or server persistence to load projects." : error.message,
        projects: []
      };
    }
    return { ok: true, projects: (data || []).map(rowToProject) };
  };

  const uploadFile = async ({ file, bucket, folder = "uploads" }) => {
    if (!file) return { ok: false, skipped: true, error: "No file selected" };
    const cfg = await getConfig();
    const serverResult = await postJson("/api/supabase-upload", {
      bucket: bucket || cfg.assetsBucket,
      folder,
      fileName: file.name,
      mimeType: file.type || "application/octet-stream",
      base64: await fileToBase64(file)
    });
    if (serverResult.ok || serverResult.skipped) return serverResult;
    const client = await getClient();
    if (!client || !file) return { ok: false, skipped: true, error: lastStatus.reason };
    const targetBucket = bucket || cfg.assetsBucket;
    const path = `${folder}/${Date.now()}-${slug(file.name)}`;
    const { data, error } = await client.storage
      .from(targetBucket)
      .upload(path, file, { upsert: true, contentType: file.type || "application/octet-stream" });
    if (error) {
      const rlsLocked = String(error.message || "").toLowerCase().includes("row-level security");
      return {
        ok: false,
        skipped: rlsLocked,
        error: rlsLocked ? "Supabase Storage is connected, but write policies are locked until Auth/server uploads are added." : error.message
      };
    }
    const { data: publicUrl } = client.storage.from(targetBucket).getPublicUrl(data.path);
    return { ok: true, bucket: targetBucket, path: data.path, publicUrl: publicUrl?.publicUrl || "" };
  };

  const postToRow = (project, post, index = 0) => {
    const scheduled = new Date(`${post.date || new Date().toISOString().slice(0, 10)}T${post.time || "09:00"}:00`);
    return {
      client_id: String(post.id || `post-${Date.now()}-${index}`),
      project_client_id: String(project?.id || "local-project"),
      provider: "instagram",
      post_type: post.storyEnabled ? "feed_and_story" : "feed",
      title: post.title || "",
      caption: post.caption || "",
      hashtags: post.hashtags || "",
      first_comment: post.firstComment || "",
      media_url: post.remoteUrl || post.fileUrl || "",
      media_type: String(post.type || "image").toLowerCase(),
      scheduled_for: Number.isNaN(scheduled.getTime()) ? new Date().toISOString() : scheduled.toISOString(),
      timezone: Intl.DateTimeFormat().resolvedOptions().timeZone || "Europe/London",
      status: String(post.status || "draft").toLowerCase(),
      also_story: Boolean(post.storyEnabled),
      story_link: post.storyLink || "",
      updated_at: new Date().toISOString()
    };
  };

  const rowToPost = (row) => {
    const scheduled = row.scheduled_for ? new Date(row.scheduled_for) : new Date();
    const date = Number.isNaN(scheduled.getTime()) ? new Date() : scheduled;
    return {
      id: row.client_id || row.id,
      title: row.title || "Instagram post",
      topic: row.title || "",
      type: row.media_type === "reel" || row.media_type === "video" ? "Reel" : "Image",
      mediaName: row.media_url ? "Supabase media" : "No media yet",
      previewUrl: row.media_url || "",
      remoteUrl: row.media_url || "",
      caption: row.caption || "",
      hashtags: row.hashtags || "",
      cta: "",
      firstComment: row.first_comment || "",
      altText: "",
      date: date.toISOString().slice(0, 10),
      time: date.toTimeString().slice(0, 5),
      status: row.status ? row.status[0].toUpperCase() + row.status.slice(1) : "Draft",
      aiGoals: ["clicks", "likes", "viral_hook"],
      storyEnabled: Boolean(row.also_story),
      storyLink: row.story_link || "",
      storyStatus: row.also_story && row.status === "scheduled" ? "Scheduled" : "Draft",
    };
  };

  const saveScheduledPosts = async (project, posts) => {
    const serverResult = await postJson("/api/supabase-scheduled-posts", { action: "save", project, posts });
    if (serverResult.ok || serverResult.skipped) return serverResult;
    const client = await getClient();
    if (!client) return { ok: false, skipped: true, error: lastStatus.reason };
    const rows = (posts || []).map((post, index) => postToRow(project, post, index));
    if (!rows.length) return { ok: true, count: 0 };
    const { error } = await client
      .from("scheduled_social_posts")
      .upsert(rows, { onConflict: "client_id" });
    if (error) {
      const rlsLocked = String(error.message || "").toLowerCase().includes("row-level security");
      return {
        ok: false,
        skipped: rlsLocked,
        error: rlsLocked ? "Supabase secure mode is on. Add Auth or server persistence to sync scheduled posts." : error.message
      };
    }
    return { ok: true, count: rows.length };
  };

  const loadScheduledPosts = async (project) => {
    const serverResult = await postJson("/api/supabase-scheduled-posts", { action: "load", project, projectId: project?.id });
    if (serverResult.ok || serverResult.skipped) return serverResult;
    const client = await getClient();
    if (!client) return { ok: false, skipped: true, error: lastStatus.reason, posts: [] };
    const { data, error } = await client
      .from("scheduled_social_posts")
      .select("*")
      .eq("project_client_id", String(project?.id || "local-project"))
      .order("scheduled_for", { ascending: true })
      .limit(200);
    if (error) {
      const rlsLocked = String(error.message || "").toLowerCase().includes("row-level security");
      return {
        ok: false,
        skipped: rlsLocked,
        error: rlsLocked ? "Supabase secure mode is on. Add Auth or server persistence to load scheduled posts." : error.message,
        posts: []
      };
    }
    return { ok: true, posts: (data || []).map(rowToPost) };
  };

  return {
    getConfig,
    getClient,
    getStatus: () => lastStatus,
    loadProjects,
    saveProject,
    uploadFile,
    saveScheduledPosts,
    loadScheduledPosts
  };
})();

Object.assign(window, { BoltKitSupabase });
