/**
 * Type definitions for Onebox
 */

import type * as servezoneInterfaces from '@serve.zone/interfaces';

export type IServiceTargetPort = servezoneInterfaces.data.IServiceTargetPort;
export type IServiceDomainRoute = servezoneInterfaces.data.IServiceDomainRoute;
export type IServicePublicPortMapping = servezoneInterfaces.data.IServicePublicPortMapping;
export type IServiceSecretFile = servezoneInterfaces.data.IServiceSecretFile;

// Service types
export interface IService {
  id?: number;
  name: string;
  image: string;
  registry?: string;
  envVars: Record<string, string>;
  containerArgs?: string[];
  secretFiles?: IServiceSecretFile[];
  volumes?: IServiceVolume[];
  publishedPorts?: IServicePublishedPort[];
  targetPorts?: IServiceTargetPort[];
  domains?: IServiceDomainRoute[];
  publicPortMappings?: IServicePublicPortMapping[];
  port: number;
  domain?: string;
  containerID?: string;
  status: 'stopped' | 'starting' | 'running' | 'stopping' | 'failed';
  createdAt: number;
  updatedAt: number;
  // Onebox Registry fields
  useOneboxRegistry?: boolean;
  registryRepository?: string;
  registryImageTag?: string;
  autoUpdateOnPush?: boolean;
  imageDigest?: string;
  imageCleanup?: IServiceImageCleanup;
  // Platform service requirements
  platformRequirements?: IPlatformRequirements;
  // Backup settings
  includeImageInBackup?: boolean;
  // App Store template tracking
  appTemplateId?: string;
  appTemplateVersion?: string;
}

export interface IServiceImageCleanup {
  imageName: string;
  candidateReference: string;
  priorReference?: string;
  phase?: 'rollback-pending' | 'candidate-active';
}

export type IHostedAppLifecycleState = servezoneInterfaces.data.IHostedAppLifecycleState;

export interface IHostedAppLifecycleRecord {
  id?: number;
  serviceId: number;
  appInstanceId: string;
  hostType: 'onebox';
  state: IHostedAppLifecycleState;
  createdAt: number;
  updatedAt: number;
}

export interface IServiceSecretBundleRecord {
  serviceId: number;
  valuesEncrypted: string;
  createdAt: number;
  updatedAt: number;
}

export interface IServiceVolume {
  name?: string;
  source?: string;
  mountPath: string;
  storageClass?: string;
  driver?: string;
  readOnly?: boolean;
  backup?: boolean;
  options?: Record<string, string>;
}

export type TStorageTargetKind = 'local' | 'nfs' | 'smb' | 'backup' | 'custom';
export type TStorageClassPurpose = 'runtime' | 'database' | 'backup';

export interface IStorageTargetConfig {
  path?: string;
  server?: string;
  exportPath?: string;
  share?: string;
  username?: string;
  password?: string;
  domain?: string;
  version?: string;
  driver?: string;
  device?: string;
  options?: Record<string, string>;
}

export interface IStorageTarget {
  id?: number;
  name: string;
  displayName: string;
  kind: TStorageTargetKind;
  config: IStorageTargetConfig;
  createdAt: number;
  updatedAt: number;
}

export interface IStorageClass {
  id?: number;
  name: string;
  displayName: string;
  description?: string;
  targetName: string;
  purpose: TStorageClassPurpose;
  isDefault?: boolean;
  driver?: string;
  options?: Record<string, string>;
  createdAt: number;
  updatedAt: number;
}

export type TServicePortProtocol = 'tcp' | 'udp';

export interface IServicePublishedPort {
  targetPort: number;
  targetPortEnd?: number;
  publishedPort?: number;
  publishedPortEnd?: number;
  protocol?: TServicePortProtocol;
  hostIp?: string;
}

// Registry types
export interface IRegistry {
  id?: number;
  url: string;
  username: string;
  passwordEncrypted: string;
  createdAt: number;
}

// Registry token types
export interface IRegistryToken {
  id?: number;
  name: string;
  tokenHash: string;
  type: 'global' | 'ci';
  scope: 'all' | string[];  // 'all' or array of service names
  expiresAt: number | null;
  createdAt: number;
  lastUsedAt: number | null;
  createdBy: string;
}

