import { z } from 'zod';

import type { PermissionItem, RoleItem } from '@/database/schemas';

import type { IPaginationQuery, PaginationQueryResponse } from './common.type';
import { PaginationQuerySchema } from './common.type';

// ==================== Role Query Types ====================

/**
 * Role query parameters
 */
export type RolesListQuery = IPaginationQuery & {
  active?: boolean;
  system?: boolean;
};

export const RolesListQuerySchema = z
  .object({
    active: z
      .string()
      .transform((val) => val === 'true')
      .pipe(z.boolean())
      .nullish(),
    system: z
      .string()
      .transform((val) => val === 'true')
      .pipe(z.boolean())
      .nullish(),
  })
  .extend(PaginationQuerySchema.shape);

export type RolesListResponse = PaginationQueryResponse<{
  roles: RoleItem[];
}>;

// ==================== Role Permission Types ====================

export type RolePermissionsListQuery = IPaginationQuery;

export interface RolePermissionsListRequest extends IPaginationQuery {
  roleId: string;
}

export type RolePermissionsListResponse = PaginationQueryResponse<{
  permissions: Partial<PermissionItem>[];
}>;

// ==================== Role CRUD Types ====================

/**
 * Role creation request body
 */
export type CreateRoleRequest = {
  description?: string;
  displayName: string;
  isActive?: boolean;
  isSystem?: boolean;
  name: string;
};

export const CreateRoleRequestSchema = z.object({
  description: z.string().nullish(),
  displayName: z.string().min(1, 'Display name cannot be empty'),
  isActive: z.boolean().nullish().default(true),
  isSystem: z.boolean().nullish().default(false),
  name: z.string().min(1, 'Role name cannot be empty'),
});

/**
 * Role update request body
 */
export type UpdateRoleRequest = Partial<CreateRoleRequest>;

export const UpdateRoleRequestSchema = CreateRoleRequestSchema.partial();

/**
 * Role permissions update request
 */
export type UpdateRolePermissionsRequest = {
  grant?: string[];
  revoke?: string[];
};

export const UpdateRolePermissionsRequestSchema = z
  .object({
    grant: z.array(z.string().min(1, 'Permission ID cannot be empty')).nullish(),
    revoke: z.array(z.string().min(1, 'Permission ID cannot be empty')).nullish(),
  })
  .refine(
    (data) => {
      const grantLength = data.grant?.length ?? 0;
      const revokeLength = data.revoke?.length ?? 0;
      return grantLength > 0 || revokeLength > 0;
    },
    {
      message: 'At least one permission ID to grant or revoke must be provided',
    },
  );

// ==================== Common Schemas ====================

export const RoleIdParamSchema = z.object({
  id: z.string().min(1, 'Invalid role ID'),
});

export { PaginationQuerySchema as RolePermissionsListQuerySchema } from './common.type';
