// src/server/features/reference_books/local_it.schema.ts
// Zod schemas for local IT & Security equipment validation

import { z } from 'zod';

// IPv4 validation: Valid IPv4 address, CIDR notation (e.g., 192.168.1.1/24), or "DHCP"
export const ipv4Schema = z.string()
  .refine((val) => {
    if (val === 'DHCP') return true;
    const ipv4CidrRegex = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(?:\/(?:3[0-2]|[12]?[0-9]))?$/;
    return ipv4CidrRegex.test(val);
  }, {
    message: 'Invalid IPv4 address. Must be a valid IPv4 address, CIDR notation (e.g., 192.168.1.1/24), or "DHCP"',
  })
  .optional();

// MAC validation: full MAC (AA:BB:CC:DD:EE:FF / AA-BB-CC-DD-EE-FF) or masked suffix (AA:BB:CC:DD:XX:XX / AA:BB:CC:DD:ХХ:ХХ)
export const macAddressSchema = z.string()
  .trim()
  .transform((value) => value.toUpperCase().replace(/Х/g, 'X'))
  .refine((val) => {
    if (!val) return true;
    const separator = val.includes(':') ? ':' : val.includes('-') ? '-' : null;
    if (!separator) return false;

    const chunks = val.split(separator);
    if (chunks.length !== 6) return false;

    let wildcardStarted = false;
    for (const chunk of chunks) {
      const isWildcardChunk = /^XX$/.test(chunk);
      const isHexChunk = /^[0-9A-F]{2}$/.test(chunk);

      if (!isWildcardChunk && !isHexChunk) {
        return false;
      }

      if (isWildcardChunk) {
        wildcardStarted = true;
        continue;
      }

      if (wildcardStarted) {
        return false;
      }
    }

    return true;
  }, {
    message: 'Invalid MAC address. Use AA:BB:CC:DD:EE:FF or masked suffix AA:BB:CC:DD:XX:XX',
  })
  .optional();

// Access Port schema
export const accessPortSchema = z.object({
  serviceName: z.string().min(1, 'Service name is required'),
  port: z.coerce.number().int().min(1).max(65535).optional(),
  username: z.string().optional(),
  password: z.string().optional(),
});

// Local IT equipment creation schema
export const createLocalITSchema = z.object({
  description: z.string().min(1, 'Description is required'),
  manufacturer: z.string().min(1, 'Manufacturer is required'),
  model: z.string().min(1, 'Model is required'),
  networkAddress: ipv4Schema,
  macAddress: macAddressSchema,
  accessPorts: z.array(accessPortSchema).optional(),
  username: z.string().optional(),
  password: z.string().optional(),
  location: z.string().min(1, 'Location is required'),
  comment: z.string().optional(),
});

// Local IT equipment update schema
export const updateLocalITSchema = z.object({
  description: z.string().min(1, 'Description is required').optional(),
  manufacturer: z.string().min(1, 'Manufacturer is required').optional(),
  model: z.string().min(1, 'Model is required').optional(),
  networkAddress: ipv4Schema,
  macAddress: macAddressSchema,
  accessPorts: z.array(accessPortSchema).optional(),
  username: z.string().optional(),
  password: z.string().optional(),
  location: z.string().min(1, 'Location is required').optional(),
  comment: z.string().optional(),
});

// Local Security equipment creation schema
export const createLocalSecuritySchema = z.object({
  type: z.string().min(1, 'Type is required'),
  manufacturer: z.string().min(1, 'Manufacturer is required'),
  model: z.string().min(1, 'Model is required'),
  location: z.string().min(1, 'Location is required'),
  comment: z.string().optional(),
});

// Local Security equipment update schema
export const updateLocalSecuritySchema = z.object({
  type: z.string().min(1, 'Type is required').optional(),
  manufacturer: z.string().min(1, 'Manufacturer is required').optional(),
  model: z.string().min(1, 'Model is required').optional(),
  location: z.string().min(1, 'Location is required').optional(),
  comment: z.string().optional(),
});

// Other equipment creation schema
export const createOtherEquipmentSchema = z.object({
  description: z.string().min(1, 'Description is required'),
  type: z.string().optional(),
  manufacturer: z.string().optional(),
  model: z.string().optional(),
  location: z.string().min(1, 'Location is required'),
  comment: z.string().optional(),
});

// Other equipment update schema
export const updateOtherEquipmentSchema = z.object({
  description: z.string().min(1, 'Description is required').optional(),
  type: z.string().optional(),
  manufacturer: z.string().optional(),
  model: z.string().optional(),
  location: z.string().min(1, 'Location is required').optional(),
  comment: z.string().optional(),
});

// Response schemas
export const localITResponseSchema = z.object({
  id: z.string(),
  description: z.string(),
  manufacturer: z.string().nullable(),
  model: z.string().nullable(),
  networkAddress: z.string().nullable(),
  macAddress: z.string().nullable(),
  accessPorts: z.any(),
  username: z.string().nullable(),
  password: z.string().nullable(),
  location: z.string(),
  comment: z.string().nullable(),
  createdAt: z.string(),
  updatedAt: z.string(),
  archivedAt: z.string().nullable(),
});

export const localSecurityResponseSchema = z.object({
  id: z.string(),
  type: z.string(),
  manufacturer: z.string().nullable(),
  model: z.string().nullable(),
  location: z.string(),
  comment: z.string().nullable(),
  createdAt: z.string(),
  updatedAt: z.string(),
  archivedAt: z.string().nullable(),
});

export const otherEquipmentResponseSchema = z.object({
  id: z.string(),
  description: z.string(),
  type: z.string().nullable(),
  manufacturer: z.string().nullable(),
  model: z.string().nullable(),
  location: z.string(),
  comment: z.string().nullable(),
  createdAt: z.string(),
  updatedAt: z.string(),
  archivedAt: z.string().nullable(),
});

// Types
export type CreateLocalITInput = z.infer<typeof createLocalITSchema>;
export type UpdateLocalITInput = z.infer<typeof updateLocalITSchema>;
export type CreateLocalSecurityInput = z.infer<typeof createLocalSecuritySchema>;
export type UpdateLocalSecurityInput = z.infer<typeof updateLocalSecuritySchema>;
export type CreateOtherEquipmentInput = z.infer<typeof createOtherEquipmentSchema>;
export type UpdateOtherEquipmentInput = z.infer<typeof updateOtherEquipmentSchema>;
