import { z } from 'zod'
import { baseEnv, catalogApiClientEnv, csvEnv, databaseEnv, featureEnv, loadEnv, magentoEnv } from '@znet/shared'

export const SCOPES = {
  CATALOG_READ: 'catalog:read',
  ORDERS_READ: 'orders:read',
  ORDERS_PII: 'orders:pii',
} as const
export type Scope = (typeof SCOPES)[keyof typeof SCOPES]

const mcpEnv = baseEnv
  .extend(databaseEnv.shape)
  .extend(magentoEnv.shape)
  .extend(catalogApiClientEnv.shape)
  .extend(featureEnv.shape)
  .extend({
    /** Public URL of the MCP endpoint, exactly as ChatGPT is given it, e.g. https://mcp.znet.example/mcp */
    MCP_PUBLIC_URL: z.url(),
    MCP_HOST: z.string().default('127.0.0.1'),
    MCP_PORT: z.coerce.number().int().default(4200),
    /** Host headers accepted (DNS-rebinding protection). Defaults to the public URL's host. */
    MCP_ALLOWED_HOSTS: csvEnv,

    /**
     * magento = built-in OAuth 2.1 server, staff sign in with Magento admin credentials (default)
     * oauth   = external identity provider issues JWTs (Auth0, WorkOS, …)
     * static  = fixed tokens, local development only
     */
    AUTH_MODE: z.enum(['magento', 'oauth', 'static']).default('magento'),
    /** magento: HMAC key for the login form (openssl rand -hex 32). */
    MCP_AUTH_SECRET: z.string().min(32, 'use at least 32 random characters').optional(),
    /** magento: `google` = require the Google Authenticator code (Magento 2.4 default), `none` = 2FA module disabled. */
    MAGENTO_ADMIN_2FA: z.enum(['google', 'none']).default('google'),
    /** magento: `user=scopes;*=scopes` — which Magento admins may connect, and with which scopes. */
    MCP_USER_SCOPES: z.string().default('*=catalog:read orders:read'),
    MCP_ACCESS_TOKEN_TTL_MIN: z.coerce.number().int().positive().default(60),
    /** Also the longest a disabled Magento admin keeps access (or revoke with `pnpm auth:revoke`). */
    MCP_REFRESH_TOKEN_TTL_DAYS: z.coerce.number().int().positive().default(7),
    MCP_STORE_NAME: z.string().default('Znet'),

    /** OAuth: the authorization server (IdP) issuer URL. */
    OAUTH_ISSUER: z.url().optional(),
    /** OAuth: expected `aud`. Defaults to MCP_PUBLIC_URL (RFC 8707 resource indicator). */
    OAUTH_AUDIENCE: z.string().optional(),
    /** OAuth: claim holding granted scopes — `scope` (space-separated), `scp` or `permissions` (arrays). */
    OAUTH_SCOPE_CLAIM: z.string().default('scope'),
    /** Static (dev only): `token|subject|scope scope;token2|subject2|scope` */
    MCP_STATIC_TOKENS: z.string().optional(),

    /** Max requests per minute per token subject. */
    MCP_RATE_LIMIT_PER_MIN: z.coerce.number().int().positive().default(120),
    /** Live Magento calls time out after this many ms. */
    MAGENTO_LIVE_TIMEOUT_MS: z.coerce.number().int().positive().default(15_000),
  })
  .superRefine((env, ctx) => {
    if (env.AUTH_MODE === 'magento' && !env.MCP_AUTH_SECRET) ctx.addIssue({ code: 'custom', path: ['MCP_AUTH_SECRET'], message: 'required when AUTH_MODE=magento' })
    if (env.AUTH_MODE === 'oauth' && !env.OAUTH_ISSUER) ctx.addIssue({ code: 'custom', path: ['OAUTH_ISSUER'], message: 'required when AUTH_MODE=oauth' })
    if (env.AUTH_MODE === 'static' && !env.MCP_STATIC_TOKENS) ctx.addIssue({ code: 'custom', path: ['MCP_STATIC_TOKENS'], message: 'required when AUTH_MODE=static' })
    if (env.AUTH_MODE === 'static' && env.NODE_ENV === 'production') ctx.addIssue({ code: 'custom', path: ['AUTH_MODE'], message: 'static tokens are not allowed in production' })
  })

export type McpEnv = z.infer<typeof mcpEnv>
export const loadMcpEnv = () => loadEnv(mcpEnv)
