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

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

const service = "satismeter";

const rfc3339DateTime = s.dateTime("ISO 8601 timestamp with timezone information.");
const pageSizeField = s.integer("Maximum number of results to return on each page.", { minimum: 1, maximum: 100 });
const pageCursorField = s.string("Cursor returned by a previous SatisMeter response page.", { minLength: 1 });
const projectIdField = s.string("SatisMeter project ID.", { minLength: 1 });
const campaignIdField = s.string("SatisMeter survey ID.", { minLength: 1 });
const questionTypeSchema = s.stringEnum("Question type returned by SatisMeter.", [
  "scale",
  "smiley",
  "long-text",
  "single-choice",
  "multiple-choice",
]);
const metricTypeSchema = s.stringEnum("Metric type returned by SatisMeter.", ["nps", "ces", "csat", "pmf"]);
const unknownRecordSchema = s.record(
  "User traits captured when the response was recorded.",
  s.unknown("A trait value."),
);

const projectSchema = s.looseObject("SatisMeter project.", {
  id: s.string("Project ID."),
  name: s.string("Project name."),
});

const surveySchema = s.looseObject("SatisMeter survey.", {
  id: s.string("Survey ID."),
  name: s.string("Survey name."),
  type: s.stringEnum("Survey template type returned by SatisMeter.", ["nps", "ces", "csat", "pmf", "custom"]),
  state: s.stringEnum("Survey state returned by SatisMeter.", ["live", "paused", "draft"]),
});

const answerSchema = s.looseObject("SatisMeter response answer.", {
  id: s.string("Answered question ID."),
  label: s.string("Question label displayed to the user."),
  value: s.anyOf("Answer value returned by SatisMeter.", [
    s.string("String answer value."),
    s.integer("Numeric answer value."),
    s.array("Multiple selected values.", s.string("Selected option value.")),
  ]),
  type: s.nullable(questionTypeSchema),
  metric: s.nullable(metricTypeSchema),
});

const countrySchema = s.looseObject("Country information returned by SatisMeter.", {
  code: s.nullableString("ISO 3166 country code."),
  name: s.nullableString("Country name."),
});

const regionSchema = s.looseObject("Region information returned by SatisMeter.", {
  code: s.nullableString("ISO 3166 region code."),
  name: s.nullableString("Region name."),
});

const locationSchema = s.looseObject("Location information returned by SatisMeter.", {
  country: s.nullable(countrySchema),
  region: s.nullable(regionSchema),
  city: s.nullableString("City derived from the response IP."),
});

const deviceSchema = s.looseObject("Device information returned by SatisMeter.", {
  type: s.stringEnum("Type of the device used by the respondent.", ["phone", "tablet", "desktop"]),
  os: s.string("Operating system used by the respondent."),
});

const responseUserSchema = s.looseObject("Responding user returned by SatisMeter.", {
  id: s.string("Internal user ID assigned by SatisMeter."),
  deleted: s.boolean("Whether the referenced user has been deleted."),
  userId: s.nullableString("External user ID stored on the response."),
  anonymousId: s.nullableString("Anonymous ID generated by SatisMeter when userId is unavailable."),
  traits: unknownRecordSchema,
});

const responseSchema = s.looseObject("SatisMeter response.", {
  id: s.string("Response ID."),
  project: s.string("Project ID associated with the response."),
  campaign: s.string("Survey ID associated with the response."),
  answers: s.array("Answers left in the response.", answerSchema),
  created: rfc3339DateTime,
  user: responseUserSchema,
  ip: s.nullableString("IP address of the respondent."),
  location: locationSchema,
  referrer: s.nullableString("Page URL where the response was created."),
  method: s.stringEnum("Delivery method used for the survey.", ["In-app", "Form", "Mobile", "Reminder", "Email"]),
  language: s.nullableString("ISO 639-1 language code."),
  device: deviceSchema,
});

const pageSchema = s.object(
  "Cursor pagination metadata returned by SatisMeter.",
  {
    nextPageCursor: s.nullableString("Cursor for the next page, or null when there are no more pages."),
    hasNextPage: s.boolean("Whether there are more response pages to fetch."),
    size: s.integer("Maximum number of results requested per page."),
  },
  { optional: ["nextPageCursor", "hasNextPage", "size"] },
);

const questionValueStatisticsSchema = s.object("Aggregated count for one possible question value.", {
  value: s.anyOf("Possible answer value.", [
    s.string("Possible answer value represented as a string."),
    s.integer("Possible answer value represented as an integer."),
  ]),
  answers: s.integer("Number of answers with this value."),
});

const questionMetricSchema = s.object("Metric statistics associated with a question.", {
  type: metricTypeSchema,
  value: s.integer("Calculated metric value."),
});

