import { z } from 'zod';

export const OrganizationStatusSchema = z.enum(['active', 'disabled']);
export const WorkspaceStatusSchema = z.enum(['active', 'archived']);
export const MembershipRoleSchema = z.enum(['owner', 'admin', 'member', 'viewer']);
export const MembershipScopeSchema = z.enum(['org', 'workspace']);

export const OrganizationSchema = z.object({
  id: z.string().min(1),
  productId: z.string().min(1),
  name: z.string().min(1),
  slug: z.string().min(1),
  status: OrganizationStatusSchema,
  ownerUserId: z.string().min(1),
  metadata: z.record(z.unknown()).optional(),
  createdAt: z.string(),
  updatedAt: z.string(),
});

export type OrganizationDoc = z.infer<typeof OrganizationSchema> & {
  _ts?: number;
  _etag?: string;
};

export const WorkspaceSchema = z.object({
  id: z.string().min(1),
  orgId: z.string().min(1),
  productId: z.string().min(1),
  name: z.string().min(1),
  slug: z.string().min(1),
  status: WorkspaceStatusSchema,
  description: z.string().optional(),
  metadata: z.record(z.unknown()).optional(),
  createdAt: z.string(),
  updatedAt: z.string(),
});

export type WorkspaceDoc = z.infer<typeof WorkspaceSchema> & {
  _ts?: number;
  _etag?: string;
};

export const MembershipSchema = z.object({
  id: z.string().min(1),
  orgId: z.string().min(1),
  productId: z.string().min(1),
  scope: MembershipScopeSchema,
  workspaceId: z.string().optional(),
  userId: z.string().min(1),
  role: MembershipRoleSchema,
  status: z.enum(['active', 'invited', 'disabled']).default('active'),
  invitedBy: z.string().optional(),
  createdAt: z.string(),
  updatedAt: z.string(),
});

export type MembershipDoc = z.infer<typeof MembershipSchema> & {
  _ts?: number;
  _etag?: string;
};

export const CreateOrganizationSchema = z.object({
  name: z.string().min(1),
  slug: z.string().min(1),
  ownerUserId: z.string().min(1).optional(),
  metadata: z.record(z.unknown()).optional(),
});

export const UpdateOrganizationSchema = z.object({
  name: z.string().min(1).optional(),
  slug: z.string().min(1).optional(),
  status: OrganizationStatusSchema.optional(),
  metadata: z.record(z.unknown()).optional(),
});

export const CreateWorkspaceSchema = z.object({
  name: z.string().min(1),
  slug: z.string().min(1),
  description: z.string().optional(),
  metadata: z.record(z.unknown()).optional(),
});

export const UpdateWorkspaceSchema = z.object({
  name: z.string().min(1).optional(),
  slug: z.string().min(1).optional(),
  status: WorkspaceStatusSchema.optional(),
  description: z.string().optional(),
  metadata: z.record(z.unknown()).optional(),
});

export const CreateMembershipSchema = z.object({
  userId: z.string().min(1),
  role: MembershipRoleSchema.default('member'),
  scope: MembershipScopeSchema.default('org'),
  workspaceId: z.string().optional(),
  invitedBy: z.string().optional(),
});

export const UpdateMembershipSchema = z.object({
  role: MembershipRoleSchema.optional(),
  status: z.enum(['active', 'invited', 'disabled']).optional(),
});

export const ListOrganizationsQuerySchema = z.object({
  status: OrganizationStatusSchema.optional(),
  limit: z.coerce.number().min(1).max(100).default(20),
});

export const ListMembershipsQuerySchema = z.object({
  scope: MembershipScopeSchema.optional(),
  workspaceId: z.string().optional(),
  limit: z.coerce.number().min(1).max(100).default(100),
});

export type ListOrganizationsQuery = z.infer<typeof ListOrganizationsQuerySchema>;
export type ListMembershipsQuery = z.infer<typeof ListMembershipsQuerySchema>;

// ── RBAC Role Hierarchy ─────────────────────────────────────

export const ROLE_HIERARCHY: Record<string, number> = {
  owner: 40,
  admin: 30,
  member: 20,
  viewer: 10,
};

export type Permission =
  | 'org:read'
  | 'org:update'
  | 'org:delete'
  | 'workspace:create'
  | 'workspace:read'
  | 'workspace:update'
  | 'workspace:archive'
  | 'member:invite'
  | 'member:read'
  | 'member:update_role'
  | 'member:remove';

export const ROLE_PERMISSIONS: Record<string, Permission[]> = {
  owner: [
    'org:read',
    'org:update',
    'org:delete',
    'workspace:create',
    'workspace:read',
    'workspace:update',
    'workspace:archive',
    'member:invite',
    'member:read',
    'member:update_role',
    'member:remove',
  ],
  admin: [
    'org:read',
    'org:update',
    'workspace:create',
    'workspace:read',
    'workspace:update',
    'workspace:archive',
    'member:invite',
    'member:read',
    'member:update_role',
    'member:remove',
  ],
  member: ['org:read', 'workspace:read', 'member:read'],
  viewer: ['org:read', 'workspace:read', 'member:read'],
};

export function hasPermission(role: string, permission: Permission): boolean {
  return (ROLE_PERMISSIONS[role] ?? []).includes(permission);
}

export function canManageRole(actorRole: string, targetRole: string): boolean {
  return (ROLE_HIERARCHY[actorRole] ?? 0) > (ROLE_HIERARCHY[targetRole] ?? 0);
}
