// Zod Validation Schemas for Direct PostgreSQL Shim
// Ensures data integrity and schema compliance without CMS dependency

import { z } from 'zod';

/**
 * SITES SCHEMA
 * Mirrors init_sites.sql migration with strict validation
 */
export const SiteConfigSchema = z.object({
    site_name: z.string().optional(),
    primary_color: z.string().regex(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/, "Invalid hex color").optional(),
    logo_url: z.string().url().optional(),
    template_id: z.string().default('minimal'),
    features: z.array(z.string()).default([]),
    seo: z.object({
        defaultTitle: z.string().max(70).optional(),
        defaultDesc: z.string().max(160).optional(),
        keywords: z.array(z.string()).optional(),
    }).optional(),
});

export const SiteSchema = z.object({
    id: z.string().uuid().optional(), // Optional for create, required for update
    domain: z.string()
        .min(3, "Domain must be at least 3 characters")
        .max(255, "Domain too long")
        .regex(/^[a-z0-9.-]+$/, "Invalid domain format (lowercase, numbers, dots, hyphens only)"),
    status: z.enum(['active', 'inactive', 'pending', 'maintenance', 'archived']).default('pending'),
    site_url: z.string().url().optional().or(z.literal('')),
    site_wpjson: z.string().url().optional().or(z.literal('')),
    client_id: z.string().uuid().optional(),
    config: SiteConfigSchema.default({}),
});

export type SiteInput = z.infer<typeof SiteSchema>;
export type SiteConfig = z.infer<typeof SiteConfigSchema>;

/**
 * ARTICLES/POSTS SCHEMA (Perfect SEO Enforcement)
 * Ensures every post has complete SEO metadata
 */
export const SEODataSchema = z.object({
    title: z.string()
        .min(10, "SEO title too short")
        .max(70, "SEO title too long (max 70 chars for Google)"),
    description: z.string()
        .min(50, "SEO description too short")
        .max(160, "SEO description too long (max 160 chars)"),
    keywords: z.array(z.string()).max(10, "Too many keywords").optional(),
    og_image: z.string().url().optional(),
    og_type: z.string().default('article'),
    canonical_url: z.string().url().optional(),
    schema_markup: z.record(z.any()).optional(), // JSON-LD schema
});

export const ArticleSchema = z.object({
    id: z.string().uuid().optional(),
    site_id: z.string().uuid("Invalid site_id"),
    title: z.string()
        .min(1, "Title required")
        .max(255, "Title too long"),
    slug: z.string()
        .min(1, "Slug required")
        .regex(/^[a-z0-9-]+$/, "Slug must be lowercase alphanumeric with hyphens"),
    content: z.string().min(100, "Content too short (minimum 100 characters)"),
    excerpt: z.string().max(500).optional(),
    status: z.enum(['queued', 'processing', 'qc', 'approved', 'published', 'draft']).default('draft'),
    is_published: z.boolean().default(false),
    published_at: z.date().optional(),
    author_id: z.string().uuid().optional(),

    // PERFECT SEO - Required for published articles
    seo_data: SEODataSchema,

    // Optional metadata
    tags: z.array(z.string()).optional(),
    categories: z.array(z.string()).optional(),
    featured_image: z.string().url().optional(),
});

export type ArticleInput = z.infer<typeof ArticleSchema>;
export type SEOData = z.infer<typeof SEODataSchema>;

/**
 * CAMPAIGNS SCHEMA
 */
export const CampaignSchema = z.object({
    id: z.string().uuid().optional(),
    name: z.string().min(3).max(255),
    status: z.enum(['active', 'paused', 'completed', 'archived']).default('active'),
    target_sites: z.array(z.string().uuid()).min(1, "At least one target site required"),
    campaign_config: z.object({
        target_count: z.number().int().positive().optional(),
        schedule: z.string().optional(),
        priority: z.enum(['low', 'medium', 'high']).default('medium'),
    }).optional(),
});

