import type { RuntimeEnvironment, TaskRun, WorkerDeployment } from "@trigger.dev/database";
import { z } from "zod";
import { type TaskRunListSearchFilters } from "~/components/runs/v3/RunFilters";
import type { Organization } from "~/models/organization.server";
import type { Project } from "~/models/project.server";
import { RUNS_BULK_INSPECTOR_OPEN_VALUE } from "~/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs._index/shouldRevalidateRunsList";
import { objectToSearchParams } from "./searchParams";
import { type WaitpointSearchParams } from "~/components/runs/v3/WaitpointTokenFilters";
export type OrgForPath = Pick<Organization, "slug">;
export type ProjectForPath = Pick<Project, "slug">;
export type EnvironmentForPath = Pick<RuntimeEnvironment, "slug">;
export type v3RunForPath = Pick<TaskRun, "friendlyId">;
export type v3SpanForPath = Pick<TaskRun, "spanId">;
export type DeploymentForPath = Pick<WorkerDeployment, "shortCode">;
export type TaskForPath = {
  taskIdentifier: string;
};

export const OrganizationParamsSchema = z.object({
  organizationSlug: z.string(),
});

export const ProjectParamSchema = OrganizationParamsSchema.extend({
  projectParam: z.string(),
});

export const EnvironmentParamSchema = ProjectParamSchema.extend({
  envParam: z.string(),
});

//v3
export const v3TaskParamsSchema = EnvironmentParamSchema.extend({
  taskParam: z.string(),
});

export const v3RunParamsSchema = EnvironmentParamSchema.extend({
  runParam: z.string(),
});

export const v3SpanParamsSchema = v3RunParamsSchema.extend({
  spanParam: z.string(),
});

export const v3RunStreamParamsSchema = v3RunParamsSchema.extend({
  streamKey: z.string(),
});

export const v3DeploymentParams = EnvironmentParamSchema.extend({
  deploymentParam: z.string(),
});

export const v3ScheduleParams = EnvironmentParamSchema.extend({
  scheduleParam: z.string(),
});

export function rootPath() {
  return `/`;
}

/** Given a path, it makes it an impersonation path */
export function impersonate(path: string) {
  return `/@${path}`;
}

export function accountPath() {
  return `/account`;
}

export function personalAccessTokensPath() {
  return `/account/tokens`;
}

export function accountSecurityPath() {
  return `/account/security`;
}

export function invitesPath() {
  return `/invites`;
}

export function confirmBasicDetailsPath() {
  return `/confirm-basic-details`;
}

export function acceptInvitePath(token: string) {
  return `/invite-accept?token=${token}`;
}

export function resendInvitePath() {
  return `/invite-resend`;
}

export function logoutPath() {
  return `/logout`;
}

export function revokeInvitePath() {
  return `/invite-revoke`;
}

// Org
export function organizationPath(organization: OrgForPath) {
  return `/orgs/${organizationParam(organization)}`;
}

export function newOrganizationPath() {
  return `/orgs/new`;
}

export function selectPlanPath(organization: OrgForPath) {
  return `${organizationPath(organization)}/select-plan`;
}

export function organizationTeamPath(organization: OrgForPath) {
  return `${organizationPath(organization)}/settings/team`;
}

export function organizationRolesPath(organization: OrgForPath) {
  return `${organizationPath(organization)}/settings/roles`;
}

export function organizationSsoPath(organization: OrgForPath) {
  return `${organizationPath(organization)}/settings/sso`;
}

export function inviteTeamMemberPath(organization: OrgForPath) {
  return `${organizationPath(organization)}/invite`;
}

export function organizationBillingPath(organization: OrgForPath) {
  return `${organizationPath(organization)}/billing`;
}

export function organizationSettingsPath(organization: OrgForPath) {
  return `${organizationPath(organization)}/settings`;
}

export function organizationIntegrationsPath(organization: OrgForPath) {
  return `${organizationPath(organization)}/settings/integrations`;
}

