import "server-only";

import { Query } from "node-appwrite";

import { createAdminClient } from "./server";
import { DATABASE_ID, TABLES } from "./schema";
import type { TenantContext } from "./tenant-guard";
import type { TenantPlan } from "./schema";
import {
  PLAN_LIMITS,
  PLAN_NAMES,
  RESOURCE_LABELS,
  type PlanResource,
} from "./plan-limits-shared";

export type { PlanResource } from "./plan-limits-shared";
export { PLAN_LIMIT_EXCEEDED, PLAN_LIMITS, PLAN_NAMES, RESOURCE_LABELS } from "./plan-limits-shared";

const INF = Number.POSITIVE_INFINITY;

export function getEffectivePlan(ctx: TenantContext): TenantPlan {
  const plan = (ctx.settings?.plan as TenantPlan | undefined) ?? "free";
  if (plan !== "free") {
    const expires = ctx.settings?.planExpiresAt;
    if (expires && new Date(expires).getTime() < Date.now()) return "free";
  }
  return plan;
}

async function countResource(tenantId: string, resource: PlanResource): Promise<number> {
  const { tablesDB, teams } = createAdminClient();

  if (resource === "members") {
    const result = await teams.listMemberships(tenantId);
    return result.total;
  }

  const tableMap: Record<Exclude<PlanResource, "members">, string> = {
    properties: TABLES.properties,
    customers: TABLES.customers,
    presentations: TABLES.presentations,
  };

  const queries = [Query.equal("tenantId", tenantId), Query.limit(1)];
  // Satılan/kiralanan ilanlar limite dahil değil — sadece aktif portföy sayılır
  if (resource === "properties") {
    queries.push(
      Query.or([
        Query.equal("status", "aktif"),
        Query.equal("status", "rezerve"),
        Query.equal("status", "pasif"),
      ]) as unknown as ReturnType<typeof Query.equal>,
    );
  }

  const result = await tablesDB.listRows({
    databaseId: DATABASE_ID,
    tableId: tableMap[resource],
    queries,
  });
  return result.total;
}

export type PlanUsage = {
  plan: TenantPlan;
  usage: Record<PlanResource, { used: number; limit: number; reached: boolean }>;
};

export async function getPlanUsage(ctx: TenantContext): Promise<PlanUsage> {
  const plan = getEffectivePlan(ctx);
  const limits = PLAN_LIMITS[plan];
  const resources: PlanResource[] = ["properties", "customers", "members", "presentations"];
  const counts = await Promise.all(resources.map((r) => countResource(ctx.tenantId, r)));

  const usage = {} as PlanUsage["usage"];
  resources.forEach((r, i) => {
    usage[r] = { used: counts[i], limit: limits[r], reached: counts[i] >= limits[r] };
  });
  return { plan, usage };
}

export class PlanLimitError extends Error {
  code = "PLAN_LIMIT_EXCEEDED";
  constructor(public resource: PlanResource, public limit: number) {
    super(`Plan limit reached for ${resource} (${limit})`);
  }
}

export async function requirePlanCapacity(ctx: TenantContext, resource: PlanResource): Promise<void> {
  const plan = getEffectivePlan(ctx);
  const limit = PLAN_LIMITS[plan][resource];
  if (limit === INF) return;
  const used = await countResource(ctx.tenantId, resource);
  if (used >= limit) throw new PlanLimitError(resource, limit);
}

export function isPlanLimitError(e: unknown): e is PlanLimitError {
  return e instanceof PlanLimitError;
}

export function planLimitMessage(resource: PlanResource, limit: number, plan?: TenantPlan): string {
  const planName = plan ? (PLAN_NAMES[plan] ?? "Mevcut") : "Mevcut";
  return `${planName} planda en fazla ${limit} ${RESOURCE_LABELS[resource]} ekleyebilirsiniz. Planınızı yükselterek devam edin.`;
}
