import { z } from 'zod'

/**
 * Domain Configuration Schema (domain.json)
 * 
 * Configuration for custom domains on DevDoc projects.
 * Each project can have ONE custom domain for free.
 */

// ============================================================================
// Domain Validation Helpers
// ============================================================================

/**
 * Valid domain pattern - allows subdomains like docs.example.com
 * Does NOT allow:
 * - IP addresses
 * - Ports
 * - Paths
 * - Protocol prefixes
 */
const domainRegex = /^(?!-)[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*\.[a-zA-Z]{2,}$/

/**
 * Reserved domains that cannot be used as custom domains
 */
const RESERVED_DOMAINS = [
  'devdoc.sh',
  'devdoc.io',
  'devdoc.com',
  'localhost',
]

// ============================================================================
// SEO Schema
// ============================================================================

const domainSeoSchema = z.object({
  /**
   * Canonical URL for SEO - tells search engines this is the primary URL
   * Should match your custom domain with https://
   */
  canonical: z.string().url().optional(),
})

// ============================================================================
// Settings Schema
// ============================================================================

const domainSettingsSchema = z.object({
  /**
   * Force HTTPS redirects (recommended, default: true)
   */
  forceHttps: z.boolean().default(true),
  
  /**
   * WWW redirect preference
   * - "www": Redirect non-www to www (example.com → www.example.com)
   * - "non-www": Redirect www to non-www (www.example.com → example.com)
   * - "none": No redirect, accept both
   */
  wwwRedirect: z.enum(['www', 'non-www', 'none']).default('none'),
})

// ============================================================================
// Main Domain Configuration Schema
// ============================================================================

export const domainConfigSchema = z.object({
  /**
   * JSON Schema reference (optional)
   */
  $schema: z.string().optional(),
  
  /**
   * The custom domain for this project
   * Example: "docs.example.com" or "developer.mycompany.io"
   * 
   * Rules:
   * - Must be a valid domain name
   * - Cannot be a DevDoc domain (*.devdoc.sh)
   * - One custom domain per project (free)
   */
  customDomain: z.string()
    .min(4, 'Domain must be at least 4 characters')
    .max(253, 'Domain must be 253 characters or less')
    .regex(domainRegex, 'Invalid domain format. Example: docs.example.com')
    .refine(
      (domain) => !RESERVED_DOMAINS.some(reserved => 
        domain === reserved || domain.endsWith(`.${reserved}`)
      ),
      'Cannot use a reserved DevDoc domain'
    ),
  
  /**
   * SEO configuration for the custom domain
   */
  seo: domainSeoSchema.optional(),
  
  /**
   * Domain behavior settings
   */
  settings: domainSettingsSchema.optional(),
})

// ============================================================================
// Types
// ============================================================================

export type DomainConfig = z.infer<typeof domainConfigSchema>
export type DomainSeoConfig = z.infer<typeof domainSeoSchema>
export type DomainSettings = z.infer<typeof domainSettingsSchema>

// ============================================================================
// Domain Status Types (for API/storage)
// ============================================================================

/**
 * Status of a custom domain in the system
 */
export type DomainStatus = 
  | 'pending'           // Domain added, awaiting DNS configuration
  | 'dns_verified'      // DNS records verified, awaiting SSL
  | 'ssl_provisioning'  // SSL certificate being provisioned
  | 'active'            // Domain is live and working
  | 'error'             // Configuration error

/**
 * Custom domain entry stored in the registry
 */
export interface CustomDomainEntry {
  /** The custom domain (e.g., "docs.example.com") */
  customDomain: string
  
  /** The project slug this domain points to */
  projectSlug: string
  
  /** Current status of the domain */
  status: DomainStatus
  
  /** Vercel domain ID (from Vercel API) */
  vercelDomainId?: string
  
  /** TXT record value for domain ownership verification */
  verificationToken?: string
  
  /** When the domain was added */
  createdAt: string
  
  /** When DNS was verified */
  verifiedAt?: string
  
  /** Last time status was checked */
  lastCheckedAt?: string
  
  /** Error message if status is "error" */
  errorMessage?: string
  
  /** Domain settings from domain.json */
  settings?: DomainSettings
}

// ============================================================================
// Validation Functions
// ============================================================================

/**
 * Parse and validate domain configuration
 */
export function parseDomainConfig(data: unknown): DomainConfig {
  const result = domainConfigSchema.safeParse(data)
  
  if (!result.success) {
    const issues = result.error.issues || []
    const errors = issues.map((e) => 
      `${e.path.map(String).join('.')}: ${e.message}`
    ).join('\n')
    throw new Error(`Invalid domain.json configuration:\n${errors}`)
  }
  
  return result.data
}

/**
 * Safe parse that returns null on failure
 */
export function safeParseDomainConfig(data: unknown): DomainConfig | null {
  const result = domainConfigSchema.safeParse(data)
  return result.success ? result.data : null
}

/**
 * Validate a domain string format
 */
export function isValidDomain(domain: string): { valid: boolean; error?: string } {
  if (!domain) {
    return { valid: false, error: 'Domain is required' }
  }
  
  if (domain.length < 4) {
    return { valid: false, error: 'Domain must be at least 4 characters' }
  }
  
  if (domain.length > 253) {
    return { valid: false, error: 'Domain must be 253 characters or less' }
  }
  
  if (!domainRegex.test(domain)) {
    return { valid: false, error: 'Invalid domain format. Example: docs.example.com' }
  }
  
  // Check reserved domains
  if (RESERVED_DOMAINS.some(reserved => 
    domain === reserved || domain.endsWith(`.${reserved}`)
  )) {
    return { valid: false, error: 'Cannot use a reserved DevDoc domain' }
  }
  
  return { valid: true }
}

/**
 * Normalize a domain (lowercase, trim, remove protocol/path)
 */
export function normalizeDomain(domain: string): string {
  let normalized = domain.toLowerCase().trim()
  
  // Remove protocol if present
  normalized = normalized.replace(/^https?:\/\//, '')
  
  // Remove path if present
  normalized = normalized.split('/')[0]
  
  // Remove port if present
  normalized = normalized.split(':')[0]
  
  return normalized
}

/**
 * Get DNS instructions for a custom domain
 */
export function getDnsInstructions(customDomain: string): {
  cname: { name: string; value: string }
  txt: { name: string; value: string }
} {
  const parts = customDomain.split('.')
  const subdomain = parts.length > 2 ? parts[0] : '@'
  
  return {
    cname: {
      name: subdomain === '@' ? customDomain : subdomain,
      value: 'cname.devdoc-dns.com',
    },
    txt: {
      name: `_devdoc-verify.${customDomain}`,
      value: '', // Will be filled with actual verification token
    },
  }
}
