/**
 * Zod validation schemas for infrastructure documentation types
 */

import { z } from 'zod'

// Region enum
export const regionSchema = z.enum([
  'Africa (Sub-Saharan)',
  'Middle East & North Africa',
  'Americas',
  'Asia-Pacific',
  'Europe',
])

// Relationship type enum
export const relationshipTypeSchema = z.enum([
  'Full Diplomatic Relations',
  'Official (Non-Diplomatic)',
  'Ambassador Level',
  'Full Diplomatic Relations (Special Mission)',
])

// Priority enum
export const prioritySchema = z.enum(['Critical', 'High', 'Medium', 'Low'])

// Compliance status enum
export const complianceStatusSchema = z.enum([
  'Compliant',
  'Partial',
  'Pending',
  'Non-Compliant',
])

// Deployment status enum
export const deploymentStatusSchema = z.enum([
  'Planned',
  'In Progress',
  'Complete',
  'Blocked',
])

// Cost category enum
export const costCategorySchema = z.enum([
  'Infrastructure',
  'Network',
  'Compliance',
  'Operations',
])

// Topology node type enum
export const topologyNodeTypeSchema = z.enum([
  'region',
  'datacenter',
  'tunnel',
  'vm',
  'service',
])

// Topology edge type enum
export const topologyEdgeTypeSchema = z.enum(['tunnel', 'peering', 'network-route'])

// Coordinates schema
export const coordinatesSchema = z
  .object({
    lat: z.number().min(-90).max(90),
    lng: z.number().min(-180).max(180),
  })
  .optional()

// Country schema
export const countrySchema = z.object({
  name: z.string().min(1, 'Country name is required'),
  region: regionSchema,
  relationshipType: relationshipTypeSchema,
  priority: prioritySchema,
  cloudflareCoverage: z.boolean(),
  networkInfrastructurePriority: z.string().min(1),
  notes: z.string().optional(),
  coordinates: coordinatesSchema,
})

// Topology node schema
export const topologyNodeSchema = z.object({
  id: z.string().min(1, 'Node ID is required'),
  type: topologyNodeTypeSchema,
  label: z.string().min(1, 'Node label is required'),
  region: z.string().min(1, 'Region is required'),
  entity: z.string().min(1, 'Entity is required'),
  position: z.object({
    x: z.number(),
    y: z.number(),
  }),
  metadata: z.record(z.any()).default({}),
})

// Topology edge schema
export const topologyEdgeSchema = z.object({
  id: z.string().min(1, 'Edge ID is required'),
  source: z.string().min(1, 'Source node ID is required'),
  target: z.string().min(1, 'Target node ID is required'),
  type: topologyEdgeTypeSchema,
  metadata: z.record(z.any()).default({}),
})

// Network topology schema
export const networkTopologySchema = z.object({
  nodes: z.array(topologyNodeSchema).min(0),
  edges: z.array(topologyEdgeSchema).min(0),
  region: z.string().min(1, 'Region is required'),
  entity: z.string().min(1, 'Entity is required'),
  lastUpdated: z.string().datetime({ message: 'Invalid datetime format' }),
})

// Compliance requirement schema
export const complianceRequirementSchema = z.object({
  country: z.string().min(1, 'Country is required'),
  region: regionSchema,
  frameworks: z.array(z.string().min(1)).min(1, 'At least one framework is required'),
  status: complianceStatusSchema,
  requirements: z.array(z.string()).min(0),
  lastAuditDate: z.string().datetime().optional(),
  notes: z.string().optional(),
})

// Deployment milestone schema with date validation
export const deploymentMilestoneSchema = z
  .object({
    id: z.string().min(1, 'Milestone ID is required'),
    title: z.string().min(1, 'Title is required'),
    region: z.string().min(1, 'Region is required'),
    entity: z.string().min(1, 'Entity is required'),
    priority: prioritySchema,
    startDate: z.string().datetime({ message: 'Invalid start date format' }),
    endDate: z.string().datetime({ message: 'Invalid end date format' }),
    status: deploymentStatusSchema,
    dependencies: z.array(z.string()).optional(),
    cost: z.number().min(0, 'Cost must be non-negative').optional(),
    description: z.string().optional(),
  })
  .refine(
    (data) => {
      const start = new Date(data.startDate)
      const end = new Date(data.endDate)
      return end > start
    },
    {
      message: 'End date must be after start date',
      path: ['endDate'],
    }
  )

