import { AuditOutcome, SiteEnvironment, SiteStatus, SubscriptionStatus } from "@prisma/client";
import { db } from "@/lib/db";
import { validateSiteAgent } from "./client";

export type EnrollmentInput = {
  organizationId: string;
  actorUserId: string;
  name: string;
  url: string;
  token: string;
  environment: "Production" | "Staging" | "Development";
  notes?: string;
};

export type EnrolledSite = {
  id: string;
  name: string;
  url: string;
  environment: "Production" | "Staging" | "Development";
  status: "Connected" | "Needs attention" | "Disconnected" | "Paused";
  licenseActive?: boolean;
  licenseValidUntil?: Date | null;
  siteId?: string;
  pluginVersion?: string;
  capabilitiesUrl?: string;
  lastSeenAt: string;
  notes?: string;
};

const environmentToDb: Record<EnrollmentInput["environment"], SiteEnvironment> = {
  Production: SiteEnvironment.PRODUCTION,
  Staging: SiteEnvironment.STAGING,
  Development: SiteEnvironment.DEVELOPMENT,
};

const environmentFromDb: Record<SiteEnvironment, EnrolledSite["environment"]> = {
  PRODUCTION: "Production",
  STAGING: "Staging",
  DEVELOPMENT: "Development",
};

const statusFromDb: Record<SiteStatus, EnrolledSite["status"]> = {
  PENDING_ENROLLMENT: "Needs attention",
  CONNECTED: "Connected",
  NEEDS_ATTENTION: "Needs attention",
  DISCONNECTED: "Disconnected",
  PAUSED: "Paused",
  REMOVED: "Disconnected",
};

export function toEnrolledSite(site: {
  id: string;
  displayName: string;
  normalizedUrl: string;
  environment: SiteEnvironment;
  status: SiteStatus;
  licenseActive?: boolean;
  licenseValidUntil?: Date | null;
  pluginSiteId: string | null;
  pluginVersion: string | null;
  lastSeenAt: Date | null;
  notes: string | null;
}) : EnrolledSite {
  return {
    id: site.id,
    name: site.displayName,
    url: site.normalizedUrl,
    environment: environmentFromDb[site.environment],
    status: statusFromDb[site.status],
    licenseActive: Boolean(site.licenseActive && site.licenseValidUntil && site.licenseValidUntil > new Date()),
    siteId: site.pluginSiteId ?? undefined,
    pluginVersion: site.pluginVersion ?? undefined,
    capabilitiesUrl: site.pluginSiteId ? `${site.normalizedUrl}/wp-json/site-agent/v1/capabilities` : undefined,
    lastSeenAt: (site.lastSeenAt ?? new Date()).toLocaleString(),
    notes: site.notes ?? undefined,
  };
}

export async function enrollSite(input: EnrollmentInput): Promise<EnrolledSite> {
  // The raw plugin token is intentionally used only for this validation call.
  const validation = await validateSiteAgent(input.url, input.token);

  const subscription = await db.subscription.findUnique({
    where: { organizationId: input.organizationId },
    include: { plan: true },
  });
  const enrollableStatuses: SubscriptionStatus[] = [SubscriptionStatus.ACTIVE, SubscriptionStatus.TRIALING];
  if (!subscription || !enrollableStatuses.includes(subscription.status)) {
    throw new Error("An active WooCommerce subscription is required before enrolling a site.");
  }

  const result = await db.$transaction(async (tx) => {
    const existing = await tx.site.findUnique({ where: { normalizedUrl: validation.normalizedUrl } });
    if (existing) {
      if (existing.organizationId === input.organizationId) throw new Error("This site is already enrolled in this workspace.");
      throw new Error("This site is already enrolled by another workspace.");
    }

    const usedSites = await tx.site.count({
      where: { organizationId: input.organizationId, status: { not: SiteStatus.REMOVED } },
    });
    if (usedSites >= subscription.plan.siteLimit) {
      throw new Error(`Your ${subscription.plan.name} plan includes ${subscription.plan.siteLimit} site${subscription.plan.siteLimit === 1 ? "" : "s"}. Upgrade in WooCommerce to add another site.`);
    }

    const now = new Date();
    const site = await tx.site.create({
      data: {
        organizationId: input.organizationId,
        pluginSiteId: validation.siteId,
        displayName: input.name,
        normalizedUrl: validation.normalizedUrl,
        environment: environmentToDb[input.environment],
        status: SiteStatus.CONNECTED,
        pluginVersion: validation.pluginVersion,
        remoteAccessEnabled: true,
        licenseActive: subscription.status === SubscriptionStatus.ACTIVE,
        aiChatEntitled: subscription.plan.allowAiChat,
        lastSeenAt: now,
        notes: input.notes || null,
      },
    });
    await tx.auditEvent.create({
      data: {
        organizationId: input.organizationId,
        siteId: site.id,
        actorUserId: input.actorUserId,
        action: "Enrolled WordPress site",
        operationGroup: "enrollment",
        outcome: AuditOutcome.SUCCESS,
        riskLevel: "write",
        requestSummary: "Validated public HTTPS Site Agent access without retaining the submitted enrollment token.",
        details: { pluginSiteId: validation.siteId, pluginVersion: validation.pluginVersion ?? null },
      },
    });
    return site;
  });

  return toEnrolledSite(result);
}