export function organizationVercelIntegrationPath(organization: OrgForPath) {
  return `${organizationIntegrationsPath(organization)}/vercel`;
}

export function organizationSlackIntegrationPath(organization: OrgForPath) {
  return `${organizationIntegrationsPath(organization)}/slack`;
}

function organizationParam(organization: OrgForPath) {
  return organization.slug;
}

// Project
export function newProjectPath(organization: OrgForPath, message?: string) {
  return `${organizationPath(organization)}/projects/new${
    message ? `?message=${encodeURIComponent(message)}` : ""
  }`;
}

function projectParam(project: ProjectForPath) {
  return project.slug;
}

function environmentParam(environment: EnvironmentForPath) {
  return environment.slug;
}

//v3 project
export function v3ProjectPath(organization: OrgForPath, project: ProjectForPath) {
  return `/orgs/${organizationParam(organization)}/projects/${projectParam(project)}`;
}

export function githubAppInstallPath(organizationSlug: string, redirectTo: string) {
  return `/github/install?org_slug=${organizationSlug}&redirect_to=${encodeURIComponent(
    redirectTo
  )}`;
}

export function vercelAppInstallPath(organizationSlug: string, projectSlug: string) {
  return `/vercel/install?org_slug=${organizationSlug}&project_slug=${projectSlug}`;
}

export function vercelCallbackPath() {
  return `/vercel/callback`;
}

export function vercelResourcePath(
  organizationSlug: string,
  projectSlug: string,
  environmentSlug: string
) {
  return `/resources/orgs/${organizationSlug}/projects/${projectSlug}/env/${environmentSlug}/vercel`;
}

export function v3EnvironmentPath(
  organization: OrgForPath,
  project: ProjectForPath,
  environment: EnvironmentForPath
) {
  return `/orgs/${organizationParam(organization)}/projects/${projectParam(
    project
  )}/env/${environmentParam(environment)}`;
}

export function v3TasksDashboardPath(
  organization: OrgForPath,
  project: ProjectForPath,
  environment: EnvironmentForPath
) {
  return `${v3EnvironmentPath(organization, project, environment)}/tasks/dashboard`;
}

export function v3TasksStreamingPath(
  organization: OrgForPath,
  project: ProjectForPath,
  environment: EnvironmentForPath
) {
  return `${v3EnvironmentPath(organization, project, environment)}/tasks/stream`;
}

export function v3ApiKeysPath(
  organization: OrgForPath,
  project: ProjectForPath,
  environment: EnvironmentForPath
) {
  return `${v3EnvironmentPath(organization, project, environment)}/apikeys`;
}

export function v3BulkActionsPath(
  organization: OrgForPath,
  project: ProjectForPath,
  environment: EnvironmentForPath
) {
  return `${v3EnvironmentPath(organization, project, environment)}/bulk-actions`;
}

export function v3BulkActionPath(
  organization: OrgForPath,
  project: ProjectForPath,
  environment: EnvironmentForPath,
  bulkAction: { friendlyId: string }
) {
  return `${v3BulkActionsPath(organization, project, environment)}/${bulkAction.friendlyId}`;
}

export function v3EnvironmentVariablesPath(
  organization: OrgForPath,
  project: ProjectForPath,
  environment: EnvironmentForPath
) {
  return `${v3EnvironmentPath(organization, project, environment)}/environment-variables`;
}

export function v3NewEnvironmentVariablesPath(
  organization: OrgForPath,
  project: ProjectForPath,
  environment: EnvironmentForPath
) {
  return `${v3EnvironmentVariablesPath(organization, project, environment)}/new`;
}

export function v3ProjectAlertsPath(
  organization: OrgForPath,
  project: ProjectForPath,
  environment: EnvironmentForPath
) {
  return `${v3EnvironmentPath(organization, project, environment)}/alerts`;
}

