import { z } from 'zod';

import { authUserSchema } from './auth';
import { serverResponseSchema } from './servers';

export const whmcsHealthResponseSchema = z.object({
  status: z.literal('ok'),
  integrationId: z.string(),
  billingProvider: z.string(),
});

export const whmcsPlanCatalogItemSchema = z.object({
  id: z.string().uuid(),
  slug: z.string(),
  name: z.string(),
  maxRamMb: z.number().int(),
  isFree: z.boolean(),
});

export const whmcsPlanCatalogResponseSchema = z.object({
  plans: z.array(whmcsPlanCatalogItemSchema),
});

export const whmcsUpsertClientRequestSchema = z.object({
  email: z.string().email(),
  username: z.string().min(3).max(32),
  displayName: z.string().max(64).optional(),
});

export const whmcsUpsertClientResponseSchema = z.object({
  userId: z.string().uuid(),
  externalClientId: z.string(),
  created: z.boolean(),
});

export const whmcsProvisionServiceRequestSchema = z.object({
  externalServiceId: z.string().min(1).max(64),
  externalClientId: z.string().min(1).max(64),
  externalProductId: z.string().max(64).optional(),
  planSlug: z.string().min(1).max(64),
  serverName: z.string().min(1).max(64),
  minecraftVersion: z.string().min(1).max(32).default('1.21.1'),
  softwareFamily: z
    .enum(['VANILLA', 'PAPER', 'PURPUR', 'FABRIC', 'FORGE', 'NEOFORGE', 'QUILT', 'BEDROCK_DEDICATED'])
    .default('VANILLA'),
  edition: z.enum(['JAVA', 'BEDROCK']).default('JAVA'),
  eulaAccepted: z.literal(true),
});

export const whmcsServiceResponseSchema = z.object({
  externalServiceId: z.string(),
  status: z.enum(['PENDING', 'ACTIVE', 'SUSPENDED', 'TERMINATED']),
  server: serverResponseSchema,
});

export const whmcsChangePackageRequestSchema = z.object({
  planSlug: z.string().min(1).max(64),
  ramMb: z.number().int().min(512).max(65536).optional(),
});

export const whmcsSuspendRequestSchema = z.object({
  reason: z.string().max(256).optional(),
});

export const whmcsSsoRoleSchema = z.enum(['owner', 'admin']);

export const whmcsSsoKindSchema = z.enum(['service', 'admin']);

export const whmcsCreateSsoRequestSchema = z.object({
  externalClientId: z.string().min(1).max(64),
  externalUserId: z.string().min(1).max(64),
  role: whmcsSsoRoleSchema.default('owner'),
  kind: whmcsSsoKindSchema.default('service'),
  targetPath: z.string().max(256).optional(),
});

export const whmcsCreateSsoResponseSchema = z.object({
  ticketId: z.string().uuid(),
  redirectUrl: z.string().url(),
  expiresAt: z.string().datetime(),
  targetPath: z.string(),
});

export const ssoConsumeRequestSchema = z.object({
  ticket: z.string().min(32).max(256),
});

export const ssoImpersonationSchema = z.object({
  isImpersonation: z.boolean(),
  label: z.string().optional(),
});

export const ssoConsumeResponseSchema = z.object({
  redirectPath: z.string(),
  user: authUserSchema,
  impersonation: ssoImpersonationSchema.optional(),
});

export type WhmcsHealthResponse = z.infer<typeof whmcsHealthResponseSchema>;
export type WhmcsPlanCatalogResponse = z.infer<typeof whmcsPlanCatalogResponseSchema>;
export type WhmcsUpsertClientRequest = z.infer<typeof whmcsUpsertClientRequestSchema>;
export type WhmcsUpsertClientResponse = z.infer<typeof whmcsUpsertClientResponseSchema>;
export type WhmcsProvisionServiceRequest = z.infer<typeof whmcsProvisionServiceRequestSchema>;
export type WhmcsServiceResponse = z.infer<typeof whmcsServiceResponseSchema>;
export type WhmcsChangePackageRequest = z.infer<typeof whmcsChangePackageRequestSchema>;
export type WhmcsSuspendRequest = z.infer<typeof whmcsSuspendRequestSchema>;
export type WhmcsCreateSsoRequest = z.infer<typeof whmcsCreateSsoRequestSchema>;
export type WhmcsCreateSsoResponse = z.infer<typeof whmcsCreateSsoResponseSchema>;
export type SsoConsumeRequest = z.infer<typeof ssoConsumeRequestSchema>;
export type SsoConsumeResponse = z.infer<typeof ssoConsumeResponseSchema>;

