// decorators/permission.decorator.ts
import { SetMetadata, CustomDecorator, applyDecorators, UseGuards } from '@nestjs/common';
import { PermissionLevel, METADATA_KEYS } from '@/constants/permission.constant';
import { PermissionGuard } from '../guards/permission.guard';
import { GroupMemberGuard } from '../guards/group-member.guard';
import { GroupOwnerOrAdminGuard } from '../guards/group-owner.guard';

/**
 * Decorator yêu cầu quyền truy cập
 * @param level - Cấp độ quyền yêu cầu
 * @example
 * @RequirePermission(PermissionLevel.ADMIN)
 * async updateGroup() {}
 */
export const RequirePermission = (level: PermissionLevel): CustomDecorator => 
  SetMetadata(METADATA_KEYS.PERMISSION, level);

/**
 * Decorator cho phép quyền truy cập linh hoạt (có thể có hoặc không)
 * @param levels - Danh sách các cấp độ quyền được chấp nhận
 * @example
 * @AllowPermissions(PermissionLevel.ADMIN, PermissionLevel.MEMBER)
 */
export const AllowPermissions = (...levels: PermissionLevel[]): CustomDecorator => 
  SetMetadata(METADATA_KEYS.PERMISSION_OPTIONAL, levels);

/**
 * Decorator chỉ định resource để lấy groupId
 * @param resourceType - Loại resource ('map', 'trip', 'group', 'custom')
 * @param idSource - Nguồn lấy ID ('param', 'query', 'body', 'custom')
 * @example
 * @Resource('map', 'param')
 */
export const Resource = (resourceType: string, idSource?: string): CustomDecorator =>
  SetMetadata(METADATA_KEYS.PERMISSION_RESOURCE, { resourceType, idSource });

/**
 * Decorator kết hợp - Yêu cầu quyền Member
 */
export const RequireMember = () =>
  applyDecorators(
    RequirePermission(PermissionLevel.MEMBER),
    UseGuards(PermissionGuard),
  );

/**
 * Decorator kết hợp - Yêu cầu quyền Admin hoặc Owner
 */
export const RequireAdmin = () =>
  applyDecorators(
    RequirePermission(PermissionLevel.ADMIN),
    UseGuards(PermissionGuard),
  );

/**
 * Decorator kết hợp - Yêu cầu quyền Owner
 */
export const RequireOwner = () =>
  applyDecorators(
    RequirePermission(PermissionLevel.OWNER),
    UseGuards(PermissionGuard),
  );

/**
 * Decorator kết hợp - Dùng guard riêng biệt
 */
export const UseGroupMemberGuard = () => UseGuards(GroupMemberGuard);
export const UseGroupAdminGuard = () => UseGuards(GroupOwnerOrAdminGuard);

/**
 * Decorator public - Không cần kiểm tra quyền
 */
export const Public = (): CustomDecorator => SetMetadata('isPublic', true);

/**
 * Decorator bỏ qua permission check
 */
export const SkipPermission = (): CustomDecorator => SetMetadata('skipPermission', true);

// Trip decorators
export const TripResource = (idSource: 'param' | 'query' | 'body' = 'param') =>
  Resource('trip', idSource);

export const TripMember = () =>
  applyDecorators(
    TripResource(),
    RequireMember(),
  );

export const TripAdmin = () =>
  applyDecorators(
    TripResource(),
    RequireAdmin(),
  );

export const TripOwner = () =>
  applyDecorators(
    TripResource(),
    RequireOwner(),
  );

  // Group decorators
export const GroupResource = (idSource: 'param' | 'query' | 'body' = 'param') =>
  Resource('group', idSource);

export const GroupMember = () =>
  applyDecorators(
    GroupResource(),
    RequireMember(),
  );

export const GroupAdmin = () =>
  applyDecorators(
    GroupResource(),
    RequireAdmin(),
  );

export const GroupOwner = () =>
  applyDecorators(
    GroupResource(),
    RequireOwner(),
  );

// Map decorators
export const MapResource = (idSource: 'param' | 'query' | 'body' = 'param') =>
  Resource('map', idSource);

export const MapMember = () =>
  applyDecorators(
    MapResource(),
    RequireMember(),
  );

export const MapAdmin = () =>
  applyDecorators(
    MapResource('body'),
    RequireAdmin(),
  );

// Timeline decorators
export const TimelineResource = (idSource: 'param' | 'query' | 'body' = 'param') =>
  Resource('timeline', idSource);

export const TimelineMember = () =>
  applyDecorators(
    TimelineResource(),
    RequireMember(),
  );

export const TimelineAdmin = () =>
  applyDecorators(
    TimelineResource(),
    RequireAdmin(),
  );