export function v3NewProjectAlertPath(
  organization: OrgForPath,
  project: ProjectForPath,
  environment: EnvironmentForPath
) {
  return `${v3ProjectAlertsPath(organization, project, environment)}/new`;
}

export function v3NewProjectAlertPathConnectToSlackPath(
  organization: OrgForPath,
  project: ProjectForPath,
  environment: EnvironmentForPath
) {
  return `${v3ProjectAlertsPath(organization, project, environment)}/new/connect-to-slack`;
}

export function v3TestPath(
  organization: OrgForPath,
  project: ProjectForPath,
  environment: EnvironmentForPath
) {
  return `${v3EnvironmentPath(organization, project, environment)}/test`;
}

export function queryPath(
  organization: OrgForPath,
  project: ProjectForPath,
  environment: EnvironmentForPath
) {
  return `${v3EnvironmentPath(organization, project, environment)}/query`;
}

export function v3CustomDashboardPath(
  organization: OrgForPath,
  project: ProjectForPath,
  environment: EnvironmentForPath,
  dashboard: { friendlyId: string }
) {
  return `${v3EnvironmentPath(organization, project, environment)}/dashboards/custom/${
    dashboard.friendlyId
  }`;
}

export function v3BuiltInDashboardPath(
  organization: OrgForPath,
  project: ProjectForPath,
  environment: EnvironmentForPath,
  key: string
) {
  return `${v3EnvironmentPath(organization, project, environment)}/dashboards/${key}`;
}

export function v3DashboardsLandingPath(
  organization: OrgForPath,
  project: ProjectForPath,
  environment: EnvironmentForPath
) {
  return `${v3EnvironmentPath(organization, project, environment)}/dashboards`;
}

export function v3TestTaskPath(
  organization: OrgForPath,
  project: ProjectForPath,
  environment: EnvironmentForPath,
  task: TaskForPath
) {
  return `${v3TestPath(organization, project, environment)}/tasks/${encodeURIComponent(
    task.taskIdentifier
  )}`;
}

export function v3PlaygroundPath(
  organization: OrgForPath,
  project: ProjectForPath,
  environment: EnvironmentForPath
) {
  return `${v3EnvironmentPath(organization, project, environment)}/playground`;
}

export function v3PlaygroundAgentPath(
  organization: OrgForPath,
  project: ProjectForPath,
  environment: EnvironmentForPath,
  agentSlug: string
) {
  return `${v3PlaygroundPath(organization, project, environment)}/${encodeURIComponent(agentSlug)}`;
}

export function v3AgentTaskPath(
  organization: OrgForPath,
  project: ProjectForPath,
  environment: EnvironmentForPath,
  agentSlug: string
) {
  return `${v3EnvironmentPath(organization, project, environment)}/agents/${encodeURIComponent(
    agentSlug
  )}`;
}

export function v3StandardTaskPath(
  organization: OrgForPath,
  project: ProjectForPath,
  environment: EnvironmentForPath,
  taskSlug: string
) {
  return `${v3EnvironmentPath(organization, project, environment)}/tasks/standard/${encodeURIComponent(
    taskSlug
  )}`;
}

export function v3ScheduledTaskPath(
  organization: OrgForPath,
  project: ProjectForPath,
  environment: EnvironmentForPath,
  taskSlug: string
) {
  return `${v3EnvironmentPath(organization, project, environment)}/tasks/scheduled/${encodeURIComponent(
    taskSlug
  )}`;
}

export function v3RunsPath(
  organization: OrgForPath,
  project: ProjectForPath,
  environment: EnvironmentForPath,
  filters?: TaskRunListSearchFilters
) {
  const searchParams = objectToSearchParams(filters);
  const query = searchParams ? `?${searchParams.toString()}` : "";
  return `${v3EnvironmentPath(organization, project, environment)}/runs${query}`;
}

