import "server-only";

import { cache } from "react";
import { cookies } from "next/headers";
import { Query } from "node-appwrite";

import { createAdminClient, getCurrentUser } from "./server";
import { DATABASE_ID, TABLES, type TenantSettings } from "./schema";
import { ACTIVE_TENANT_COOKIE } from "./tenant-types";
import { getActiveTenantId } from "./tenant";

function pickHighestRole(roles: string[]): "owner" | "admin" | "member" {
  if (roles.includes("owner")) return "owner";
  if (roles.includes("admin")) return "admin";
  return "member";
}

export type ActiveContext = {
  user: { id: string; name: string; email: string };
  tenantId: string;
  settings: TenantSettings | null;
  role: "owner" | "admin" | "member";
  memberCount: number;
};

async function setActiveTenantCookie(tenantId: string) {
  try {
    (await cookies()).set(ACTIVE_TENANT_COOKIE, tenantId, {
      path: "/",
      httpOnly: true,
      sameSite: "strict",
      secure: process.env.NODE_ENV === "production",
      maxAge: 60 * 60 * 24 * 365,
    });
  } catch { /* ignore in middleware context */ }
}

export const getActiveContext = cache(async function getActiveContext(): Promise<ActiveContext | null> {
  const user = await getCurrentUser();
  if (!user) return null;

  const { teams: adminTeams, users: adminUsers, tablesDB } = createAdminClient();

  let tenantId = await getActiveTenantId();

  // Validate cookie/prefs tenantId — team must exist and user must be a member.
  if (tenantId) {
    try {
      await adminTeams.get(tenantId); // throws if team was deleted
      const memberships = await adminTeams.listMemberships(tenantId);
      const isMember = memberships.memberships.some((m) => m.userId === user.$id);
      if (!isMember) {
        try { (await cookies()).delete(ACTIVE_TENANT_COOKIE); } catch { /* ignore */ }
        tenantId = null;
      }
    } catch {
      // Team deleted or inaccessible — clear stale pointer.
      try { (await cookies()).delete(ACTIVE_TENANT_COOKIE); } catch { /* ignore */ }
      tenantId = null;
    }
  }

  if (!tenantId) {
    try {
      const memberships = await adminUsers.listMemberships(user.$id);
      if (memberships.total > 0) {
        const teamIds = memberships.memberships.map((m) => m.teamId);
        const settings = await tablesDB.listRows({
          databaseId: DATABASE_ID,
          tableId: TABLES.tenantSettings,
          queries: [Query.equal("tenantId", teamIds), Query.limit(1)],
        });
        tenantId = (settings.rows[0] as unknown as { tenantId: string })?.tenantId ?? teamIds[0] ?? null;
      }
    } catch {
      // admin client failure is a server config issue — fall through to null
    }
    if (tenantId) await setActiveTenantCookie(tenantId);
  }

  if (!tenantId) return null;

  let settings: TenantSettings | null = null;
  let role: "owner" | "admin" | "member" = "member";
  let memberCount = 1;

  try {
    const [settingsResult, membershipsResult] = await Promise.all([
      tablesDB.listRows({
        databaseId: DATABASE_ID,
        tableId: TABLES.tenantSettings,
        queries: [Query.equal("tenantId", tenantId), Query.limit(1)],
      }),
      adminTeams.listMemberships(tenantId),
    ]);
    settings = (settingsResult.rows[0] as unknown as TenantSettings) ?? null;
    const myMembership = membershipsResult.memberships.find((m) => m.userId === user.$id);
    if (myMembership) role = pickHighestRole(myMembership.roles);
    memberCount = membershipsResult.memberships.filter((m) => m.confirm).length;
  } catch {
    settings = null;
  }

  return {
    user: { id: user.$id, name: user.name, email: user.email },
    tenantId,
    settings,
    role,
    memberCount,
  };
});