export interface ICreateRegistryTokenRequest {
  name: string;
  type: 'global' | 'ci';
  scope: 'all' | string[];
  expiresIn: '30d' | '90d' | '365d' | 'never';
}

export interface IRegistryTokenView {
  id: number;
  name: string;
  type: 'global' | 'ci';
  scope: 'all' | string[];
  scopeDisplay: string;
  expiresAt: number | null;
  createdAt: number;
  lastUsedAt: number | null;
  createdBy: string;
  isExpired: boolean;
}

export interface ITokenCreatedResponse {
  token: IRegistryTokenView;
  plainToken: string;  // Only shown once at creation
}

// Platform service types
export type TPlatformServiceType = 'mongodb' | 'minio' | 'smartstorage' | 'valkey' | 'postgresql' | 'rabbitmq' | 'coretraffic' | 'clickhouse' | 'mariadb';
export type TPlatformResourceType = 'database' | 'bucket' | 'cache' | 'queue';
export type TPlatformServiceStatus = 'stopped' | 'starting' | 'running' | 'stopping' | 'failed';

export interface IPlatformService {
  id?: number;
  name: string;
  type: TPlatformServiceType;
  status: TPlatformServiceStatus;
  containerId?: string;
  config: IPlatformServiceConfig;
  adminCredentialsEncrypted?: string;
  createdAt: number;
  updatedAt: number;
}

export interface IPlatformServiceConfig {
  image: string;
  port: number;
  volumes?: string[];
  storageClass?: string;
  command?: string;
  environment?: Record<string, string>;
}

export interface IPlatformResource {
  id?: number;
  platformServiceId: number;
  serviceId: number;
  resourceType: TPlatformResourceType;
  resourceName: string;
  credentialsEncrypted: string;
  createdAt: number;
}

export interface IPlatformRequirements {
  mongodb?: boolean;
  s3?: boolean;
  clickhouse?: boolean;
  valkey?: boolean;
  mariadb?: boolean;
}

export interface IProvisionedResource {
  type: TPlatformResourceType;
  name: string;
  credentials: Record<string, string>;
  envVars: Record<string, string>;
}

export interface IEnvVarMapping {
  envVar: string;
  credentialPath: string;
}

// Nginx configuration types
export interface INginxConfig {
  id?: number;
  serviceId: number;
  domain: string;
  port: number;
  sslEnabled: boolean;
  configTemplate: string;
  createdAt: number;
  updatedAt: number;
}

// Domain management types
export interface IDomain {
  id?: number;
  domain: string;
  dnsProvider: 'cloudflare' | 'manual' | 'dcrouter' | null;
  cloudflareZoneId?: string;
  isObsolete: boolean;
  defaultWildcard: boolean;
  createdAt: number;
  updatedAt: number;
}

export interface ICertificate {
  id?: number;
  domainId: number;
  certDomain: string;
  isWildcard: boolean;
  certPem: string;       // Certificate PEM content
  keyPem: string;        // Private key PEM content
  fullchainPem: string;  // Full chain PEM content (cert + intermediates)
  expiryDate: number;
  issuer: string;
  isValid: boolean;
  createdAt: number;
  updatedAt: number;
}

export interface ICertRequirement {
  id?: number;
  serviceId: number;
  domainId: number;
  subdomain: string;
  certificateId?: number;
  status: 'pending' | 'active' | 'renewing';
  createdAt: number;
  updatedAt: number;
}

export interface IDomainView {
  domain: IDomain;
  certificates: ICertificate[];
  requirements: ICertRequirement[];
  serviceCount: number;
  certificateStatus: 'valid' | 'expiring-soon' | 'expired' | 'pending' | 'none';
  daysRemaining: number | null;
}

// SSL certificate type - stores certificate content directly in database
export interface ISslCertificate {
  id?: number;
  domain: string;
  certPem: string;       // Certificate PEM content
  keyPem: string;        // Private key PEM content
  fullchainPem: string;  // Full chain PEM content (cert + intermediates)
  expiryDate: number;
  issuer: string;
  createdAt: number;
  updatedAt: number;
}

// DNS record types
export interface IDnsRecord {
  id?: number;
  domain: string;
  type: 'A' | 'AAAA' | 'CNAME';
  value: string;
  cloudflareID?: string;
  createdAt: number;
  updatedAt: number;
}