export function v3CreateBulkActionPath(
  organization: OrgForPath,
  project: ProjectForPath,
  environment: EnvironmentForPath,
  filters?: TaskRunListSearchFilters,
  mode?: "selected" | "filter",
  action?: "replay" | "cancel"
) {
  const searchParams = objectToSearchParams(filters) ?? new URLSearchParams();
  searchParams.set("bulkInspector", RUNS_BULK_INSPECTOR_OPEN_VALUE);
  if (mode) {
    searchParams.set("mode", mode);
  }
  if (action) {
    searchParams.set("action", action);
  }
  const query = `?${searchParams.toString()}`;
  return `${v3RunsPath(organization, project, environment)}${query}`;
}

export function v3RunPath(
  organization: OrgForPath,
  project: ProjectForPath,
  environment: EnvironmentForPath,
  run: v3RunForPath,
  searchParams?: URLSearchParams
) {
  const query = searchParams ? `?${searchParams.toString()}` : "";
  return `${v3RunsPath(organization, project, environment)}/${run.friendlyId}${query}`;
}

export function v3RunRedirectPath(
  organization: OrgForPath,
  project: ProjectForPath,
  run: v3RunForPath
) {
  return `${v3ProjectPath(organization, project)}/runs/${run.friendlyId}`;
}

export function v3RunPathFromFriendlyId(runId: string) {
  return `/runs/${runId}`;
}

export function v3RunDownloadLogsPath(run: v3RunForPath) {
  return `/resources/runs/${run.friendlyId}/logs/download`;
}

export function v3RunSpanPath(
  organization: OrgForPath,
  project: ProjectForPath,
  environment: EnvironmentForPath,
  run: v3RunForPath,
  span: v3SpanForPath,
  searchParams?: URLSearchParams
) {
  searchParams = searchParams ?? new URLSearchParams();
  searchParams.set("span", span.spanId);
  return `${v3RunPath(organization, project, environment, run, searchParams)}`;
}

export function v3RunStreamingPath(
  organization: OrgForPath,
  project: ProjectForPath,
  environment: EnvironmentForPath,
  run: v3RunForPath
) {
  return `${v3RunPath(organization, project, environment, run)}/stream`;
}

export function v3RunIdempotencyKeyResetPath(
  organization: OrgForPath,
  project: ProjectForPath,
  environment: EnvironmentForPath,
  run: v3RunForPath
) {
  return `/resources/orgs/${organizationParam(organization)}/projects/${projectParam(
    project
  )}/env/${environmentParam(environment)}/runs/${run.friendlyId}/idempotencyKey/reset`;
}

export function v3SchedulePath(
  organization: OrgForPath,
  project: ProjectForPath,
  environment: EnvironmentForPath,
  schedule: { friendlyId: string }
) {
  return `${v3EnvironmentPath(organization, project, environment)}/schedules/${
    schedule.friendlyId
  }`;
}

export function v3EditSchedulePath(
  organization: OrgForPath,
  project: ProjectForPath,
  environment: EnvironmentForPath,
  schedule: { friendlyId: string }
) {
  return `${v3EnvironmentPath(organization, project, environment)}/schedules/edit/${
    schedule.friendlyId
  }`;
}

export function v3NewSchedulePath(
  organization: OrgForPath,
  project: ProjectForPath,
  environment: EnvironmentForPath
) {
  return `${v3EnvironmentPath(organization, project, environment)}/schedules/new`;
}

export function v3SchedulesAddOnPath(organization: OrgForPath) {
  return `/resources/orgs/${organizationParam(organization)}/schedules-addon`;
}

export function v3QueuesPath(
  organization: OrgForPath,
  project: ProjectForPath,
  environment: EnvironmentForPath
) {
  return `${v3EnvironmentPath(organization, project, environment)}/queues`;
}

export function v3WaitpointTokensPath(
  organization: OrgForPath,
  project: ProjectForPath,
  environment: EnvironmentForPath,
  filters?: WaitpointSearchParams
) {
  const searchParams = objectToSearchParams(filters);
  const query = searchParams ? `?${searchParams.toString()}` : "";
  return `${v3EnvironmentPath(organization, project, environment)}/waitpoints/tokens${query}`;
}

