import axios from "axios";

const TAG = "[Smartcar Webhook Subscribe]";

const DEFAULT_MANAGEMENT_BASE = "https://management.api.smartcar.com/v3";

/**
 * Subscribe a vehicle to a Dashboard webhook via Smartcar Management API.
 * @see https://smartcar.com/docs/api-reference/create-subscription
 * @see https://smartcar.com/docs/api-reference/webhooks/subscribe-webhook
 */
export function getApplicationManagementTokenFromEnv(): string | undefined {
  return (
    process.env.SMARTCAR_APPLICATION_MANAGEMENT_TOKEN?.trim() ||
    process.env.APPLICATION_MANAGEMENT_TOKEN?.trim()
  );
}

export function getDefaultWebhookIdFromEnv(): string | undefined {
  return process.env.SMARTCAR_WEBHOOK_ID?.trim();
}

function managementBaseUrl(): string {
  const raw = process.env.SMARTCAR_MANAGEMENT_API_URL?.trim();
  if (raw) return raw.replace(/\/+$/, "");
  return DEFAULT_MANAGEMENT_BASE;
}

export type SubscribeWebhookResult = {
  ok: boolean;
  status: number;
  body: unknown;
};

/**
 * POST /subscriptions — requires Application Management Token (Bearer).
 * Returns 202 when creation is accepted.
 */
export async function createWebhookSubscriptionViaManagementApi(opts: {
  applicationManagementToken: string;
  webhookId: string;
  smartcarUserId: string;
  smartcarVehicleId: string;
}): Promise<SubscribeWebhookResult> {
  const {
    applicationManagementToken,
    webhookId,
    smartcarUserId,
    smartcarVehicleId,
  } = opts;

  const url = `${managementBaseUrl()}/subscriptions`;
  const payload = {
    data: {
      type: "subscription",
      attributes: {
        webhookId,
        userId: smartcarUserId,
        vehicleId: smartcarVehicleId,
      },
    },
  };

  const commonHeaders = {
    Authorization: `Bearer ${applicationManagementToken}`,
  } as Record<string, string>;

  let res = await axios.post(url, payload, {
    headers: {
      ...commonHeaders,
      "Content-Type": "application/vnd.api+json",
      Accept: "application/vnd.api+json",
    },
    validateStatus: () => true,
    timeout: 30_000,
  });

  if (res.status === 401 || res.status === 415) {
    res = await axios.post(url, payload, {
      headers: {
        ...commonHeaders,
        "Content-Type": "application/json",
        Accept: "application/json",
      },
      validateStatus: () => true,
      timeout: 30_000,
    });
  }

  const ok = res.status >= 200 && res.status < 300;
  return { ok, status: res.status, body: res.data };
}

export async function subscribeVehiclesToDefaultWebhook(opts: {
  smartcarUserId: string;
  vehicles: Array<{ smartcarVehicleId?: string }>;
  webhookId?: string;
  applicationManagementToken?: string;
}): Promise<void> {
  const webhookId =
    opts.webhookId?.trim() || getDefaultWebhookIdFromEnv();
  const amt =
    opts.applicationManagementToken?.trim() ||
    getApplicationManagementTokenFromEnv();

  if (!webhookId || !amt) {
    console.info(
      `${TAG} Skipping subscription batch — set SMARTCAR_WEBHOOK_ID and APPLICATION_MANAGEMENT_TOKEN (or SMARTCAR_APPLICATION_MANAGEMENT_TOKEN).`
    );
    return;
  }

  const seen = new Set<string>();
  for (const v of opts.vehicles) {
    const vid = v.smartcarVehicleId?.trim();
    if (!vid || seen.has(vid)) continue;
    seen.add(vid);

    const result = await createWebhookSubscriptionViaManagementApi({
      applicationManagementToken: amt,
      webhookId,
      smartcarUserId: opts.smartcarUserId,
      smartcarVehicleId: vid,
    });

    if (result.ok || result.status === 409) {
      if (result.status === 409) {
        console.info(
          `${TAG} Already subscribed vehicleId=${vid} webhookId=${webhookId}`
        );
      } else {
        console.info(
          `${TAG} Subscribed vehicleId=${vid} webhookId=${webhookId} http=${result.status}`
        );
      }
    } else {
      console.warn(
        `${TAG} Subscribe failed vehicleId=${vid} http=${result.status}:`,
        result.body
      );
    }
  }
}
