/**
 * Netlify adapter — zip deploy via the Netlify API.
 * Auth: personal access token (stored as the connection secret).
 * Creates a site on first deploy (persisted back via connectionPatch), then deploys
 * the standalone bundle as a zip. Netlify provides the live HTTPS URL + free SSL.
 */

import { HostingAdapter, DeployInput, DeployResult, zipBundleToBuffer } from './types';

const API = 'https://api.netlify.com/api/v1';

async function nfetch(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.message || body.error)) || `Netlify API ${res.status}`;
    const err: any = new Error(msg);
    err.status = res.status;
    throw err;
  }
  return body;
}

export const netlifyAdapter: HostingAdapter = {
  provider: 'netlify',

  async validate(_connection, secret) {
    try {
      await nfetch(secret, '/sites?per_page=1');
      return { ok: true };
    } catch (err: any) {
      return { ok: false, error: err?.message || 'Invalid Netlify token' };
    }
  },

  async deploy({ bundle, connection, secret, customDomain }: DeployInput): Promise<DeployResult> {
    const token = secret;
    let siteId = connection.siteId;
    const connectionPatch: Record<string, any> = {};

    // Create the site on first deploy.
    if (!siteId) {
      const site = await nfetch(token, '/sites', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({}),
      });
      siteId = site.id || site.site_id;
      connectionPatch.siteId = siteId;
    }

    // Attach a custom domain if requested.
    if (customDomain) {
      try {
        await nfetch(token, `/sites/${siteId}`, {
          method: 'PATCH',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ custom_domain: customDomain }),
        });
      } catch { /* non-fatal — deploy still proceeds */ }
    }

    // Zip deploy.
    const zip = await zipBundleToBuffer(bundle.files);
    const deploy = await nfetch(token, `/sites/${siteId}/deploys`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/zip' },
      body: zip,
    });

    const deployUrl = (customDomain ? `https://${customDomain}` : '') || deploy.ssl_url || deploy.deploy_ssl_url || deploy.url || deploy.deploy_url;
    return {
      deployUrl,
      providerDeployId: deploy.id,
      ...(Object.keys(connectionPatch).length ? { connectionPatch } : {}),
    };
  },
};