export function v3WaitpointTokenPath(
  organization: OrgForPath,
  project: ProjectForPath,
  environment: EnvironmentForPath,
  token: { id: string },
  filters?: WaitpointSearchParams
) {
  const searchParams = objectToSearchParams(filters);
  const query = searchParams ? `?${searchParams.toString()}` : "";
  return `${v3WaitpointTokensPath(organization, project, environment)}/${token.id}${query}`;
}

export function v3BatchesPath(
  organization: OrgForPath,
  project: ProjectForPath,
  environment: EnvironmentForPath
) {
  return `${v3EnvironmentPath(organization, project, environment)}/batches`;
}

export function v3SessionsPath(
  organization: OrgForPath,
  project: ProjectForPath,
  environment: EnvironmentForPath
) {
  return `${v3EnvironmentPath(organization, project, environment)}/sessions`;
}

export function v3SessionPath(
  organization: OrgForPath,
  project: ProjectForPath,
  environment: EnvironmentForPath,
  session: { friendlyId: string }
) {
  return `${v3SessionsPath(organization, project, environment)}/${session.friendlyId}`;
}

export function v3BatchPath(
  organization: OrgForPath,
  project: ProjectForPath,
  environment: EnvironmentForPath,
  batch: { friendlyId: string }
) {
  return `${v3BatchesPath(organization, project, environment)}/${batch.friendlyId}`;
}

export function v3BatchRunsPath(
  organization: OrgForPath,
  project: ProjectForPath,
  environment: EnvironmentForPath,
  batch: { friendlyId: string }
) {
  return `${v3RunsPath(organization, project, environment, { batchId: batch.friendlyId })}`;
}

export function v3ProjectSettingsPath(
  organization: OrgForPath,
  project: ProjectForPath,
  environment: EnvironmentForPath
) {
  return `${v3EnvironmentPath(organization, project, environment)}/settings`;
}

export function v3ProjectSettingsGeneralPath(
  organization: OrgForPath,
  project: ProjectForPath,
  environment: EnvironmentForPath
) {
  return `${v3ProjectSettingsPath(organization, project, environment)}/general`;
}

export function v3ProjectSettingsIntegrationsPath(
  organization: OrgForPath,
  project: ProjectForPath,
  environment: EnvironmentForPath
) {
  return `${v3ProjectSettingsPath(organization, project, environment)}/integrations`;
}

export function v3LogsPath(
  organization: OrgForPath,
  project: ProjectForPath,
  environment: EnvironmentForPath
) {
  return `${v3EnvironmentPath(organization, project, environment)}/logs`;
}

export function v3PromptsPath(
  organization: OrgForPath,
  project: ProjectForPath,
  environment: EnvironmentForPath
) {
  return `${v3EnvironmentPath(organization, project, environment)}/prompts`;
}

export function v3PromptPath(
  organization: OrgForPath,
  project: ProjectForPath,
  environment: EnvironmentForPath,
  promptSlug: string,
  version?: string | number
) {
  const base = `${v3PromptsPath(organization, project, environment)}/${promptSlug}`;
  return version != null ? `${base}?version=${version}` : base;
}

export function v3ModelsPath(
  organization: OrgForPath,
  project: ProjectForPath,
  environment: EnvironmentForPath
) {
  return `${v3EnvironmentPath(organization, project, environment)}/models`;
}

export function v3ModelDetailPath(
  organization: OrgForPath,
  project: ProjectForPath,
  environment: EnvironmentForPath,
  modelId: string
) {
  return `${v3ModelsPath(organization, project, environment)}/${modelId}`;
}

export function v3ModelComparePath(
  organization: OrgForPath,
  project: ProjectForPath,
  environment: EnvironmentForPath
) {
  return `${v3ModelsPath(organization, project, environment)}/compare`;
}

