import { z } from 'zod';
import { defaultTransformSchema } from '../shared/shared.dto';
import {
  ALL_PERMISSION_KEYS,
  isValidPermissionValue,
} from './permission-catalog';

const optionalString = z.preprocess((value) => {
  if (typeof value === 'string' && value.trim() === '') return undefined;
  return value;
}, z.string().trim().optional());

const optionalUuid = z.preprocess((value) => {
  if (typeof value === 'string' && value.trim() === '') return undefined;
  return value;
}, z.string().uuid().optional());

export const permissionMapSchema = z
  .record(z.string(), z.string())
  .superRefine((value, ctx) => {
    for (const [key, permissionValue] of Object.entries(value)) {
      if (!ALL_PERMISSION_KEYS.includes(key)) {
        ctx.addIssue({
          code: z.ZodIssueCode.custom,
          message: `Unknown permission key: ${key}`,
          path: [key],
        });
        continue;
      }

      if (!isValidPermissionValue(key, permissionValue)) {
        ctx.addIssue({
          code: z.ZodIssueCode.custom,
          message: `Invalid value for ${key}`,
          path: [key],
        });
      }
    }
  });

export const createAccessRoleSchema = z.object({
  name: z
    .string()
    .trim()
    .min(2, { message: 'Role name must be at least 2 characters long' }),
  description: optionalString,
  source_role_id: optionalUuid,
});

export const updateAccessRoleSchema = z
  .object({
    name: z.string().trim().min(2).optional(),
    description: optionalString,
    permissions: permissionMapSchema.optional(),
  })
  .refine((data) => Object.keys(data).length > 0, {
    message: 'At least one field must be provided',
  });

export const accessRoleResponseSchema = z.object({
  id: z.string().uuid(),
  name: z.string(),
  slug: z.string(),
  description: defaultTransformSchema,
  is_system: z.boolean(),
  hierarchy: z.number(),
  permissions: z.record(z.string(), z.string()),
  created_at: z.coerce.date(),
  updated_at: z.coerce.date(),
});

export const accessRolesResponseSchema = z.array(accessRoleResponseSchema);

export type createAccessRoleDto = z.infer<typeof createAccessRoleSchema>;
export type updateAccessRoleDto = z.infer<typeof updateAccessRoleSchema>;
