/**
 * Layout Zod Validation Schemas
 * Inspired by Rackula's schema architecture
 * Schema v1.0.0 - Flat structure with plant-specific fields
 */

import { z } from 'zod';

// =============================================================================
// Constants & Patterns
// =============================================================================

/**
 * Slug pattern: lowercase alphanumeric with hyphens, no leading/trailing/consecutive hyphens
 */
const SLUG_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;

/**
 * Hex colour pattern: 6-character hex with # prefix
 */
const HEX_COLOUR_PATTERN = /^#[0-9a-fA-F]{6}$/;

// =============================================================================
// Enums
// =============================================================================

/**
 * Plant category types for library organization
 */
export const PlantCategorySchema = z.enum([
    'VEG',
    'FLOWER',
    'MOTHER',
    'CLONE',
    'SEEDLING',
]);
export type PlantCategory = z.infer<typeof PlantCategorySchema>;

/**
 * Section subtype - preserves visual diversity while using unified Rack concept
 */
export const SectionSubtypeSchema = z.enum([
    'TABLE',
    'RACK',
    'TRAY',
    'HANGER',
    'FLOOR',
]);
export type SectionSubtype = z.infer<typeof SectionSubtypeSchema>;

/**
 * Position status
 */
export const PositionStatusSchema = z.enum([
    'EMPTY',
    'OCCUPIED',
    'RESERVED',
    'DAMAGED',
]);
export type PositionStatus = z.infer<typeof PositionStatusSchema>;

// =============================================================================
// Core Schemas
// =============================================================================

/**
 * Slug schema for plant type identification
 */
export const SlugSchema = z
    .string()
    .min(1, 'Slug is required')
    .max(100, 'Slug must be 100 characters or less')
    .regex(
        SLUG_PATTERN,
        'Slug must be lowercase with hyphens only (no leading/trailing/consecutive)'
    );

/**
 * Plant Type - template definition in library
 * Analogous to Rackula's DeviceType
 */
export const PlantTypeSchema = z.object({
    // --- Core Identity ---
    slug: SlugSchema,
    name: z.string().min(1, 'Name is required').max(100),
    strain: z.string().max(100).optional(),

    // --- Classification ---
    category: PlantCategorySchema,

    // --- Visual Properties ---
    colour: z
        .string()
        .regex(HEX_COLOUR_PATTERN, 'Color must be valid hex (e.g., #4A90D9)'),

    // --- Growth Properties ---
    growthDays: z.number().int().positive().optional(),
    yieldGrams: z.number().positive().optional(),

    // --- Metadata ---
    notes: z.string().optional(),
    tags: z.array(z.string()).optional(),
    customFields: z.record(z.string(), z.unknown()).optional(),
});
export type PlantType = z.infer<typeof PlantTypeSchema>;

/**
 * Placed Plant - instance at a specific position
 * Analogous to Rackula's PlacedDevice
 */
export const PlacedPlantSchema = z.object({
    // --- Identity ---
    id: z.string().uuid(),
    plantTypeSlug: z.string().min(1, 'Plant type slug is required'),

    // --- Position ---
    row: z.number().int().min(0),
    column: z.number().int().min(0),
    tier: z.number().int().min(1).default(1),
    slot: z.number().int().min(1).default(1),

    // --- Overrides ---
    name: z.string().optional(),
    colourOverride: z.string().regex(HEX_COLOUR_PATTERN).optional(),

    // --- Metadata ---
    notes: z.string().optional(),
    customFields: z.record(z.string(), z.unknown()).optional(),
});
export type PlacedPlant = z.infer<typeof PlacedPlantSchema>;

/**
 * Rack/Section - container structure for plants
 * Analogous to Rackula's Rack, with subtype for visual variety
 */
export const RackSchema = z.object({
    // --- Identity ---
    id: z.string().uuid(),
    name: z.string().min(1),
    code: z.string().max(20).optional(),

    // --- Type (hybrid approach) ---
    subtype: SectionSubtypeSchema.default('RACK'),

    // --- Dimensions ---
    rows: z.number().int().min(1).max(100),
    columns: z.number().int().min(1).max(100),
    tiers: z.number().int().min(1).max(10).default(1),
    spacing: z.number().positive().optional(), // inches between positions

    // --- Position on floor ---
    posX: z.number(),
    posY: z.number(),
    width: z.number().positive(),
    height: z.number().positive(),

    // --- Contents ---
    plants: z.array(PlacedPlantSchema).default([]),

    // --- Metadata ---
    notes: z.string().optional(),
});
export type Rack = z.infer<typeof RackSchema>;

/**
 * Room Layout - complete room state
 */
export const RoomLayoutSchema = z.object({
    // --- Identity ---
    id: z.string().uuid(),
    name: z.string().min(1),
    code: z.string().max(20).optional(),
    type: z.enum(['VEG', 'FLOWER', 'DRY', 'CURE', 'MOTHER', 'CLONE', 'FACILITY']),

    // --- Position on floor ---
    posX: z.number(),
    posY: z.number(),
    width: z.number().positive(),
    height: z.number().positive(),
    rotation: z.number().default(0),

    // --- Visual ---
    color: z.string().regex(HEX_COLOUR_PATTERN).optional(),

    // --- Contents ---
    racks: z.array(RackSchema).default([]),
});
export type RoomLayout = z.infer<typeof RoomLayoutSchema>;

/**
 * Floor Layout - complete floor state for serialization
 */
export const FloorLayoutSchema = z.object({
    // --- Metadata ---
    version: z.string().default('1.0.0'),
    name: z.string(),

    // --- Floor dimensions ---
    width: z.number().positive(),
    height: z.number().positive(),
    ceilingHeight: z.number().positive().optional(),

    // --- Contents ---
    rooms: z.array(RoomLayoutSchema),

    // --- Plant Type Library ---
    plantTypes: z.array(PlantTypeSchema).default([]),
});
export type FloorLayout = z.infer<typeof FloorLayoutSchema>;

// =============================================================================
// Helper Types for Creation
// =============================================================================

/**
 * Helper type for creating a PlantType
 */
export const CreatePlantTypeSchema = PlantTypeSchema.omit({
    slug: true,
}).extend({
    name: z.string().min(1),
});
export type CreatePlantTypeData = z.infer<typeof CreatePlantTypeSchema>;

/**
 * Helper type for updating a PlantType
 */
export const UpdatePlantTypeSchema = PlantTypeSchema.partial().omit({
    slug: true,
});
export type UpdatePlantTypeData = z.infer<typeof UpdatePlantTypeSchema>;

// =============================================================================
// Utility Functions
// =============================================================================

/**
 * Generate a slug from a name
 */
export function generateSlug(name: string): string {
    return name
        .toLowerCase()
        .replace(/[^a-z0-9]+/g, '-')
        .replace(/^-+|-+$/g, '')
        .replace(/-+/g, '-');
}

/**
 * Validates that all slugs in an array are unique
 */
export function validateSlugUniqueness(items: { slug: string }[]): string[] {
    const slugCounts = new Map<string, number>();

    for (const item of items) {
        slugCounts.set(item.slug, (slugCounts.get(item.slug) ?? 0) + 1);
    }

    const duplicates: string[] = [];
    for (const [slug, count] of slugCounts) {
        if (count > 1) {
            duplicates.push(slug);
        }
    }

    return duplicates;
}