export function v3ErrorsPath(
  organization: OrgForPath,
  project: ProjectForPath,
  environment: EnvironmentForPath
) {
  return `${v3EnvironmentPath(organization, project, environment)}/errors`;
}

export function v3ErrorsConnectToSlackPath(
  organization: OrgForPath,
  project: ProjectForPath,
  environment: EnvironmentForPath
) {
  return `${v3ErrorsPath(organization, project, environment)}/connect-to-slack`;
}

export function v3ErrorPath(
  organization: OrgForPath,
  project: ProjectForPath,
  environment: EnvironmentForPath,
  error: { fingerprint: string }
) {
  return `${v3ErrorsPath(organization, project, environment)}/${error.fingerprint}`;
}

export function v3DeploymentsPath(
  organization: OrgForPath,
  project: ProjectForPath,
  environment: EnvironmentForPath
) {
  return `${v3EnvironmentPath(organization, project, environment)}/deployments`;
}

export function v3DeploymentPath(
  organization: OrgForPath,
  project: ProjectForPath,
  environment: EnvironmentForPath,
  deployment: DeploymentForPath,
  currentPage: number
) {
  const query = currentPage ? `?page=${currentPage}` : "";
  return `${v3DeploymentsPath(organization, project, environment)}/${deployment.shortCode}${query}`;
}

export function v3DeploymentVersionPath(
  organization: OrgForPath,
  project: ProjectForPath,
  environment: EnvironmentForPath,
  version: string
) {
  return `${v3DeploymentsPath(organization, project, environment)}?version=${version}`;
}

export function branchesPath(
  organization: OrgForPath,
  project: ProjectForPath,
  environment: EnvironmentForPath
) {
  return `${v3EnvironmentPath(organization, project, environment)}/branches`;
}

export function branchesDevPath(
  organization: OrgForPath,
  project: ProjectForPath,
  environment: EnvironmentForPath
) {
  return `${v3EnvironmentPath(organization, project, environment)}/dev-branches`;
}

export function concurrencyPath(
  organization: OrgForPath,
  project: ProjectForPath,
  environment: EnvironmentForPath
) {
  return `${v3EnvironmentPath(organization, project, environment)}/concurrency`;
}

export function limitsPath(
  organization: OrgForPath,
  project: ProjectForPath,
  environment: EnvironmentForPath
) {
  return `${v3EnvironmentPath(organization, project, environment)}/limits`;
}

export function regionsPath(
  organization: OrgForPath,
  project: ProjectForPath,
  environment: EnvironmentForPath
) {
  return `${v3EnvironmentPath(organization, project, environment)}/regions`;
}

export function v3BillingPath(organization: OrgForPath, message?: string) {
  return `${organizationPath(organization)}/settings/billing${
    message ? `?message=${encodeURIComponent(message)}` : ""
  }`;
}

export function v3BillingLimitsPath(organization: OrgForPath) {
  return `${organizationPath(organization)}/settings/billing-limits`;
}

/** @deprecated Use v3BillingLimitsPath — redirects from billing-alerts are preserved */
export function v3BillingAlertsPath(organization: OrgForPath) {
  return v3BillingLimitsPath(organization);
}

export function v3PrivateConnectionsPath(organization: OrgForPath) {
  return `${organizationPath(organization)}/settings/private-connections`;
}

export function v3NewPrivateConnectionPath(organization: OrgForPath) {
  return `${organizationPath(organization)}/settings/private-connections/new`;
}

export function v3StripePortalPath(organization: OrgForPath) {
  return `/resources/${organization.slug}/subscription/portal`;
}

export function v3UsagePath(organization: OrgForPath) {
  return `${organizationPath(organization)}/settings/usage`;
}

// Docs
export function docsRoot() {
  return "https://trigger.dev/docs";
}

export function docsPath(path: string) {
  return `${docsRoot()}/${path}`;
}

export function docsTroubleshootingPath(path: string) {
  return `${docsRoot()}/v3/troubleshooting`;
}

export function adminPath() {
  return `/@`;
}
