/**
 * Products registry types — central product configuration.
 * Admin creates products, dev teams use the productId across their stack.
 *
 * Status lifecycle: draft → pre_launch → beta → active → sunset → disabled
 */

import { z } from 'zod';

// ── Status lifecycle ──

export const PRODUCT_STATUSES = [
  'draft',
  'pre_launch',
  'beta',
  'active',
  'sunset',
  'disabled',
] as const;

export type ProductStatus = (typeof PRODUCT_STATUSES)[number];

/** Valid forward transitions. Admin override can skip steps. */
const STATUS_TRANSITIONS: Record<ProductStatus, ProductStatus[]> = {
  draft: ['pre_launch', 'disabled'],
  pre_launch: ['beta', 'active', 'disabled'],
  beta: ['active', 'disabled'],
  active: ['sunset', 'disabled'],
  sunset: ['disabled'],
  disabled: ['draft'],
};

/**
 * Check whether a status transition is valid.
 * Returns true if transition is allowed, false otherwise.
 */
export function isValidStatusTransition(current: ProductStatus, next: ProductStatus): boolean {
  if (current === next) return true; // no-op is always valid
  return STATUS_TRANSITIONS[current]?.includes(next) ?? false;
}

// ── Pre-launch config ──

export interface CustomField {
  key: string;
  label: string;
  type: 'text' | 'email' | 'select' | 'multiselect' | 'textarea' | 'number' | 'checkbox';
  options?: string[];
  required: boolean;
  placeholder?: string;
  maxLength?: number;
}

export interface PrelaunchConfig {
  signupEnabled: boolean;
  launchDate?: string;
  tagline?: string;
  logoUrl?: string;
  customFields: CustomField[];
  confirmationMessage?: string;
  redirectUrl?: string;
  maxSignups?: number;
  captchaEnabled: boolean;
  captchaProvider?: 'turnstile' | 'hcaptcha' | 'recaptcha';
}

const CustomFieldSchema = z.object({
  key: z
    .string()
    .min(1)
    .max(64)
    .regex(/^[a-z0-9_]+$/),
  label: z.string().min(1).max(256),
  type: z.enum(['text', 'email', 'select', 'multiselect', 'textarea', 'number', 'checkbox']),
  options: z.array(z.string().max(256)).max(50).optional(),
  required: z.boolean().default(false),
  placeholder: z.string().max(256).optional(),
  maxLength: z.number().int().min(1).max(5000).optional(),
});

export const PrelaunchConfigSchema = z.object({
  signupEnabled: z.boolean().default(false),
  launchDate: z.string().optional(),
  tagline: z.string().max(512).optional(),
  logoUrl: z.string().url().or(z.literal('')).optional(),
  customFields: z.array(CustomFieldSchema).max(20).default([]),
  confirmationMessage: z.string().max(1024).optional(),
  redirectUrl: z.string().url().or(z.literal('')).optional(),
  maxSignups: z.number().int().min(1).optional(),
  captchaEnabled: z.boolean().default(false),
  captchaProvider: z.enum(['turnstile', 'hcaptcha', 'recaptcha']).optional(),
});

// ── Product document ──

export interface ProductDoc {
  id: string;
  productId: string;
  displayName: string;
  licensePrefix: string;
  packageName: string;
  defaultPlan: 'free' | 'pro';
  trialDays: number;
  deviceLimits: {
    free: number;
    pro: number;
    enterprise: number;
  };
  websiteUrl: string;
  status: ProductStatus;
  prelaunchConfig?: PrelaunchConfig;
  /** The user (JWT `sub`) who created/registered this product. Drives per-user
   *  scoping ("my projects") for a generic, multi-tenant platform. Optional for
   *  backward compatibility with products created before ownership tracking. */
  ownerId?: string;
  createdAt: string;
  updatedAt: string;
}

const DeviceLimitsSchema = z.object({
  free: z.number().int().min(0).default(1),
  pro: z.number().int().min(0).default(3),
  enterprise: z.number().int().min(0).default(10),
});

export const CreateProductSchema = z.object({
  productId: z
    .string()
    .min(1)
    .max(64)
    .regex(/^[a-z0-9_-]+$/, 'productId must be lowercase alphanumeric with hyphens/underscores'),
  displayName: z.string().min(1).max(128),
  licensePrefix: z
    .string()
    .min(1)
    .max(16)
    .regex(/^[A-Z]+$/, 'licensePrefix must be uppercase letters'),
  packageName: z.string().max(256).default(''),
  defaultPlan: z.enum(['free', 'pro']).default('free'),
  trialDays: z.number().int().min(0).max(365).default(14),
  deviceLimits: DeviceLimitsSchema.default({ free: 1, pro: 3, enterprise: 10 }),
  websiteUrl: z.string().url().or(z.literal('')).default(''),
  status: z.enum(PRODUCT_STATUSES).default('active'),
  prelaunchConfig: PrelaunchConfigSchema.optional(),
  ownerId: z.string().optional(),
});

export const UpdateProductSchema = z.object({
  displayName: z.string().min(1).max(128).optional(),
  licensePrefix: z
    .string()
    .min(1)
    .max(16)
    .regex(/^[A-Z]+$/)
    .optional(),
  packageName: z.string().max(256).optional(),
  defaultPlan: z.enum(['free', 'pro']).optional(),
  trialDays: z.number().int().min(0).max(365).optional(),
  deviceLimits: DeviceLimitsSchema.partial().optional(),
  websiteUrl: z.string().url().or(z.literal('')).optional(),
  status: z.enum(PRODUCT_STATUSES).optional(),
  prelaunchConfig: PrelaunchConfigSchema.partial().optional(),
});

export type CreateProductInput = z.infer<typeof CreateProductSchema>;
export type UpdateProductInput = z.infer<typeof UpdateProductSchema>;
