"use server";

import { ID, Permission, Query, Role } from "node-appwrite";

import { createAdminClient, createSessionClient } from "./server";
import { DATABASE_ID, TABLES } from "./schema";

export interface UserPrefs {
  theme?: "dark" | "light" | "system";
  colorTheme?: string;
  tweakcnTheme?: string;
  radius?: string;
  sidebarVariant?: "sidebar" | "floating" | "inset";
  sidebarCollapsible?: "offcanvas" | "icon" | "none";
  sidebarSide?: "left" | "right";
}

export async function getUserPrefs(): Promise<UserPrefs> {
  try {
    const { account } = await createSessionClient();
    const user = await account.get();
    const { tablesDB } = createAdminClient();

    const result = await tablesDB.listRows({
      databaseId: DATABASE_ID,
      tableId: TABLES.userPreferences,
      queries: [Query.equal("userId", user.$id), Query.limit(1)],
    });

    if (result.rows.length === 0) {
      // Pre-create an empty row so saveUserPrefsAction always calls updateRow
      // (createRow inside a Server Action causes router cache invalidation → remount loop)
      try {
        await tablesDB.createRow(
          DATABASE_ID,
          TABLES.userPreferences,
          ID.unique(),
          { userId: user.$id },
          [
            Permission.read(Role.user(user.$id)),
            Permission.update(Role.user(user.$id)),
            Permission.delete(Role.user(user.$id)),
          ],
        );
      } catch {
        // race condition or already exists — fine
      }
      return {};
    }

    const row = result.rows[0] as Record<string, unknown>;
    const str = (v: unknown) => (v && typeof v === "string" ? v : undefined);
    return {
      theme: (row.theme as UserPrefs["theme"]) ?? undefined,
      colorTheme: str(row.colorTheme),
      tweakcnTheme: str(row.tweakcnTheme),
      radius: str(row.radius),
      sidebarVariant: (row.sidebarVariant as UserPrefs["sidebarVariant"]) ?? undefined,
      sidebarCollapsible: (row.sidebarCollapsible as UserPrefs["sidebarCollapsible"]) ?? undefined,
      sidebarSide: (row.sidebarSide as UserPrefs["sidebarSide"]) ?? undefined,
    };
  } catch {
    return {};
  }
}

export async function saveUserPrefsAction(
  update: Partial<UserPrefs>,
): Promise<{ ok: boolean; error?: string }> {
  try {
    const { account } = await createSessionClient();
    const user = await account.get();
    const { tablesDB } = createAdminClient();

    // undefined → skip, "" → null (Appwrite rejects empty strings on nullable attrs)
    const clean: Record<string, unknown> = {};
    for (const [k, v] of Object.entries(update)) {
      if (v === undefined) continue;
      clean[k] = v === "" ? null : v;
    }
    if (Object.keys(clean).length === 0) return { ok: true };

    const existing = await tablesDB.listRows({
      databaseId: DATABASE_ID,
      tableId: TABLES.userPreferences,
      queries: [Query.equal("userId", user.$id), Query.limit(1)],
    });

    const perms = [
      Permission.read(Role.user(user.$id)),
      Permission.update(Role.user(user.$id)),
      Permission.delete(Role.user(user.$id)),
    ];

    if (existing.rows.length === 0) {
      await tablesDB.createRow(
        DATABASE_ID,
        TABLES.userPreferences,
        ID.unique(),
        { userId: user.$id, ...clean },
        perms,
      );
    } else {
      await tablesDB.updateRow(
        DATABASE_ID,
        TABLES.userPreferences,
        existing.rows[0].$id,
        clean,
      );
    }

    return { ok: true };
  } catch (err) {
    const msg = err instanceof Error ? err.message : String(err);
    console.error("[saveUserPrefsAction]", msg);
    return { ok: false, error: msg };
  }
}
