/**
 * @fileoverview Zod schemas and TypeScript types for tab system data validation and type safety.
 *
 * This module provides comprehensive type definitions and runtime validation schemas for:
 * - Tab location history management
 * - Tab metadata with history configuration
 * - Tab entity creation, updates, and persistence
 * - Schema validation for all tab-related operations
 *
 * The schemas ensure data integrity while TypeScript interfaces provide compile-time
 * type safety. Separate types are provided for different use cases (creation, updates,
 * persistence) to maintain strict typing throughout the application.
 */

import { z } from 'zod';

/**
 * Schema for validating tab location entries.
 *
 * Each location represents a navigation point in a tab's history,
 * capturing the URL, page title, and timestamp for later navigation.
 */
export const TabLocationSchema = z.object({
  /** Timestamp when this location was visited (milliseconds since epoch) */
  timestamp: z.number(),
  /** Human-readable page title */
  title: z.string(),
  /** Full URL of the location */
  url: z.string(),
});

/** TypeScript type for tab location entries */
export type TabLocation = z.infer<typeof TabLocationSchema>;

/**
 * Schema for tab location history management.
 *
 * Tracks navigation history with a current index pointing to the
 * active location in the history array. Supports back/forward navigation.
 */
export const TabLocationHistorySchema = z.object({
  /** Current index in the locations array (-1 for empty history) */
  current: z.number(),
  /** Array of location history entries */
  locations: z.array(TabLocationSchema),
});

/** TypeScript type for tab location history */
export type TabLocationHistory = z.infer<typeof TabLocationHistorySchema>;

/**
 * Base schema for tab metadata (arbitrary key-value pairs).
 *
 * Allows storing custom data associated with tabs. Defaults to empty object.
 */
export const TabMetadataSchema = z.record(z.unknown()).default({});

/** TypeScript type for basic tab metadata */
export type TabMetadata = z.infer<typeof TabMetadataSchema>;

/**
 * Extended metadata schema supporting history configuration overrides.
 *
 * Allows individual tabs to override global history limits and behavior.
 * Uses passthrough() to preserve other metadata properties not defined here.
 */
export const TabMetadataWithHistorySchema = z
  .object({
    /** Override for maximum history size (1-1000 entries) */
    maxHistorySize: z.number().min(1).max(1000).optional(),
    /** Override for maximum forward history (0-100 entries) */
    maxForwardHistory: z.number().min(0).max(100).optional(),
  })
  .passthrough()
  .default({});

/** TypeScript type for metadata with history configuration */
export type TabMetadataWithHistory = z.infer<
  typeof TabMetadataWithHistorySchema
>;

/**
 * Schema for tab tags (array of strings).
 *
 * Tags can be used for categorization, filtering, or custom tab organization.
 */
export const TabTagsSchema = z.array(z.string()).default([]);

/** TypeScript type for tab tags */
export type TabTags = z.infer<typeof TabTagsSchema>;

/**
 * Base schema for tab validation (runtime validation only).
 *
 * This schema is primarily used for validation purposes. For NgRx entities,
 * use the separate Tab interface which ensures required properties.
 */
export const TabSchema = z.object({
  /** Unique identifier for the tab */
  id: z.number(),
  /** Display name for the tab (minimum 1 character) */
  name: z.string().default('Neuer Vorgang'),
  /** Subtitle for the tab */
  subtitle: z.string().default(''),
  /** Creation timestamp (milliseconds since epoch) */
  createdAt: z.number(),
  /** Last activation timestamp (optional) */
  activatedAt: z.number().optional(),
  /** Custom metadata for the tab */
  metadata: TabMetadataSchema,
  /** Navigation history for the tab */
  location: TabLocationHistorySchema,
  /** Array of tags for organization */
  tags: TabTagsSchema,
});

/**
 * NgRx-compatible Tab interface with strict typing.
 *
 * This interface ensures all required properties are present for NgRx entity
 * operations. Separates compile-time typing from runtime validation.
 */
export interface Tab {
  /** Unique identifier (required for NgRx entities) */
  id: number;
  /** Display name for the tab */
  name: string;
  /** Subtitle for the tab */
  subtitle: string;
  /** Creation timestamp */
  createdAt: number;
  /** Last activation timestamp */
  activatedAt?: number;
  /** Custom metadata object */
  metadata: Record<string, unknown>;
  /** Navigation history state */
  location: TabLocationHistory;
  /** Organization tags */
  tags: string[];
}

/**
 * Type for creating new tabs where id can be auto-generated.
 *
 * Used when creating tabs where the ID might be generated by the system.
 * All other properties are required for proper tab initialization.
 */
