import type { ActionDefinition } from "../../core/types.ts";

import { s } from "../../core/json-schema.ts";
import { defineProviderAction } from "../../core/provider-definition.ts";

const service = "pdf_co";

const outputNameSchema = s.nonEmptyString("Optional output file name generated by PDF.co.");
const expirationSchema = s.number(
  "Optional output link expiration time in minutes, subject to the account plan limits.",
);
const timeoutSchema = s.number("Optional PDF.co operation timeout in seconds.");
const profileSchema = s.looseObject("Advanced PDF.co profiles object forwarded to the endpoint as-is.");
const httpAuthSchema = {
  httpUsername: s.nonEmptyString("Optional HTTP username for protected source URLs."),
  httpPassword: s.nonEmptyString("Optional HTTP password for protected source URLs."),
};
const sourceUrlSchema = s.url("Publicly reachable source document URL.");
const transitFileSchema = s.object("A copy of a provider-generated file stored in local transit storage.", {
  fileId: s.nonEmptyString("The local transit file identifier."),
  downloadUrl: s.url("The local URL for downloading the transit file."),
  sizeBytes: s.number("The transit file size in bytes."),
  name: s.nonEmptyString("The transit file name."),
  mimeType: s.nonEmptyString("The transit file MIME type."),
});
const pdfResultSchema = s.object("Normalized PDF.co file-producing response.", {
  url: s.nullable(s.url("The generated output file URL returned by PDF.co.")),
  transitFile: s.nullable(transitFileSchema),
  body: s.nullable(s.unknown("Inline response body returned by PDF.co when inline mode is used.")),
  jobId: s.nullable(s.string("The PDF.co job identifier when returned.")),
  credits: s.nullable(s.number("The number of credits used by the operation when returned.")),
  remainingCredits: s.nullable(s.number("The number of remaining account credits after the operation when returned.")),
  duration: s.nullable(s.number("The operation duration in milliseconds when returned.")),
  status: s.nullable(s.string("The upstream PDF.co status string when returned.")),
  message: s.nullable(s.string("The upstream PDF.co message when returned.")),
  raw: s.looseObject("The raw PDF.co JSON response for fields not normalized by the connector."),
});
const htmlToPdfOptionsSchema = {
  name: outputNameSchema,
  margins: s.nonEmptyString("Custom PDF margins such as '10px 10px 10px 10px' or a single value such as '5mm'."),
  paperSize: s.nonEmptyString("Paper size such as Letter, A4, or a custom width and height."),
  orientation: s.stringEnum("PDF page orientation.", ["Portrait", "Landscape"]),
  printBackground: s.boolean("Whether background graphics should be printed into the PDF."),
  mediaType: s.stringEnum("CSS media type used while rendering the HTML or URL.", ["print", "screen"]),
  doNotWaitFullLoad: s.boolean("Whether PDF.co should skip waiting for full page load."),
  header: s.nonEmptyString("Optional HTML header inserted into the rendered PDF."),
  footer: s.nonEmptyString("Optional HTML footer inserted into the rendered PDF."),
  renderTimeout: s.number("Optional render timeout in milliseconds."),
  expiration: expirationSchema,
  profiles: profileSchema,
  customScript: s.nonEmptyString("Optional custom JavaScript executed during rendering."),
};
const sourceDocumentOptionsSchema = {
  name: outputNameSchema,
  password: s.nonEmptyString("Optional password for encrypted source PDF files."),
  timeout: timeoutSchema,
  expiration: expirationSchema,
  profiles: profileSchema,
  ...httpAuthSchema,
};

export type PdfCoActionName =
  | "get_account_balance"
  | "html_to_pdf"
  | "url_to_pdf"
  | "get_pdf_info"
  | "merge_pdfs"
  | "split_pdf"
  | "compress_pdf"
  | "pdf_to_text";

