/**
 * Vercel adapter — inline-files deployment via the Vercel API.
 * Auth: access token (connection secret). Optional teamId on the connection.
 * Uploads the standalone bundle as an inline base64 file set to a production deployment.
 * Note: inline uploads suit typical landing pages; very large image sets may exceed
 * Vercel's inline request size, in which case the deploy fails with a clear message.
 */

import fs from 'fs';
import { HostingAdapter, DeployInput, DeployResult } from './types';

const API = 'https://api.vercel.com';

async function vfetch(token: string, pathname: string, init: RequestInit = {}): Promise<any> {
  const res = await fetch(`${API}${pathname}`, {
    ...init,
    headers: { Authorization: `Bearer ${token}`, ...(init.headers || {}) },
  });
  const text = await res.text();
  let body: any = null;
  try { body = text ? JSON.parse(text) : null; } catch { body = text; }
  if (!res.ok) {
    const msg = (body && body.error && (body.error.message || body.error.code)) || (body && body.message) || `Vercel API ${res.status}`;
    const err: any = new Error(msg);
    err.status = res.status;
    throw err;
  }
  return body;
}

function projectName(page: any): string {
  const raw = (page?.slug || page?.name || 'landing-page').toString().toLowerCase();
  const cleaned = raw.replace(/[^a-z0-9-]/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '').slice(0, 52);
  return cleaned || 'landing-page';
}

export const vercelAdapter: HostingAdapter = {
  provider: 'vercel',

  async validate(_connection, secret) {
    try {
      await vfetch(secret, '/v2/user');
      return { ok: true };
    } catch (err: any) {
      return { ok: false, error: err?.message || 'Invalid Vercel token' };
    }
  },

  async deploy({ bundle, page, connection, secret }: DeployInput): Promise<DeployResult> {
    const token = secret;
    const teamQuery = connection.teamId ? `?teamId=${encodeURIComponent(connection.teamId)}` : '';

    const files = await Promise.all(bundle.files.map(async (f) => ({
      file: f.relPath,
      data: (await fs.promises.readFile(f.absPath)).toString('base64'),
      encoding: 'base64' as const,
    })));

    const deployment = await vfetch(token, `/v13/deployments${teamQuery}`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        name: connection.siteId || projectName(page),
        files,
        projectSettings: { framework: null },
        target: 'production',
      }),
    });

    const host = (Array.isArray(deployment.alias) && deployment.alias[0]) || deployment.url;
    return {
      deployUrl: host ? `https://${host}` : '',
      providerDeployId: deployment.id,
      ...(connection.siteId ? {} : { connectionPatch: { siteId: connection.siteId || projectName(page) } }),
    };
  },
};
