// src/server/features/personnel/personnel.schema.ts
// Zod schemas for personnel validation

import { z } from 'zod';

// Phone validation: Allow flexible format with spaces, parentheses, and hyphens
// Minimum 5 characters, maximum 50 characters to accommodate formatting
export const phoneSchema = z.string()
  .min(5, 'Некорректный номер телефона (минимум 5 символов)')
  .max(50, 'Некорректный номер телефона (максимум 50 символов)');

// Optional phone schema for updates
export const phoneSchemaOptional = z.union([
  z.string().min(5, 'Некорректный номер телефона (минимум 5 символов)').max(50, 'Некорректный номер телефона (максимум 50 символов)'),
  z.null(),
]).optional();

// Email validation (optional - can be empty string or null)
export const emailSchema = z.union([
  z.string().email('Invalid email format'),
  z.literal(''),
  z.null(),
]).optional().transform(v => v === '' ? null : v);

// Helper to transform empty strings and undefined to null
const emptyToNull = z.union([
  z.string().optional(),
  z.literal(''),
  z.null(),
]).transform(val => val === '' || val === undefined || val === null ? null : val);

// Helper to transform empty strings and undefined to null for dates
const emptyDateToNull = z.union([
  z.string().optional(),
  z.literal(''),
  z.null(),
]).transform(val => {
  if (val === '' || val === undefined || val === null) return null;
  // Validate it's a valid date string
  const date = new Date(val);
  if (isNaN(date.getTime())) return null;
  return val;
});

// Helper for optional datetime fields that can be null (for maid dates)
const optionalDatetimeOrNull = z.union([
  z.string().datetime(),
  z.null(),
]).optional().transform(val => {
  if (val === null || val === undefined || val === '') return null;
  return val;
});

// Maid period schema for managing maid role periods
export const maidPeriodSchema = z.object({
  id: z.string().optional(), // Optional for new periods
  startDate: z.string().regex(/^\d{4}-\d{2}-\d{2}$/, 'Invalid date format, expected YYYY-MM-DD'),
  endDate: z.union([
    z.string().regex(/^\d{4}-\d{2}-\d{2}$/, 'Invalid date format, expected YYYY-MM-DD'),
    z.literal(''),
    z.null(),
  ]).optional().transform(val => val === '' || val === null ? null : val),
  _deleted: z.boolean().optional(), // Flag to mark period for deletion
});

// Maid period response schema
export const maidPeriodResponseSchema = z.object({
  id: z.string(),
  startDate: z.string(), // YYYY-MM-DD format
  endDate: z.union([
    z.string(),
    z.literal(''),
    z.null(),
  ]).transform(val => val === '' || val === null ? null : val), // YYYY-MM-DD format or null
});

// Employee input schema
export const createEmployeeSchema = z.object({
  fullName: z.string().min(1, 'Full name is required'),
  position: z.string().min(1, 'Position is required'),
  phone: phoneSchema,
  email: emailSchema,
  birthDate: emptyDateToNull,
  address: emptyToNull,
  notes: emptyToNull,
  hireDate: z.string().datetime().optional(), // Дата приёма (ISO datetime string)
  createUser: z.boolean().optional(),
  username: z.string().optional(), // Optional - will be auto-generated for MAID role
  password: z.string().min(6, 'Password must be at least 6 characters').optional(),
  role: z.enum(['ADMIN', 'MANAGER', 'MAID']).optional(),
  // Maid periods array for managing maid role history
  maidPeriods: z.array(maidPeriodSchema).optional(),
});

export const updateEmployeeSchema = z.object({
  fullName: z.string().min(1, 'Full name is required').optional(),
  position: z.string().min(1, 'Position is required').optional(),
  phone: phoneSchemaOptional,
  email: emailSchema,
  birthDate: emptyDateToNull,
  address: emptyToNull,
  notes: emptyToNull,
  hireDate: z.string().datetime().optional(), // Дата приёма (ISO datetime string)
  password: z.string().min(6, 'Password must be at least 6 characters').optional().or(z.literal('')),
  // User creation fields for "promote to user" functionality
  createUser: z.boolean().optional(),
  username: z.string().optional(),
  role: z.enum(['ADMIN', 'MANAGER', 'MAID', 'GOD']).optional(),
  // Field for unified handling of firing/return reason
  firedReason: emptyToNull,
  isFired: z.boolean().optional(),
  archivedAt: z.string().datetime().nullable().optional(), // Termination date (ISO datetime string)
  // Maid periods array for managing maid role history
  maidPeriods: z.array(maidPeriodSchema).optional(),
});

// Fire employee schema
export const fireEmployeeSchema = z.object({
  firedReason: z.string().min(1, 'Firing reason is required'),
  firedAt: z.string().datetime().optional(),
});

// Rehire employee schema
export const rehireEmployeeSchema = z.object({
  returnReason: z.string().min(3, 'Причина восстановления слишком коротка'),
  rehireDate: z.string().datetime().optional(), // Дата восстановления (ISO datetime string)
  maidPeriods: z.array(maidPeriodSchema).optional(), // Optional maid periods for rehire
});

// Restore employee schema (no body needed, only id from params)
export const restoreEmployeeSchema = z.object({});

// Employee response schema
export const employeeResponseSchema = z.object({
  id: z.string(),
  fullName: z.string(),
  position: z.string(),
  phone: z.string().nullable(),
  email: z.string().nullable(),
  birthDate: z.string().nullable(),
  address: z.string().nullable(),
  notes: z.string().nullable(),
  isFired: z.boolean(),
  firedReason: z.string().nullable(),
  username: z.string().nullable(),
  role: z.string().nullable(),
  isMentionable: z.boolean().optional(),
  isMaidAlso: z.boolean(), // Computed field - true if employee has active maid period today
  maidPeriods: z.array(maidPeriodResponseSchema), // Array of all maid periods
  createdAt: z.string(),
  updatedAt: z.string(),
  archivedAt: z.string().nullable(),
});

// Employees list response schema
export const employeesListResponseSchema = z.object({
  success: z.boolean(),
  data: z.array(employeeResponseSchema),
});

// Single employee response schema
export const employeeResponseWrapperSchema = z.object({
  success: z.boolean(),
  data: employeeResponseSchema,
});

// Error response schema
export const errorResponseSchema = z.object({
  success: z.boolean(),
  error: z.object({
    message: z.string(),
    code: z.string(),
  }),
});

// Check username availability request schema
export const checkUsernameSchema = z.object({
  username: z.string().min(1, 'Username is required'),
});

// Check username availability response schema
export const checkUsernameResponseSchema = z.object({
  success: z.boolean(),
  data: z.object({
    available: z.boolean(),
  }),
});

// Get employees query schema
export const getEmployeesQuerySchema = z.object({
  isFired: z.enum(['true', 'false']).optional().transform(val => val === 'true'),
});

// Types
export type CreateEmployeeInput = z.infer<typeof createEmployeeSchema>;
export type UpdateEmployeeInput = z.infer<typeof updateEmployeeSchema>;
export type FireEmployeeInput = z.infer<typeof fireEmployeeSchema>;
export type RehireEmployeeInput = z.infer<typeof rehireEmployeeSchema>;
export type EmployeeResponse = z.infer<typeof employeeResponseSchema>;
export type CheckUsernameInput = z.infer<typeof checkUsernameSchema>;
export type MaidPeriod = z.infer<typeof maidPeriodSchema>;
export type MaidPeriodResponse = z.infer<typeof maidPeriodResponseSchema>;
export type RehireEmployeeMaidPeriod = z.infer<typeof maidPeriodSchema>;