export const pdfCoActions: ActionDefinition[] = [
  defineProviderAction(service, {
    name: "get_account_balance",
    description: "Get the current PDF.co account credit balance for the API key.",
    requiredScopes: [],
    inputSchema: s.object("No input parameters are required for this action.", {}),
    outputSchema: s.object("Normalized PDF.co account balance response.", {
      credits: s.nullable(s.number("The account credit balance returned by PDF.co.")),
      status: s.nullable(s.string("The upstream PDF.co status string when returned.")),
      message: s.nullable(s.string("The upstream PDF.co message when returned.")),
      raw: s.looseObject("The raw PDF.co JSON response."),
    }),
  }),
  defineProviderAction(service, {
    name: "html_to_pdf",
    description: "Convert raw HTML into a PDF document and return the generated file URL.",
    requiredScopes: [],
    inputSchema: s.object(
      "Input parameters for converting raw HTML into a PDF document.",
      {
        html: s.nonEmptyString("The raw HTML markup to render as a PDF."),
        templateId: s.nonEmptyString("Optional PDF.co HTML template identifier."),
        templateData: s.looseObject("Optional data object used with a PDF.co HTML template."),
        ...htmlToPdfOptionsSchema,
      },
      {
        optional: [
          "templateId",
          "templateData",
          "name",
          "margins",
          "paperSize",
          "orientation",
          "printBackground",
          "mediaType",
          "doNotWaitFullLoad",
          "header",
          "footer",
          "renderTimeout",
          "expiration",
          "profiles",
          "customScript",
        ],
      },
    ),
    outputSchema: pdfResultSchema,
  }),
  defineProviderAction(service, {
    name: "url_to_pdf",
    description: "Convert a publicly reachable web page URL into a PDF document.",
    requiredScopes: [],
    inputSchema: s.object(
      "Input parameters for converting a web page URL into a PDF document.",
      {
        url: s.url("The publicly reachable web page URL to render."),
        ...htmlToPdfOptionsSchema,
        templateData: s.looseObject("Optional template data object forwarded to PDF.co."),
        ...httpAuthSchema,
      },
      {
        optional: [
          "name",
          "margins",
          "paperSize",
          "orientation",
          "printBackground",
          "mediaType",
          "doNotWaitFullLoad",
          "header",
          "footer",
          "renderTimeout",
          "expiration",
          "profiles",
          "customScript",
          "templateData",
          "httpUsername",
          "httpPassword",
        ],
      },
    ),
    outputSchema: pdfResultSchema,
  }),
  defineProviderAction(service, {
    name: "get_pdf_info",
    description: "Read metadata, page information, and security details from a PDF URL.",
    requiredScopes: [],
    inputSchema: s.object(
      "Input parameters for reading PDF metadata from a source URL.",
      {
        url: sourceUrlSchema,
        password: sourceDocumentOptionsSchema.password,
        timeout: timeoutSchema,
        expiration: expirationSchema,
        profiles: profileSchema,
        ...httpAuthSchema,
      },
      {
        optional: ["password", "timeout", "expiration", "profiles", "httpUsername", "httpPassword"],
      },
    ),
    outputSchema: s.object("Normalized PDF.co PDF info response.", {
      pageCount: s.nullable(s.number("The number of pages in the source PDF when returned.")),
      title: s.nullable(s.string("The PDF title metadata when returned.")),
      author: s.nullable(s.string("The PDF author metadata when returned.")),
      subject: s.nullable(s.string("The PDF subject metadata when returned.")),
      keywords: s.nullable(s.string("The PDF keyword metadata when returned.")),
      encrypted: s.nullable(s.boolean("Whether PDF.co reported the source PDF as encrypted.")),
      credits: s.nullable(s.number("The number of credits used by the operation when returned.")),
      remainingCredits: s.nullable(
        s.number("The number of remaining account credits after the operation when returned."),
      ),
      duration: s.nullable(s.number("The operation duration in milliseconds when returned.")),
      status: s.nullable(s.string("The upstream PDF.co status string when returned.")),
      message: s.nullable(s.string("The upstream PDF.co message when returned.")),
      raw: s.looseObject("The raw PDF.co JSON response for fields not normalized by the connector."),
    }),
  }),
  defineProviderAction(service, {
    name: "merge_pdfs",
    description: "Merge multiple PDF URLs into one PDF document.",
    requiredScopes: [],
    inputSchema: s.object(
      "Input parameters for merging multiple PDF URLs.",
      {
        urls: s.array("The source PDF URLs to merge in order.", sourceUrlSchema, { minItems: 2 }),
        name: outputNameSchema,
        timeout: timeoutSchema,
        expiration: expirationSchema,
        profiles: profileSchema,
        ...httpAuthSchema,
      },
      {
        optional: ["name", "timeout", "expiration", "profiles", "httpUsername", "httpPassword"],
      },
    ),
    outputSchema: pdfResultSchema,
  }),
  defineProviderAction(service, {
    name: "split_pdf",
    description: "Split a PDF URL into one or more output files by page numbers or ranges.",
    requiredScopes: [],
    inputSchema: s.object(
      "Input parameters for splitting a PDF by one-based page indexes or ranges.",
      {
        url: sourceUrlSchema,
        pages: s.nonEmptyString("One-based page indexes or ranges, such as '1,2,3-7' or '!1' for the last page."),
        inline: s.boolean("Whether PDF.co should return results inside the JSON response."),
        ...sourceDocumentOptionsSchema,
      },
      {
        optional: [
          "pages",
          "inline",
          "name",
          "password",
          "timeout",
          "expiration",
          "profiles",
          "httpUsername",
          "httpPassword",
        ],
      },
    ),
    outputSchema: pdfResultSchema,
  }),
  defineProviderAction(service, {
    name: "compress_pdf",
    description: "Compress a PDF URL and return the generated compressed PDF file URL.",
    requiredScopes: [],
    inputSchema: s.object(
      "Input parameters for compressing a PDF URL.",
      {
        url: sourceUrlSchema,
        name: outputNameSchema,
        config: s.looseObject("Optional PDF.co compression configuration object."),
      },
      { optional: ["name", "config"] },
    ),
    outputSchema: pdfResultSchema,
  }),
  defineProviderAction(service, {
    name: "pdf_to_text",
    description: "Convert a PDF URL to text and return either a file URL or inline text payload.",
    requiredScopes: [],
    inputSchema: s.object(
      "Input parameters for extracting text from a PDF URL.",
      {
        url: sourceUrlSchema,
        pages: s.nonEmptyString("Zero-based page indexes or ranges, such as '0,2,5-10'."),
        lang: s.nonEmptyString("OCR language code such as eng."),
        inline: s.boolean("Whether PDF.co should return extracted text inside the JSON response."),
        unwrap: s.boolean("Whether PDF.co should unwrap text lines."),
        lineGrouping: s.boolean("Whether PDF.co should group nearby text lines."),
        rect: s.nonEmptyString("Optional extraction rectangle in PDF.co coordinate format."),
        ...sourceDocumentOptionsSchema,
      },
      {
        optional: [
          "pages",
          "lang",
          "inline",
          "unwrap",
          "lineGrouping",
          "rect",
          "name",
          "password",
          "timeout",
          "expiration",
          "profiles",
          "httpUsername",
          "httpPassword",
        ],
      },
    ),
    outputSchema: pdfResultSchema,
  }),
];
