import type { ChangeEvent } from "react";
import {
  useStuffboxUpload,
  type UploadTransport,
} from "@stuffbox/sdk/react";

async function responseJson<T>(response: Response): Promise<T> {
  if (!response.ok) {
    throw new Error(`Upload endpoint failed with status ${response.status}`);
  }
  return response.json() as Promise<T>;
}

export const uploadTransport: UploadTransport = {
  async createUpload(input, options) {
    const response = await fetch("/api/stuffbox/uploads", {
      method: "POST",
      headers: { "content-type": "application/json" },
      body: JSON.stringify(input),
      ...(options?.signal ? { signal: options.signal } : {}),
    });
    return responseJson(response);
  },

  async completeUpload(uploadId, input, options) {
    const response = await fetch(`/api/stuffbox/uploads/${uploadId}/complete`, {
      method: "POST",
      headers: { "content-type": "application/json" },
      body: JSON.stringify(input ?? {}),
      ...(options?.signal ? { signal: options.signal } : {}),
    });
    return responseJson(response);
  },
};

export function StuffboxUploadButton() {
  const { state, upload, abort, reset } = useStuffboxUpload(uploadTransport);

  function chooseFile(event: ChangeEvent<HTMLInputElement>) {
    const file = event.currentTarget.files?.[0];
    if (file) void upload(file).catch(() => undefined);
  }

  return (
    <div>
      <input type="file" onChange={chooseFile} disabled={state.status === "uploading"} />

      {state.status === "uploading" && (
        <button type="button" onClick={abort}>
          Cancel upload ({Math.round(state.progress.percent)}%)
        </button>
      )}

      {state.status === "complete" && (
        <p>
          Uploaded <a href={state.asset.url}>{state.asset.filename}</a>{" "}
          <button type="button" onClick={reset}>Upload another</button>
        </p>
      )}

      {state.status === "error" && <p role="alert">{state.error.message}</p>}
    </div>
  );
}