// Metrics types
export interface IMetric {
  id?: number;
  serviceId: number;
  timestamp: number;
  cpuPercent: number;
  memoryUsed: number;
  memoryLimit: number;
  networkRxBytes: number;
  networkTxBytes: number;
}

// Log entry types
export interface ILogEntry {
  id?: number;
  serviceId: number;
  timestamp: number;
  message: string;
  level: 'info' | 'warn' | 'error' | 'debug';
  source: 'stdout' | 'stderr';
}

// User types
export interface IUser {
  id?: number;
  username: string;
  role: 'admin' | 'user';
  webauthnUserId: string;
  passkeyCredentials: IPasskeyCredential[];
  createdAt: number;
  updatedAt: number;
}

// Settings types
export interface ISetting {
  key: string;
  value: string;
  updatedAt: number;
}

// Application settings
export type TPasskeyTransport =
  | 'ble'
  | 'cable'
  | 'hybrid'
  | 'internal'
  | 'nfc'
  | 'smart-card'
  | 'usb';

export type TPasskeyDeviceType = 'singleDevice' | 'multiDevice';

export interface IPasskeyCredential {
  credentialId: string;
  publicKey: string;
  counter: number;
  transports: TPasskeyTransport[] | null;
  deviceType: TPasskeyDeviceType;
  backedUp: boolean;
  rpId: string;
  origin: string;
  createdAt: number;
  lastUsedAt: number | null;
}

export interface IAppSettings {
  serverIP?: string;
  adminUiDomain?: string;
  cloudflareToken?: string;
  cloudflareZoneId?: string;
  dcrouterMode?: 'managed' | 'external' | 'disabled';
  dcrouterManagedImage?: string;
  dcrouterManagedOpsPort?: number;
  dcrouterManagedHttpPort?: number;
  dcrouterManagedHttpsPort?: number;
  dcrouterManagedDataDir?: string;
  dcrouterGatewayUrl?: string;
  dcrouterGatewayApiToken?: string;
  dcrouterGatewayClientId?: string;
  /** @deprecated Use dcrouterGatewayClientId. */
  dcrouterTargetHost?: string;
  dcrouterTargetPort?: number;
  acmeEmail?: string;
  dataDir?: string;
  httpPort?: number;
  httpsPort?: number;
  metricsInterval?: number;
  autoRenewCerts?: boolean;
  renewalThreshold?: number;
  forceHttps?: boolean;
  logRetentionDays?: number;
}

// Container stats from Docker
export interface IContainerStats {
  cpuPercent: number;
  memoryUsed: number;
  memoryLimit: number;
  memoryPercent: number;
  networkRx: number;
  networkTx: number;
}

// Service deployment options
export interface IServiceDeployOptions {
  name: string;
  image: string;
  registry?: string;
  envVars?: Record<string, string>;
  secretEnvVars?: Record<string, string>;
  containerArgs?: string[];
  secretFiles?: IServiceSecretFile[];
  volumes?: IServiceVolume[];
  publishedPorts?: IServicePublishedPort[];
  targetPorts?: IService['targetPorts'];
  domains?: IService['domains'];
  publicPortMappings?: IService['publicPortMappings'];
  port: number;
  domain?: string;
  autoSSL?: boolean;
  autoDNS?: boolean;
  // Onebox Registry options
  useOneboxRegistry?: boolean;
  registryImageTag?: string;
  autoUpdateOnPush?: boolean;
  imageDigest?: string;
  // Platform service requirements
  enableMongoDB?: boolean;
  enableS3?: boolean;
  enableClickHouse?: boolean;
  enableValkey?: boolean;
  enableMariaDB?: boolean;
  // App Store template tracking
  appTemplateId?: string;
  appTemplateVersion?: string;
}

// HTTP API request/response types
export interface IApiResponse<T = unknown> {
  success: boolean;
  data?: T;
  error?: string;
  message?: string;
}

// CLI command types
export interface ICliArgs {
  _: string[];
  [key: string]: unknown;
}

// Backup types
export type TBackupRestoreMode = 'restore' | 'import' | 'clone';

// Retention policy for GFS (Grandfather-Father-Son) time-window based retention
export interface IRetentionPolicy {
  hourly: number;   // 0 = disabled, else keep up to N backups from last 24h
  daily: number;    // Keep 1 backup per day for last N days
  weekly: number;   // Keep 1 backup per week for last N weeks
  monthly: number;  // Keep 1 backup per month for last N months
}