const questionStatisticsSchema = s.object("Per-question SatisMeter statistics.", {
  id: s.string("Question ID."),
  label: s.string("Question label in the survey default language."),
  type: questionTypeSchema,
  statistics: s.object("Aggregated statistics for the question.", {
    answers: s.integer("Number of responses that answered this question."),
    values: s.nullable(
      s.array("Per-value answer counts, or null for long-text questions.", questionValueStatisticsSchema),
    ),
    metric: s.nullable(questionMetricSchema),
  }),
});

const surveyStatisticsSchema = s.object("Survey statistics returned by SatisMeter.", {
  statistics: s.object(
    "Top-level survey response statistics.",
    {
      responses: s.integer("Total number of responses."),
      displays: s.integer("Total number of survey displays."),
      responseRate: s.number("Ratio of responses over displays in the selected time range."),
    },
    { optional: ["responses", "displays", "responseRate"] },
  ),
  questions: s.array("Per-question statistics for the selected survey.", questionStatisticsSchema),
});

const getProjectInputSchema = s.object("The input payload for retrieving a SatisMeter project.", {
  projectId: projectIdField,
});
const listSurveysInputSchema = s.object("The input payload for listing SatisMeter surveys.", {
  projectId: projectIdField,
});
const getSurveyInputSchema = s.object("The input payload for retrieving a SatisMeter survey.", {
  projectId: projectIdField,
  campaignId: campaignIdField,
});
const responseListFields = {
  projectId: projectIdField,
  startDate: rfc3339DateTime,
  endDate: rfc3339DateTime,
  pageCursor: pageCursorField,
  pageSize: pageSizeField,
};
const listProjectResponsesInputSchema = s.object(
  "The input payload for listing project-level SatisMeter responses.",
  responseListFields,
  { optional: ["startDate", "endDate", "pageCursor", "pageSize"] },
);
const listSurveyResponsesInputSchema = s.object(
  "The input payload for listing survey-level SatisMeter responses.",
  {
    ...responseListFields,
    campaignId: campaignIdField,
  },
  { optional: ["startDate", "endDate", "pageCursor", "pageSize"] },
);
const getSurveyStatisticsInputSchema = s.object(
  "The input payload for retrieving SatisMeter survey statistics.",
  {
    projectId: projectIdField,
    campaignId: campaignIdField,
    startDate: rfc3339DateTime,
    endDate: rfc3339DateTime,
  },
  { optional: ["startDate", "endDate"] },
);

export type SatismeterActionName =
  | "get_project"
  | "list_surveys"
  | "get_survey"
  | "list_project_responses"
  | "list_survey_responses"
  | "get_survey_statistics";

export const satismeterActions: ActionDefinition[] = [
  defineProviderAction(service, {
    name: "get_project",
    description: "Retrieve a SatisMeter project by ID.",
    inputSchema: getProjectInputSchema,
    outputSchema: s.object("The output payload for retrieving a SatisMeter project.", {
      project: projectSchema,
    }),
  }),
  defineProviderAction(service, {
    name: "list_surveys",
    description: "List surveys configured in a SatisMeter project.",
    inputSchema: listSurveysInputSchema,
    outputSchema: s.object("The output payload for listing SatisMeter surveys.", {
      surveys: s.array("Surveys returned by SatisMeter.", surveySchema),
    }),
  }),
  defineProviderAction(service, {
    name: "get_survey",
    description: "Retrieve a SatisMeter survey by ID.",
    inputSchema: getSurveyInputSchema,
    outputSchema: s.object("The output payload for retrieving a SatisMeter survey.", {
      survey: surveySchema,
    }),
  }),
  defineProviderAction(service, {
    name: "list_project_responses",
    description: "List responses recorded across all surveys in a SatisMeter project.",
    inputSchema: listProjectResponsesInputSchema,
    outputSchema: s.object("The output payload for listing project-level SatisMeter responses.", {
      responses: s.array("Responses returned by SatisMeter.", responseSchema),
      page: pageSchema,
    }),
  }),
  defineProviderAction(service, {
    name: "list_survey_responses",
    description: "List responses recorded for one SatisMeter survey.",
    inputSchema: listSurveyResponsesInputSchema,
    outputSchema: s.object("The output payload for listing survey-level SatisMeter responses.", {
      responses: s.array("Responses returned by SatisMeter.", responseSchema),
      page: pageSchema,
    }),
  }),
  defineProviderAction(service, {
    name: "get_survey_statistics",
    description: "Retrieve aggregated statistics for one SatisMeter survey.",
    inputSchema: getSurveyStatisticsInputSchema,
    outputSchema: s.object("The output payload for retrieving SatisMeter survey statistics.", {
      statistics: surveyStatisticsSchema,
    }),
  }),
];