// Cost breakdown schema
export const costBreakdownSchema = z.object({
  compute: z.number().min(0).optional(),
  storage: z.number().min(0).optional(),
  network: z.number().min(0).optional(),
  licenses: z.number().min(0).optional(),
  personnel: z.number().min(0).optional(),
})

// Cost estimate schema with breakdown validation
export const costEstimateSchema = z
  .object({
    region: z.string().min(1, 'Region is required'),
    entity: z.string().min(1, 'Entity is required'),
    category: costCategorySchema,
    monthly: z.number().min(0, 'Monthly cost must be non-negative'),
    annual: z.number().min(0, 'Annual cost must be non-negative'),
    breakdown: costBreakdownSchema,
    currency: z.string().optional(),
    lastUpdated: z.string().datetime().optional(),
  })
  .refine(
    (data) => {
      const breakdownSum =
        (data.breakdown.compute || 0) +
        (data.breakdown.storage || 0) +
        (data.breakdown.network || 0) +
        (data.breakdown.licenses || 0) +
        (data.breakdown.personnel || 0)
      // Allow small floating point differences
      return Math.abs(breakdownSum - data.monthly) < 0.01
    },
    {
      message: 'Breakdown sum must equal monthly cost',
      path: ['breakdown'],
    }
  )
  .refine(
    (data) => {
      // Annual should be approximately monthly * 12 (allow small differences)
      const expectedAnnual = data.monthly * 12
      return Math.abs(data.annual - expectedAnnual) < 0.01
    },
    {
      message: 'Annual cost should be approximately monthly * 12',
      path: ['annual'],
    }
  )

// Infrastructure summary schema
export const infrastructureSummarySchema = z.object({
  totalCountries: z.number().int().min(0),
  totalRegions: z.number().int().min(0),
  totalCost: z.number().min(0),
  deploymentProgress: z.object({
    planned: z.number().int().min(0),
    inProgress: z.number().int().min(0),
    complete: z.number().int().min(0),
    blocked: z.number().int().min(0),
  }),
})

// Input schemas for mutations

// Update topology input
export const updateTopologyInputSchema = z.object({
  nodes: z.array(topologyNodeSchema).optional(),
  edges: z.array(topologyEdgeSchema).optional(),
  region: z.string().min(1).optional(),
  entity: z.string().min(1).optional(),
  lastUpdated: z.string().datetime().optional(),
})

// Create milestone input
export const createMilestoneInputSchema = deploymentMilestoneSchema.omit({ id: true })

// Update milestone input
export const updateMilestoneInputSchema = deploymentMilestoneSchema.partial().required({ id: true })

// Update compliance input
export const updateComplianceInputSchema = complianceRequirementSchema.partial().required({
  country: true,
})

// Update cost estimate input
export const updateCostEstimateInputSchema = costEstimateSchema
  .partial()
  .required({ region: true, entity: true, category: true })

// Type exports for TypeScript inference
export type CountryInput = z.infer<typeof countrySchema>
export type TopologyNodeInput = z.infer<typeof topologyNodeSchema>
export type TopologyEdgeInput = z.infer<typeof topologyEdgeSchema>
export type NetworkTopologyInput = z.infer<typeof networkTopologySchema>
export type ComplianceRequirementInput = z.infer<typeof complianceRequirementSchema>
export type DeploymentMilestoneInput = z.infer<typeof deploymentMilestoneSchema>
export type CostEstimateInput = z.infer<typeof costEstimateSchema>
export type InfrastructureSummaryInput = z.infer<typeof infrastructureSummarySchema>
export type UpdateTopologyInput = z.infer<typeof updateTopologyInputSchema>
export type CreateMilestoneInput = z.infer<typeof createMilestoneInputSchema>
export type UpdateMilestoneInput = z.infer<typeof updateMilestoneInputSchema>
export type UpdateComplianceInput = z.infer<typeof updateComplianceInputSchema>
export type UpdateCostEstimateInput = z.infer<typeof updateCostEstimateInputSchema>

