import { sdk } from '../sdk'
import { configFile } from '../file-models/config.json'

const { InputSpec, Value } = sdk

// Lifetime cap on how many distinct anonymous trial cookies one IP
// address can mint, FOR THE LIFETIME OF THE INSTALL — not a rolling
// daily window. Was previously per-day; switched in 0.2.84 so a user
// who clears cookies can't simply wait 24h and replay the trial.
//
// Anti-abuse model:
//   - Each minted cookie carries trial_credits_per_visitor credits
//   - Each IP can mint at most `trials_per_ip_lifetime` cookies, ever
//   - Combined effect: an IP's total free credits =
//       trial_credits_per_visitor × trials_per_ip_lifetime
//   - Once spent, the visitor must sign up (which grants
//     tenant_default_credits) or pay for more
//
// IP rotation via VPN / proxy pool defeats this, same as before. The
// goal isn't to be unbypassable — it's to raise the floor for casual
// scripted abuse and give the operator forensic data (IP + UA logged
// on every trial) to manually ban any sophisticated abuser.
//
// Defaults to 5 — generous enough that a family on one NAT all get
// trials, tight enough that 50 trials/IP from one address looks like
// scripted abuse in the admin dashboard.
//
// Legacy field name `trials_per_ip_per_day` is preserved on the
// config schema as a read-only alias so installs upgrading from
// 0.2.77–0.2.83 don't lose their existing setting.
const inputSpec = InputSpec.of({
  limit: Value.number({
    name: 'Max trial cookies per IP (lifetime)',
    description:
      'How many anonymous trial cookies can be issued from a single IP, FOR THE LIFE OF THIS INSTALL. Not a rolling daily window — once the IP hits this cap, no more trial cookies from that address ever. Higher = friendlier to shared networks (offices, families). Lower = tighter against scripted abuse + cookie-clearing replay.',
    required: true,
    default: 5,
    integer: true,
    min: 1,
    max: 50,
  }),
})

export const setTrialsPerIpPerDay = sdk.Action.withInput(
  'set-trials-per-ip-per-day',

  async ({ effects }) => ({
    name: 'Set Trial Cookies per IP (Lifetime)',
    description:
      'Anti-abuse cap on how many trial cookies a single IP can mint over the life of this install. Default: 5. Was per-day in 0.2.77–0.2.83 and is now lifetime — see release notes for 0.2.84.',
    warning: null,
    allowedStatuses: 'any',
    group: 'Multi-Tenant',
    visibility: 'enabled',
  }),

  inputSpec,

  async ({ effects }) => {
    const config = await configFile.read().once()
    // Prefer the new field; fall back to the legacy per_day key for
    // operators whose StartOS-managed config still has the old name.
    const current =
      config?.trials_per_ip_lifetime ??
      config?.trials_per_ip_per_day ??
      5
    return { limit: current }
  },

  async ({ effects, input }) => {
    // Write to BOTH keys so any code path still reading the legacy name
    // gets a sane value too. anon-trial.js prefers the new key.
    await configFile.merge(effects, {
      trials_per_ip_lifetime: input.limit,
      trials_per_ip_per_day: input.limit,
    })
    return null
  },
)
