import { z } from "zod";

export const userRoles = ["admin", "editor", "viewer"] as const;

export const fieldTypeEnum = z.enum([
  "text",
  "number",
  "boolean",
  "select",
  "rich-text",
  "image",
  "video",
  "audio",
  "date",
  "multi-select",
  "color"
]);

export const normalizeGroupName = (name: string): string => {
  let words = name.split(/[\s\-_]+/);
  if (words.length === 1) {
    words = words[0]
      .replace(/([a-z0-9])([A-Z])/g, '$1 $2')
      .replace(/([a-zA-Z])(\d)/g, '$1 $2')
      .replace(/([a-z])([a-z]*)/gi, (match, first, rest) => `${first}${rest.toLowerCase()}`)
      .split(/\s+/);
  }

  words = words
    .filter(word => word.length > 0)
    .map(word => word.toLowerCase());

  if (words.length === 0) return '';

  return words[0] + words.slice(1)
    .map(word => word.charAt(0).toUpperCase() + word.slice(1))
    .join('');
};

// Base schemas and types
export const validationSchema = z.object({
  required: z.boolean().default(false),
  min: z.number().optional(),
  max: z.number().optional(),
  pattern: z.string().optional(),
  customError: z.string().optional()
}).optional();

export const fieldSchema = z.object({
  id: z.string(),
  name: z.string().min(1, "Field name is required"),
  label: z.string(),
  type: fieldTypeEnum,
  description: z.string().optional(),
  defaultValue: z.any().optional(),
  options: z.array(z.string()).optional(),
  validation: validationSchema,
  step: z.number().optional(),
  groupId: z.string().optional()
});

export const groupSchema = z.object({
  id: z.string(),
  name: z.string(),
  description: z.string().optional(),
  order: z.number(),
  fieldIds: z.array(z.string()),
  normalizedName: z.string().optional()
});

export const templateSchema = z.object({
  id: z.string(),
  name: z.string(),
  description: z.string(),
  type: z.string(),
  fields: z.array(fieldSchema),
  groups: z.record(z.string(), groupSchema),
  ungroupedFieldIds: z.array(z.string()),
  groupOrder: z.array(z.string()),
  createdBy: z.string(),
  createdAt: z.number(),
  updatedAt: z.number(),
  version: z.number().default(1),
  settings: z.object({
    cacheStrategy: z.enum(["memory", "local", "none"]).default("memory"),
    syncInterval: z.number().optional(),
    offlineSupport: z.boolean().default(false),
  }).default({
    cacheStrategy: "memory",
    offlineSupport: false
  })
});

export const templateValuesSchema = z.object({
  groups: z.record(z.string(), z.record(z.string(), z.any())).default({}),
  ungrouped: z.record(z.string(), z.any()).default({}),
  _template: z.object({
    id: z.string(),
    version: z.number()
  }).optional()
});

// Content schema with data field
const baseContentSchema = z.object({
  id: z.string(),
  title: z.string(),
  description: z.string(),
  type: z.enum(["text", "image", "video", "template"]),
  mediaUrl: z.string().optional(),
  projectIds: z.array(z.string()).default([]),
  createdBy: z.string(),
  createdAt: z.number(),
  updatedAt: z.number(),
  templateId: z.string().optional(),
  templateValues: templateValuesSchema.optional(),
  templateVersion: z.number().optional(),
  version: z.number().default(1),
  status: z.enum(["published", "draft", "archived"]).default("draft"),
  metadata: z.record(z.string(), z.any()).default({}),
  data: z.record(z.string(), z.any()).optional()
});

export const contentSchema = z.preprocess((data: any) => {
  if (typeof data !== 'object' || data === null) return data;

  const processed = { ...data };
  if (processed.published === true) {
    processed.status = "published";
  }
  delete processed.published;
  return processed;
}, baseContentSchema);

// Export types
export type Content = z.infer<typeof baseContentSchema>;
export type Field = z.infer<typeof fieldSchema>;
export type Group = z.infer<typeof groupSchema>;
export type Template = z.infer<typeof templateSchema>;
export type FieldType = z.infer<typeof fieldTypeEnum>;
export type TemplateValues = z.infer<typeof templateValuesSchema>;

export interface KioskConfig {
  projectId: string;
  apiKey: string;
  authDomain?: string;
  offlineSupport?: boolean;
  cacheStrategy?: "memory" | "local" | "none";
  syncInterval?: number;
  cacheMaxAge?: number;
}

export interface CacheOptions {
  ttl?: number;
  strategy?: "memory" | "local" | "none";
  validateOnLoad?: boolean;
}

export interface SyncOptions {
  force?: boolean;
  onProgress?: (progress: number) => void;
  onError?: (error: Error) => void;
  retryAttempts?: number;
}

export interface GroupedTemplateContent {
  group: Group & { normalizedName: string };
  fields: Field[];
  values: Record<string, any>;
}

export interface TemplateContentStructure {
  groups: GroupedTemplateContent[];
  ungroupedFields: {
    fields: Field[];
    values: Record<string, any>;
  };
}

export interface ContentHookResult {
  content: Content | null;
  template: Template | null;
  loading: boolean;
  error: Error | null;
  isOnline: boolean;
  refresh?: () => void;
}