export const whmcsExpectedStatusSchema = z.enum([
  'Pending',
  'Active',
  'Suspended',
  'Terminated',
  'Cancelled',
]);

export const whmcsReconcileRequestSchema = z.object({
  expectedWhmcsStatus: whmcsExpectedStatusSchema.optional(),
  expectedPlanSlug: z.string().max(64).optional(),
  expectedRamMb: z.number().int().min(512).max(65536).optional(),
  dryRun: z.boolean().default(false),
  autoRepair: z.boolean().default(false),
});

export const reconciliationSeveritySchema = z.enum([
  'INFO',
  'WARNING',
  'BLOCKING',
  'DESTRUCTIVE',
  'SECURITY',
]);

export const reconciliationIssueSchema = z.object({
  id: z.string().uuid(),
  code: z.string(),
  severity: reconciliationSeveritySchema,
  message: z.string(),
  externalServiceId: z.string().nullable(),
  serverId: z.string().uuid().nullable(),
  details: z.record(z.unknown()).optional(),
  autoRepaired: z.boolean(),
});

export const whmcsReconcileResponseSchema = z.object({
  runId: z.string().uuid(),
  dryRun: z.boolean(),
  issues: z.array(reconciliationIssueSchema),
  repaired: z.array(z.string()),
});

export const whmcsListAccountsResponseSchema = z.object({
  accounts: z.array(
    z.object({
      externalServiceId: z.string(),
      externalClientId: z.string(),
      serverId: z.string().uuid(),
      domain: z.string(),
      username: z.string().nullable(),
      status: z.enum(['Active', 'Suspended', 'Terminated', 'Pending']),
      planSlug: z.string(),
      ramMb: z.number().int(),
      gameCloudStatus: z.string(),
      linkStatus: z.enum(['PENDING', 'ACTIVE', 'SUSPENDED', 'TERMINATED']),
      lastReconciledAt: z.string().datetime().nullable(),
    }),
  ),
});

export const whmcsImportServiceRequestSchema = z.object({
  externalServiceId: z.string().min(1).max(64),
  externalClientId: z.string().min(1).max(64),
  serverId: z.string().uuid(),
  externalProductId: z.string().max(64).optional(),
  expectedPlanSlug: z.string().max(64).optional(),
});

export const integrationEventSchema = z.object({
  id: z.string().uuid(),
  eventType: z.string(),
  payload: z.record(z.unknown()),
  status: z.enum(['PENDING', 'ACKNOWLEDGED', 'DEAD_LETTER']),
  createdAt: z.string().datetime(),
});

export const whmcsEventsResponseSchema = z.object({
  events: z.array(integrationEventSchema),
  nextCursor: z.string().uuid().nullable(),
});

export const whmcsEventsAckRequestSchema = z.object({
  eventIds: z.array(z.string().uuid()).min(1).max(100),
  deadLetter: z.boolean().default(false),
  deadLetterReason: z.string().max(512).optional(),
});

export const whmcsEventsAckResponseSchema = z.object({
  acknowledged: z.number().int(),
});

export const whmcsUsageMetricsSchema = z.object({
  runtime_minutes: z.number(),
  memory_gib_minutes: z.number(),
  cpu_core_minutes: z.number(),
  storage_gib_days: z.number(),
  backup_storage_gib_days: z.number(),
  egress_gib: z.number(),
  extra_port_days: z.number(),
  priority_queue_minutes: z.number(),
  managed_service_units: z.number(),
});

export const whmcsUsageUpdateSchema = z.object({
  diskUsageGiB: z.number(),
  bandwidthGiB: z.number(),
});

export const whmcsUsageQuerySchema = z.object({
  periodStart: z.string().datetime().optional(),
  periodEnd: z.string().datetime().optional(),
  testMode: z.coerce.boolean().default(false),
});