export interface TabCreate {
  /** Optional ID (can be generated if not provided) */
  id?: number;
  /** Display name for the tab */
  name: string;
  /** Subtitle for the tab */
  subtitle?: string;
  /** Creation timestamp */
  createdAt: number;
  /** Last activation timestamp */
  activatedAt?: number;
  /** Custom metadata object */
  metadata: Record<string, unknown>;
  /** Navigation history state */
  location: TabLocationHistory;
  /** Organization tags */
  tags: string[];
}

/**
 * Schema for validating persisted tabs loaded from storage.
 *
 * Ensures tabs loaded from sessionStorage/localStorage have all required
 * properties with strict validation (no extra properties allowed).
 */
export const PersistedTabSchema = z
  .object({
    /** Required unique identifier */
    id: z.number(),
    /** Tab display name */
    name: z.string().default('Neuer Vorgang'),
    /** Tab subtitle */
    subtitle: z.string(),
    /** Creation timestamp */
    createdAt: z.number(),
    /** Last activation timestamp */
    activatedAt: z.number().optional(),
    /** Custom metadata */
    metadata: TabMetadataSchema,
    /** Navigation history */
    location: TabLocationHistorySchema,
    /** Organization tags */
    tags: TabTagsSchema,
  })
  .strict();

/** Input type for TabSchema (before validation) */
export type TabInput = z.input<typeof TabSchema>;

/**
 * Schema for adding new tabs to the system.
 *
 * Defines the minimal required properties for tab creation.
 * ID and activatedAt are optional as they can be auto-generated.
 */
export const AddTabSchema = z.object({
  /** Display name for the new tab */
  name: z.string().default('Neuer Vorgang'),
  /** Subtitle for the new tab */
  subtitle: z.string().default(''),
  /** Initial tags for the tab */
  tags: TabTagsSchema,
  /** Initial metadata for the tab */
  metadata: TabMetadataSchema,
  /** Optional ID (auto-generated if not provided) */
  id: z.number().optional(),
  /** Optional activation timestamp */
  activatedAt: z.number().optional(),
});

/** TypeScript type for adding tabs */
export type AddTab = z.infer<typeof AddTabSchema>;

/** Input type for AddTabSchema (before validation) */
export type AddTabInput = z.input<typeof AddTabSchema>;

/**
 * Schema for tab entity updates (NgRx-compatible partial updates).
 *
 * Defines optional properties that can be updated on existing tabs.
 * All properties are optional to support partial updates.
 */
export const TabUpdateSchema = z
  .object({
    /** Updated display name */
    name: z.string().min(1).optional(),
    /** Updated subtitle */
    subtitle: z.string().optional(),
    /** Updated activation timestamp */
    activatedAt: z.number().optional(),
    /** Updated metadata object */
    metadata: z.record(z.unknown()).optional(),
    /** Updated location history */
    location: TabLocationHistorySchema.optional(),
    /** Updated tags array */
    tags: z.array(z.string()).optional(),
  })
  .strict();

/** TypeScript type for tab updates */
export type TabUpdate = z.infer<typeof TabUpdateSchema>;

/**
 * Schema for tab activation updates.
 *
 * Specifically validates activation timestamp updates when
 * switching between tabs.
 */
export const TabActivationUpdateSchema = z
  .object({
    /** New activation timestamp */
    activatedAt: z.number(),
  })
  .strict();

/** TypeScript type for activation updates */
export type TabActivationUpdate = z.infer<typeof TabActivationUpdateSchema>;

/**
 * Schema for tab metadata updates.
 *
 * Validates metadata-only updates to avoid affecting other tab properties.
 */
export const TabMetadataUpdateSchema = z
  .object({
    /** Updated metadata object */
    metadata: z.record(z.unknown()),
  })
  .strict();

/** TypeScript type for metadata updates */
export type TabMetadataUpdate = z.infer<typeof TabMetadataUpdateSchema>;

/**
 * Schema for tab location history updates.
 *
 * Validates navigation history updates when tabs navigate to new locations.
 */
export const TabLocationUpdateSchema = z
  .object({
    /** Updated location history */
    location: TabLocationHistorySchema,
  })
  .strict();

/** TypeScript type for location updates */
export type TabLocationUpdate = z.infer<typeof TabLocationUpdateSchema>;

/**
 * Legacy patch schema for backward compatibility.
 *
 * Maintained for existing code that uses the "patch" terminology.
 * Functionally identical to TabUpdateSchema.
 */
export const PatchTabSchema = TabUpdateSchema;

/** TypeScript type for legacy patch operations */
export type PatchTab = z.infer<typeof PatchTabSchema>;

/** Input type for legacy patch operations */
export type PatchTabInput = z.input<typeof PatchTabSchema>;