// Default retention presets
export const RETENTION_PRESETS = {
  standard: { hourly: 0, daily: 7, weekly: 4, monthly: 12 },
  frequent: { hourly: 24, daily: 7, weekly: 4, monthly: 12 },
  minimal: { hourly: 0, daily: 3, weekly: 2, monthly: 6 },
  longterm: { hourly: 0, daily: 14, weekly: 8, monthly: 24 },
} as const;

export type TRetentionPreset = keyof typeof RETENTION_PRESETS | 'custom';

export interface IBackup {
  id?: number;
  serviceId: number;
  serviceName: string;  // Denormalized for display
  filename: string;
  snapshotId?: string;  // ContainerArchive snapshot ID (new backups)
  sizeBytes: number;
  storedSizeBytes?: number;  // Actual stored size after dedup+compression
  createdAt: number;
  includesImage: boolean;
  platformResources: TPlatformServiceType[];  // Which platform types were backed up
  checksum: string;
  // Scheduled backup fields
  scheduleId?: number;  // Links backup to its schedule for retention
}

export interface IBackupManifest {
  version: string;
  createdAt: number;
  oneboxVersion: string;
  serviceName: string;
  includesImage: boolean;
  platformResources: TPlatformServiceType[];
  checksum: string;
}

export interface IBackupServiceConfig {
  name: string;
  image: string;
  registry?: string;
  envVars: Record<string, string>;
  /** Machine-key ciphertext. Cross-host restore requires the same ONEBOX_ENCRYPTION_KEY. */
  serviceSecretsEncrypted?: string;
  containerArgs?: string[];
  secretFiles?: IServiceSecretFile[];
  volumes?: IServiceVolume[];
  publishedPorts?: IServicePublishedPort[];
  targetPorts?: IService['targetPorts'];
  domains?: IService['domains'];
  publicPortMappings?: IService['publicPortMappings'];
  port: number;
  domain?: string;
  useOneboxRegistry?: boolean;
  registryRepository?: string;
  registryImageTag?: string;
  autoUpdateOnPush?: boolean;
  platformRequirements?: IPlatformRequirements;
  includeImageInBackup?: boolean;
}

export interface IBackupPlatformResource {
  resourceType: TPlatformResourceType;
  resourceName: string;
  platformServiceType: TPlatformServiceType;
  credentials: Record<string, string>;  // Decrypted for backup, re-encrypted on restore
}

export interface IBackupResult {
  backup: IBackup;
  filePath?: string;  // Legacy file-based backups only
  snapshotId?: string;  // ContainerArchive snapshot ID
}

export interface IRestoreOptions {
  mode: TBackupRestoreMode;
  newServiceName?: string;  // Required for 'import' and 'clone' modes
  skipPlatformData?: boolean;  // Restore config only, skip DB/bucket data
  overwriteExisting?: boolean; // For 'restore' mode
}

export interface IRestoreResult {
  service: IService;
  platformResourcesRestored: number;
  warnings: string[];
}

// Backup scheduling types (GFS retention scheme)
export type TBackupScheduleScope = 'all' | 'pattern' | 'service';

export interface IBackupSchedule {
  id?: number;
  scopeType: TBackupScheduleScope;
  scopePattern?: string;        // Glob pattern for 'pattern' scope type
  serviceId?: number;           // Only for 'service' scope type
  serviceName?: string;         // Only for 'service' scope type
  cronExpression: string;
  retention: IRetentionPolicy;  // Per-tier retention counts
  enabled: boolean;
  lastRunAt: number | null;
  nextRunAt: number | null;
  lastStatus: 'success' | 'failed' | null;
  lastError: string | null;
  createdAt: number;
  updatedAt: number;
}

export interface IBackupScheduleCreate {
  scopeType: TBackupScheduleScope;
  scopePattern?: string;        // Required for 'pattern' scope type
  serviceName?: string;         // Required for 'service' scope type
  cronExpression: string;
  retention: IRetentionPolicy;
  enabled?: boolean;
}

export interface IBackupScheduleUpdate {
  cronExpression?: string;
  retention?: IRetentionPolicy;
  enabled?: boolean;
}

// Backup creation options (for scheduled backups)
export interface IBackupCreateOptions {
  scheduleId?: number;
}