export const whmcsUsageResponseSchema = z.object({
  exportId: z.string().uuid(),
  externalServiceId: z.string(),
  serverId: z.string().uuid(),
  periodStart: z.string().datetime(),
  periodEnd: z.string().datetime(),
  metrics: whmcsUsageMetricsSchema,
  usageUpdate: whmcsUsageUpdateSchema,
  contentHash: z.string(),
  status: z.enum(['DRAFT', 'EXPORTED', 'ADJUSTED']),
  isTestMode: z.boolean(),
  adjustments: z.array(
    z.object({
      metricKey: z.string(),
      delta: z.number(),
      reason: z.string(),
    }),
  ),
});

export const whmcsUsageAdjustmentRequestSchema = z.object({
  periodStart: z.string().datetime(),
  periodEnd: z.string().datetime(),
  adjustments: z
    .array(
      z.object({
        metricKey: z.string().min(1).max(64),
        delta: z.number(),
        reason: z.string().min(1).max(256),
      }),
    )
    .min(1)
    .max(20),
  testMode: z.boolean().default(false),
});

export type WhmcsReconcileRequest = z.infer<typeof whmcsReconcileRequestSchema>;
export type WhmcsReconcileResponse = z.infer<typeof whmcsReconcileResponseSchema>;
export type WhmcsListAccountsResponse = z.infer<typeof whmcsListAccountsResponseSchema>;
export type WhmcsImportServiceRequest = z.infer<typeof whmcsImportServiceRequestSchema>;
export type WhmcsEventsResponse = z.infer<typeof whmcsEventsResponseSchema>;
export type WhmcsEventsAckRequest = z.infer<typeof whmcsEventsAckRequestSchema>;
export type WhmcsEventsAckResponse = z.infer<typeof whmcsEventsAckResponseSchema>;
export type WhmcsUsageResponse = z.infer<typeof whmcsUsageResponseSchema>;
export type WhmcsUsageAdjustmentRequest = z.infer<typeof whmcsUsageAdjustmentRequestSchema>;

export const whmcsDashboardStatsResponseSchema = z.object({
  integrationId: z.string(),
  billingProvider: z.enum(['internal', 'whmcs', 'stripe']),
  moduleVersion: z.string(),
  linkedClients: z.number().int(),
  linkedServices: z.number().int(),
  suspendedServices: z.number().int(),
  terminatedServices: z.number().int(),
  pendingEvents: z.number().int(),
  deadLetterEvents: z.number().int(),
  openReconciliationIssues: z.number().int(),
  exportedUsagePeriods: z.number().int(),
  eventsCursor: z.string().uuid().nullable(),
  lastEventSyncAt: z.string().datetime().nullable(),
  lastReconciliationAt: z.string().datetime().nullable(),
  mtlsEnabled: z.boolean(),
  mtlsFingerprintRegistered: z.boolean(),
});

export type WhmcsDashboardStatsResponse = z.infer<typeof whmcsDashboardStatsResponseSchema>;

export const whmcsRegisterMtlsRequestSchema = z.object({
  fingerprint: z.string().min(32).max(128),
  subject: z.string().max(256).optional(),
});

export const whmcsMtlsStatusResponseSchema = z.object({
  integrationId: z.string(),
  mtlsEnabled: z.boolean(),
  fingerprintRegistered: z.boolean(),
  fingerprintPreview: z.string().nullable(),
  subject: z.string().nullable(),
});

export const whmcsValidatePlanRequestSchema = z.object({
  planSlug: z.string().min(1).max(64),
});

export const whmcsValidatePlanResponseSchema = z.object({
  valid: z.boolean(),
  planSlug: z.string(),
  plan: whmcsPlanCatalogItemSchema.nullable(),
});

export type WhmcsRegisterMtlsRequest = z.infer<typeof whmcsRegisterMtlsRequestSchema>;
export type WhmcsMtlsStatusResponse = z.infer<typeof whmcsMtlsStatusResponseSchema>;
export type WhmcsValidatePlanResponse = z.infer<typeof whmcsValidatePlanResponseSchema>;
