import crypto from "node:crypto";
import os from "node:os";
import path from "node:path";

function hash(value) {
  return crypto.createHash("sha256").update(value || "unknown").digest("base64url");
}

function projectContext(session) {
  const raw = session.cwd || session.sourcePath || "unknown-project";
  const displayName =
    session.projectName ||
    (session.cwd ? path.basename(session.cwd) : "") ||
    "Unknown project";
  return {
    key: hash(raw).slice(0, 32),
    displayName,
    pathHash: hash(raw)
  };
}

export function defaultDevice() {
  return {
    name: os.hostname() || "Local machine",
    platform: `${os.platform()} ${os.arch()}`
  };
}

export function buildIngestPayload(summary, device) {
  const aggregateDaily = (summary.contributionDays || summary.byDay || []).map((day) => ({
    date: day.date,
    projectKey: "all-projects",
    tool: "all",
    provider: "mixed",
    model: "mixed",
    totalTokens: day.totalTokens || 0,
    inputTokens: day.inputTokens || 0,
    outputTokens: day.outputTokens || 0,
    cacheReadTokens: day.cacheReadTokens || 0,
    cacheCreationTokens: day.cacheCreationTokens || 0,
    reasoningTokens: day.reasoningTokens || 0,
    costUsd: day.costUsd || 0,
    events: day.events || 0
  }));
  const modelDaily = (summary.modelContributionDays || []).map((day) => ({
    date: day.date,
    projectKey: "all-projects",
    tool: day.tool || "unknown",
    provider: day.provider || "unknown",
    model: day.model || "unknown",
    totalTokens: day.totalTokens || 0,
    inputTokens: day.inputTokens || 0,
    outputTokens: day.outputTokens || 0,
    cacheReadTokens: day.cacheReadTokens || 0,
    cacheCreationTokens: day.cacheCreationTokens || 0,
    reasoningTokens: day.reasoningTokens || 0,
    costUsd: day.costUsd || 0,
    events: day.events || 0
  }));

  return {
    schemaVersion: 1,
    generatedAt: summary.generatedAt,
    device,
    sessions: (summary.sessions || []).map((session) => ({
      sessionKey: hash(`${session.tool}:${session.id}`),
      tool: session.tool || "unknown",
      provider: session.provider || "unknown",
      model: session.model || "unknown",
      project: projectContext(session),
      firstSeenAt: session.firstSeen,
      lastSeenAt: session.lastSeen,
      totalTokens: session.totalTokens || 0,
      inputTokens: session.inputTokens || 0,
      outputTokens: session.outputTokens || 0,
      cacheReadTokens: session.cacheReadTokens || 0,
      cacheCreationTokens: session.cacheCreationTokens || 0,
      reasoningTokens: session.reasoningTokens || 0,
      costUsd: session.costUsd || 0,
      events: session.events || 0
    })),
    daily: [...aggregateDaily, ...modelDaily],
    hourly: (summary.byHour || [])
      .filter((hour) => (hour.totalTokens || 0) > 0 || (hour.costUsd || 0) > 0 || (hour.events || 0) > 0)
      .map((hour) => ({
        hour: hour.hour,
        projectKey: "all-projects",
        tool: "all",
        provider: "mixed",
        model: "mixed",
        totalTokens: hour.totalTokens || 0,
        costUsd: hour.costUsd || 0,
        events: hour.events || 0
      }))
  };
}

export async function postIngest(apiUrl, token, payload) {
  const response = await fetch(`${apiUrl.replace(/\/$/, "")}/api/ingest`, {
    method: "POST",
    headers: {
      authorization: `Bearer ${token}`,
      "content-type": "application/json"
    },
    body: JSON.stringify(payload)
  });

  if (!response.ok) {
    const text = await response.text();
    const error = new Error(`Sync failed: ${response.status} ${text}`);
    error.status = response.status;
    throw error;
  }

  return response.json();
}
