// Delta Exchange authenticated proxy — signs REST requests with HMAC-SHA256
// and returns the caller's wallet balance + profile. Credentials arrive in
// the POST body; nothing is persisted server-side.
//
// Delta docs: https://docs.delta.exchange/#authentication
// Signature = HMAC_SHA256(secret, method + timestamp + path + query + body)
// Headers: api-key, signature, timestamp, User-Agent

import { createFileRoute } from "@tanstack/react-router";
import { createHmac } from "node:crypto";

const CORS = {
  "Access-Control-Allow-Origin": "*",
  "Access-Control-Allow-Methods": "POST, OPTIONS",
  "Access-Control-Allow-Headers": "Content-Type, Authorization",
} as const;

const BASES: Record<string, string> = {
  india: "https://api.india.delta.exchange",
  global: "https://api.delta.exchange",
};

function json(body: unknown, status = 200) {
  return new Response(JSON.stringify(body), {
    status,
    headers: { "Content-Type": "application/json", ...CORS },
  });
}

function sign(secret: string, payload: string) {
  return createHmac("sha256", secret).update(payload).digest("hex");
}

async function callDelta(base: string, key: string, secret: string, path: string) {
  const timestamp = Math.floor(Date.now() / 1000).toString();
  const method = "GET";
  const signature = sign(secret, method + timestamp + path);
  const res = await fetch(base + path, {
    method,
    headers: {
      "api-key": key,
      signature,
      timestamp,
      "User-Agent": "delta-terminal/1.0",
      Accept: "application/json",
    },
  });
  const text = await res.text();
  let body: unknown = null;
  try {
    body = JSON.parse(text);
  } catch {
    body = { raw: text };
  }
  return { ok: res.ok, status: res.status, body };
}

export const Route = createFileRoute("/api/delta/account")({
  server: {
    handlers: {
      OPTIONS: async () => new Response(null, { status: 204, headers: CORS }),

      POST: async ({ request }) => {
        let payload: { api_key?: string; api_secret?: string; region?: string };
        try {
          payload = await request.json();
        } catch {
          return json({ connected: false, error: "Invalid JSON body" }, 400);
        }

        const key = payload.api_key?.trim();
        const secret = payload.api_secret?.trim();
        const region = (payload.region ?? "india").toLowerCase();


        if (!key || !secret) {
          return json({ connected: false, error: "api_key and api_secret are required" }, 400);
        }

        // Try requested region first; if 401 and region wasn't explicit, try the other.
        const primaryRegion = region;
        const fallbackRegion = primaryRegion === "india" ? "global" : "india";
        const attempts: Array<{ region: string; status: number; code?: string }> = [];

        async function tryRegion(r: string) {
          const b = BASES[r] ?? BASES.india;
          const [profile, wallet] = await Promise.all([
            callDelta(b, key!, secret!, "/v2/profile"),
            callDelta(b, key!, secret!, "/v2/wallet/balances"),
          ]);
          const errBody = profile.body as { error?: { code?: string } } | null;
          attempts.push({ region: r, status: profile.status, code: errBody?.error?.code });
          return { profile, wallet, region: r, base: b };
        }

        try {
          let result = await tryRegion(primaryRegion);
          if (!result.profile.ok && result.profile.status === 401) {
            // Auto-try the other region — common cause of invalid_api_key
            result = await tryRegion(fallbackRegion);
          }

          const { profile, wallet, region: usedRegion } = result;

          if (!profile.ok) {
            const err = profile.body as { error?: { code?: string; context?: unknown }; message?: string };
            const code = err?.error?.code ?? "";
            const isAuth = profile.status === 401 || code === "invalid_api_key" || code === "unauthorized";
            return json(
              {
                connected: false,
                error: code || err?.message || `Delta rejected the request (${profile.status})`,
                hint: isAuth
                  ? "Delta rejected these credentials. Most common causes:\n" +
                    "1) IP whitelist on the API key — this request comes from a Lovable server IP, not yours. Remove IP restrictions on the key OR run the self-hosted backend.\n" +
                    "2) Wrong region — India keys only work with api.india.delta.exchange, Global keys only with api.delta.exchange.\n" +
                    "3) Key or secret has a stray space/newline."
                  : undefined,
                status: profile.status,
                attempts,
                key_prefix: key.slice(0, 4),
                key_suffix: key.slice(-4),
                key_length: key.length,
              },
              200,
            );
          }

          const prof = (profile.body as { result?: Record<string, unknown> }).result ?? {};
          const balances = ((wallet.body as { result?: Array<Record<string, unknown>> }).result ?? [])
            .map((b) => ({
              asset: String(b.asset_symbol ?? b.asset ?? ""),
              balance: Number(b.balance ?? 0),
              available: Number(b.available_balance ?? b.balance ?? 0),
            }))
            .filter((b) => b.asset);

          const usd = balances
            .filter((b) => /USD|USDT|USDC/i.test(b.asset))
            .reduce((s, b) => s + b.balance, 0);
          const primary = balances.find((b) => /USDT/i.test(b.asset)) ?? balances[0];

          return json({
            connected: true,
            account_id: String(prof.id ?? prof.user_id ?? ""),
            email: String(prof.email ?? ""),
            balance: usd || (primary?.balance ?? 0),
            currency: primary?.asset ?? "USDT",
            balances,
            permissions: Array.isArray(prof.permissions) ? prof.permissions : undefined,
            region: usedRegion,
            last_synced_at: new Date().toISOString(),
          });
        } catch (e) {
          return json(
            {
              connected: false,
              error: e instanceof Error ? e.message : String(e),
              hint: "Network error reaching Delta Exchange from the server.",
            },
            502,
          );
        }

      },
    },
  },
});