export type CampaignInput = z.infer<typeof CampaignSchema>;

/**
 * PAGES SCHEMA
 * For static landing pages with routes
 */
export const PageSchema = z.object({
    id: z.string().uuid().optional(),
    site_id: z.string().uuid("Invalid site_id"),
    name: z.string().min(1, "Name required").max(255, "Name too long"),
    route: z.string()
        .min(1, "Route required")
        .regex(/^\/[a-z0-9-\/]*$/, "Route must start with / and contain only lowercase letters, numbers, hyphens, and slashes"),
    html_content: z.string().optional(),
    meta_title: z.string().max(70, "Meta title too long").optional(),
    meta_description: z.string().max(160, "Meta description too long").optional(),
    status: z.enum(['draft', 'published', 'archived']).default('draft'),
    published_at: z.date().optional(),
});

export type PageInput = z.infer<typeof PageSchema>;

/**
 * GENERATION JOB SCHEMA
 */
export const GenerationJobSchema = z.object({
    id: z.string().uuid().optional(),
    site_id: z.string().uuid(),
    campaign_id: z.string().uuid().optional(),
    status: z.enum(['pending', 'processing', 'completed', 'failed']).default('pending'),
    total_count: z.number().int().min(1).max(10000),
    current_offset: z.number().int().min(0).default(0),
    error_message: z.string().optional(),
    job_config: z.record(z.any()).optional(),
});

export type GenerationJobInput = z.infer<typeof GenerationJobSchema>;

/**
 * PARTIAL UPDATE SCHEMAS
 * For PATCH operations where not all fields are required
 */
export const PartialSiteSchema = SiteSchema.partial().required({ id: true });
export const PartialArticleSchema = ArticleSchema.partial().required({ id: true });
export const PartialCampaignSchema = CampaignSchema.partial().required({ id: true });
export const PartialPageSchema = PageSchema.partial().required({ id: true });

/**
 * QUERY FILTER SCHEMAS
 * Validates filter parameters for list endpoints
 */
export const SiteFilterSchema = z.object({
    limit: z.number().int().min(1).max(1000).default(50),
    offset: z.number().int().min(0).default(0),
    status: z.enum(['active', 'inactive', 'pending', 'maintenance', 'archived']).optional(),
    search: z.string().max(255).optional(),
    client_id: z.string().uuid().optional(),
});

export const ArticleFilterSchema = z.object({
    limit: z.number().int().min(1).max(1000).default(50),
    offset: z.number().int().min(0).default(0),
    status: z.enum(['queued', 'processing', 'qc', 'approved', 'published', 'draft']).optional(),
    search: z.string().max(255).optional(),
    site_id: z.string().uuid().optional(),
    is_published: z.boolean().optional(),
});

export type SiteFilter = z.infer<typeof SiteFilterSchema>;
export type ArticleFilter = z.infer<typeof ArticleFilterSchema>;

/**
 * VALIDATION HELPERS
 */

/**
 * Safe parse with detailed error messages
 */
export function validateOrThrow<T>(schema: z.ZodSchema<T>, data: unknown, context: string): T {
    const result = schema.safeParse(data);

    if (!result.success) {
        const errors = result.error.errors.map(e => `${e.path.join('.')}: ${e.message}`).join(', ');
        throw new Error(`Validation failed for ${context}: ${errors}`);
    }

    return result.data;
}

/**
 * Validate for database INSERT (all required fields must be present)
 */
export function validateForCreate<T>(schema: z.ZodSchema<T>, data: unknown, entityName: string): T {
    return validateOrThrow(schema, data, `${entityName} creation`);
}

/**
 * Validate for database UPDATE (partial fields allowed)
 */
export function validateForUpdate<T>(schema: z.ZodSchema<T>, data: unknown, entityName: string): T {
    return validateOrThrow(schema, data, `${entityName} update`);
}
