import { TRPCError } from '@trpc/server';
import debug from 'debug';
import { customAlphabet } from 'nanoid/non-secure';
import { z } from 'zod';

import { withScopedPermission } from '@/business/server/trpc-middlewares/rbacPermission';
import { authedProcedure, router } from '@/libs/trpc/lambda';
import { marketSDK, marketUserInfo, serverDatabase } from '@/libs/trpc/lambda/middleware';
import { type TrustedClientUserInfo } from '@/libs/trusted-client';
import { generateTrustedClientToken } from '@/libs/trusted-client';

const MARKET_BASE_URL = process.env.MARKET_BASE_URL || 'https://market.lobehub.com';

interface MarketUserInfo {
  accountId: number;
  sub: string;
}

const log = debug('lambda-router:market:agent-group');

/**
 * Generate a market identifier (8-character lowercase alphanumeric string)
 * Format: [a-z0-9]{8}
 */
const generateMarketIdentifier = () => {
  const alphabet = '0123456789abcdefghijklmnopqrstuvwxyz';
  const generate = customAlphabet(alphabet, 8);
  return generate();
};

interface FetchMarketUserInfoOptions {
  accessToken?: string;
  userInfo?: TrustedClientUserInfo;
}

/**
 * Fetch Market user info using either trustedClientToken or accessToken
 * Returns the Market accountId which is different from LobeChat userId
 */
const fetchMarketUserInfo = async (
  options: FetchMarketUserInfoOptions,
): Promise<MarketUserInfo | null> => {
  const { userInfo, accessToken } = options;

  try {
    const userInfoUrl = `${MARKET_BASE_URL}/lobehub-oidc/userinfo`;
    const headers: Record<string, string> = {
      'Content-Type': 'application/json',
    };

    if (userInfo) {
      const trustedClientToken = generateTrustedClientToken(userInfo);
      if (trustedClientToken) {
        headers['x-lobe-trust-token'] = trustedClientToken;
        log('Using trustedClientToken for user info fetch');
      }
    }

    if (!headers['x-lobe-trust-token'] && accessToken) {
      headers['Authorization'] = `Bearer ${accessToken}`;
      log('Using accessToken for user info fetch');
    }

    if (!headers['x-lobe-trust-token'] && !headers['Authorization']) {
      log('No authentication method available for fetching user info');
      return null;
    }

    const response = await fetch(userInfoUrl, {
      headers,
      method: 'GET',
    });

    if (!response.ok) {
      log('Failed to fetch Market user info: %s %s', response.status, response.statusText);
      return null;
    }

    return (await response.json()) as MarketUserInfo;
  } catch (error) {
    log('Error fetching Market user info: %O', error);
    return null;
  }
};

const withActingAccountHeader = async <T>(
  marketSDK: unknown,
  actAs: number | undefined,
  operation: () => Promise<T>,
): Promise<T> => {
  const headers = (marketSDK as { headers?: Record<string, string> }).headers;
  if (actAs === undefined || !headers) return operation();

  const previous = headers['x-lobe-owner-account-id'];
  headers['x-lobe-owner-account-id'] = String(actAs);

  try {
    return await operation();
  } finally {
    if (previous === undefined) {
      delete headers['x-lobe-owner-account-id'];
    } else {
      headers['x-lobe-owner-account-id'] = previous;
    }
  }
};

// Authenticated procedure for agent group management
const agentGroupProcedure = authedProcedure
  .use(serverDatabase)
  .use(marketUserInfo)
  .use(marketSDK)
  .use(async ({ ctx, next }) => {
    const { UserModel } = await import('@/database/models/user');
    const userModel = new UserModel(ctx.serverDB, ctx.userId);

    let marketOidcAccessToken: string | undefined;
    try {
      const userState = await userModel.getUserState(async () => ({}));
      marketOidcAccessToken = userState.settings?.market?.accessToken;
      log('marketOidcAccessToken from DB exists=%s', !!marketOidcAccessToken);
    } catch (error) {
      log('Failed to get marketOidcAccessToken from DB: %O', error);
    }

    return next({
      ctx: {
        marketOidcAccessToken,
      },
    });
  });
const agentGroupWriteProcedure = agentGroupProcedure.use(withScopedPermission('agent:create'));

// Schema definitions
const memberAgentSchema = z.object({
  avatar: z.string().nullish(),
  category: z.string().optional(),
  config: z.record(z.any()),
  description: z.string(),
  displayOrder: z.number().optional(),
  identifier: z.string(),
  name: z.string(),
  role: z.enum(['supervisor', 'participant']),
  url: z.string(),
});

const publishOrCreateGroupSchema = z.object({
  actAs: z.number().int().positive().optional(),
  avatar: z.string().nullish(),
  backgroundColor: z.string().nullish(),
  category: z.string().optional(),
  changelog: z.string().optional(),
  config: z
    .object({
      allowDM: z.boolean().optional(),
      openingMessage: z.string().optional(),
      openingQuestions: z.array(z.string()).optional(),
      revealDM: z.boolean().optional(),
      systemPrompt: z.string().optional(),
    })
    .optional(),
  description: z.string(),
  identifier: z.string().nullish(), // Allow null or undefined
  memberAgents: z.array(memberAgentSchema),
  name: z.string(),
  visibility: z.enum(['public', 'private', 'internal']).optional(),
});

export const agentGroupRouter = router({
  /**
   * Check if current user owns the specified group
   */
  checkOwnership: agentGroupProcedure
    .input(z.object({ actAs: z.number().int().positive().optional(), identifier: z.string() }))
    .query(async ({ input, ctx }) => {
      log('checkOwnership input: %O', input);

      try {
        const groupDetail = await ctx.marketSDK.agentGroups.getAgentGroupDetail(input.identifier);

        if (!groupDetail) {
          return {
            exists: false,
            isOwner: false,
            originalGroup: null,
          };
        }

        const userInfo = ctx.marketUserInfo as TrustedClientUserInfo | undefined;
        const accessToken = (ctx as { marketOidcAccessToken?: string }).marketOidcAccessToken;
        let currentAccountId: number | null = null;

        const marketUserInfoResult = await fetchMarketUserInfo({ accessToken, userInfo });
        currentAccountId = marketUserInfoResult?.accountId ?? null;

        const ownerId = groupDetail.group.ownerId;
        const actingAccountId = input.actAs ?? currentAccountId;
        const isOwner = actingAccountId !== null && `${ownerId}` === `${actingAccountId}`;

        log(
          'checkOwnership result: isOwner=%s, currentAccountId=%s, actingAccountId=%s, ownerId=%s',
          isOwner,
          currentAccountId,
          actingAccountId,
          ownerId,
        );

        return {
          exists: true,
          isOwner,
          originalGroup: isOwner
            ? null
            : {
                // TODO: Add author info from group detail
                author: undefined,
                avatar: groupDetail.group.avatar,
                identifier: groupDetail.group.identifier,
                name: groupDetail.group.name,
              },
        };
      } catch (error) {
        log('Error checking ownership: %O', error);
        return {
          exists: false,
          isOwner: false,
          originalGroup: null,
        };
      }
    }),

  /**
   * Deprecate agent group
   * POST /market/agent-group/:identifier/deprecate
   */
  deprecateAgentGroup: agentGroupWriteProcedure
    .input(z.object({ identifier: z.string() }))
    .mutation(async ({ input, ctx }) => {
      log('deprecateAgentGroup input: %O', input);

      try {
        const deprecateUrl = `${MARKET_BASE_URL}/api/v1/agent-groups/${input.identifier}/deprecate`;

        const headers: Record<string, string> = {
          'Content-Type': 'application/json',
        };

        const userInfo = ctx.marketUserInfo as TrustedClientUserInfo | undefined;
        const accessToken = (ctx as { marketOidcAccessToken?: string }).marketOidcAccessToken;

        if (userInfo) {
          const trustedClientToken = generateTrustedClientToken(userInfo);
          if (trustedClientToken) {
            headers['x-lobe-trust-token'] = trustedClientToken;
          }
        }

        if (!headers['x-lobe-trust-token'] && accessToken) {
          headers['Authorization'] = `Bearer ${accessToken}`;
        }

        const response = await fetch(deprecateUrl, {
          headers,
          method: 'POST',
        });

        if (!response.ok) {
          const errorText = await response.text();
          log(
            'Deprecate agent group failed: %s %s - %s',
            response.status,
            response.statusText,
            errorText,
          );
          throw new Error(`Failed to deprecate agent group: ${response.statusText}`);
        }

        log('Deprecate agent group success');
        return { success: true };
      } catch (error) {
        log('Error deprecating agent group: %O', error);
        throw new TRPCError({
          cause: error,
          code: 'INTERNAL_SERVER_ERROR',
          message: error instanceof Error ? error.message : 'Failed to deprecate agent group',
        });
      }
    }),

  /**
   * Fork an agent group
   * POST /market/agent-group/:identifier/fork
   */
  forkAgentGroup: agentGroupWriteProcedure
    .input(
      z.object({
        actAs: z.number().int().positive().optional(),
        identifier: z.string(),
        name: z.string().optional(),
        sourceIdentifier: z.string(),
        status: z.enum(['published', 'unpublished', 'archived', 'deprecated']).optional(),
        versionNumber: z.number().optional(),
        visibility: z.enum(['public', 'private', 'internal']).optional(),
      }),
    )
    .mutation(async ({ input, ctx }) => {
      log('forkAgentGroup input: %O', input);

      try {
        // Call Market API directly to fork agent group
        const forkUrl = `${MARKET_BASE_URL}/api/v1/agent-groups/${input.sourceIdentifier}/fork`;

        const headers: Record<string, string> = {
          'Content-Type': 'application/json',
        };

        // Use trustedClientToken or accessToken for authentication
        const userInfo = ctx.marketUserInfo as TrustedClientUserInfo | undefined;
        const accessToken = (ctx as { marketOidcAccessToken?: string }).marketOidcAccessToken;

        if (userInfo) {
          const trustedClientToken = generateTrustedClientToken(userInfo);
          if (trustedClientToken) {
            headers['x-lobe-trust-token'] = trustedClientToken;
          }
        }

        if (!headers['x-lobe-trust-token'] && accessToken) {
          headers['Authorization'] = `Bearer ${accessToken}`;
        }

        if (input.actAs !== undefined) {
          headers['x-lobe-owner-account-id'] = String(input.actAs);
        }

        const response = await fetch(forkUrl, {
          body: JSON.stringify({
            identifier: input.identifier,
            name: input.name,
            status: input.status,
            versionNumber: input.versionNumber,
            visibility: input.visibility,
          }),
          headers,
          method: 'POST',
        });

        if (!response.ok) {
          const errorText = await response.text();
          log(
            'Fork agent group failed: %s %s - %s',
            response.status,
            response.statusText,
            errorText,
          );
          throw new Error(`Failed to fork agent group: ${response.statusText}`);
        }

        const result = await response.json();
        log('Fork agent group success: %O', result);
        return result;
      } catch (error) {
        log('Error forking agent group: %O', error);
        throw new TRPCError({
          cause: error,
          code: 'INTERNAL_SERVER_ERROR',
          message: error instanceof Error ? error.message : 'Failed to fork agent group',
        });
      }
    }),

  /**
   * Get agent group detail by identifier
   * GET /market/agent-group/:identifier
   */
  getAgentGroupDetail: agentGroupProcedure
    .input(z.object({ identifier: z.string() }))
    .query(async ({ input, ctx }) => {
      log('getAgentGroupDetail input: %O', input);

      try {
        const response = await ctx.marketSDK.agentGroups.getAgentGroupDetail(input.identifier);
        return response;
      } catch (error) {
        log('Error getting agent group detail: %O', error);
        throw new TRPCError({
          cause: error,
          code: 'INTERNAL_SERVER_ERROR',
          message: error instanceof Error ? error.message : 'Failed to get agent group detail',
        });
      }
    }),

  /**
   * Get the fork source of an agent group
   * GET /market/agent-group/:identifier/fork-source
   */
  getAgentGroupForkSource: agentGroupProcedure
    .input(z.object({ identifier: z.string() }))
    .query(async ({ input, ctx }) => {
      log('getAgentGroupForkSource input: %O', input);

      try {
        const forkSourceUrl = `${MARKET_BASE_URL}/api/v1/agent-groups/${input.identifier}/fork-source`;

        const headers: Record<string, string> = {
          'Content-Type': 'application/json',
        };

        const userInfo = ctx.marketUserInfo as TrustedClientUserInfo | undefined;
        const accessToken = (ctx as { marketOidcAccessToken?: string }).marketOidcAccessToken;

        if (userInfo) {
          const trustedClientToken = generateTrustedClientToken(userInfo);
          if (trustedClientToken) {
            headers['x-lobe-trust-token'] = trustedClientToken;
          }
        }

        if (!headers['x-lobe-trust-token'] && accessToken) {
          headers['Authorization'] = `Bearer ${accessToken}`;
        }

        const response = await fetch(forkSourceUrl, {
          headers,
          method: 'GET',
        });

        if (!response.ok) {
          const errorText = await response.text();
          log(
            'Get agent group fork source failed: %s %s - %s',
            response.status,
            response.statusText,
            errorText,
          );
          throw new Error(`Failed to get agent group fork source: ${response.statusText}`);
        }

        const result = await response.json();
        return result;
      } catch (error) {
        log('Error getting agent group fork source: %O', error);
        throw new TRPCError({
          cause: error,
          code: 'INTERNAL_SERVER_ERROR',
          message: error instanceof Error ? error.message : 'Failed to get agent group fork source',
        });
      }
    }),

  /**
   * Get all forks of an agent group
   * GET /market/agent-group/:identifier/forks
   */
  getAgentGroupForks: agentGroupProcedure
    .input(z.object({ identifier: z.string() }))
    .query(async ({ input, ctx }) => {
      log('getAgentGroupForks input: %O', input);

      try {
        const forksUrl = `${MARKET_BASE_URL}/api/v1/agent-groups/${input.identifier}/forks`;

        const headers: Record<string, string> = {
          'Content-Type': 'application/json',
        };

        const userInfo = ctx.marketUserInfo as TrustedClientUserInfo | undefined;
        const accessToken = (ctx as { marketOidcAccessToken?: string }).marketOidcAccessToken;

        if (userInfo) {
          const trustedClientToken = generateTrustedClientToken(userInfo);
          if (trustedClientToken) {
            headers['x-lobe-trust-token'] = trustedClientToken;
          }
        }

        if (!headers['x-lobe-trust-token'] && accessToken) {
          headers['Authorization'] = `Bearer ${accessToken}`;
        }

        const response = await fetch(forksUrl, {
          headers,
          method: 'GET',
        });

        if (!response.ok) {
          const errorText = await response.text();
          log(
            'Get agent group forks failed: %s %s - %s',
            response.status,
            response.statusText,
            errorText,
          );
          throw new Error(`Failed to get agent group forks: ${response.statusText}`);
        }

        const result = await response.json();
        return result;
      } catch (error) {
        log('Error getting agent group forks: %O', error);
        throw new TRPCError({
          cause: error,
          code: 'INTERNAL_SERVER_ERROR',
          message: error instanceof Error ? error.message : 'Failed to get agent group forks',
        });
      }
    }),

  /**
   * Get agent group list
   * GET /api/v1/agent-groups/list
   */
  getAgentGroupList: agentGroupProcedure
    .input(
      z.object({
        category: z.string().optional(),
        locale: z.string().optional(),
        order: z.enum(['asc', 'desc']).optional(),
        ownerId: z.string().optional(),
        page: z.number().optional(),
        pageSize: z.number().optional(),
        q: z.string().optional(),
        sort: z.enum(['createdAt', 'updatedAt', 'name', 'recommended']).optional(),
        status: z.enum(['published', 'unpublished', 'archived', 'deprecated']).optional(),
        visibility: z.enum(['public', 'private', 'internal']).optional(),
      }),
    )
    .query(async ({ input, ctx }) => {
      log('getAgentGroupList input: %O', input);

      try {
        const params = new URLSearchParams();
        if (input.category) params.append('category', input.category);
        if (input.locale) params.append('locale', input.locale);
        if (input.order) params.append('order', input.order);
        if (input.ownerId) params.append('ownerId', input.ownerId);
        if (input.page) params.append('page', String(input.page));
        if (input.pageSize) params.append('pageSize', String(input.pageSize));
        if (input.q) params.append('q', input.q);
        if (input.sort) params.append('sort', input.sort);
        if (input.status) params.append('status', input.status);
        if (input.visibility) params.append('visibility', input.visibility);

        const listUrl = `${MARKET_BASE_URL}/api/v1/agent-groups/list?${params.toString()}`;

        const headers: Record<string, string> = {
          'Content-Type': 'application/json',
        };

        const userInfo = ctx.marketUserInfo as TrustedClientUserInfo | undefined;
        const accessToken = (ctx as { marketOidcAccessToken?: string }).marketOidcAccessToken;

        if (userInfo) {
          const trustedClientToken = generateTrustedClientToken(userInfo);
          if (trustedClientToken) {
            headers['x-lobe-trust-token'] = trustedClientToken;
          }
        }

        if (!headers['x-lobe-trust-token'] && accessToken) {
          headers['Authorization'] = `Bearer ${accessToken}`;
        }

        const response = await fetch(listUrl, {
          headers,
          method: 'GET',
        });

        if (!response.ok) {
          const errorText = await response.text();
          log(
            'Get agent group list failed: %s %s - %s',
            response.status,
            response.statusText,
            errorText,
          );
          throw new Error(`Failed to get agent group list: ${response.statusText}`);
        }

        const result = await response.json();
        log('Get agent group list success: count=%d', result.totalCount);

        // Transform items to match getGroupAgentList format from DiscoverService
        const transformedItems = (result.items || []).map((group: any) => ({
          author: group.author || '',
          avatar: group.avatar || '👥',
          category: group.category,
          createdAt: group.createdAt,
          description: group.description || '',
          homepage: `https://lobehub.com/discover/group_agent/${group.identifier}`,
          identifier: group.identifier,
          installCount: group.installCount || 0,
          isFeatured: group.isFeatured || false,
          isOfficial: group.isOfficial || false,
          isValidated: group.isValidated,
          memberCount: group.memberCount || 0,
          schemaVersion: 1,
          status: group.status,
          tags: group.tags || [],
          title: group.name || group.identifier,
          updatedAt: group.updatedAt,
        }));

        return {
          currentPage: result.currentPage || input.page || 1,
          items: transformedItems,
          pageSize: result.pageSize || input.pageSize || 20,
          totalCount: result.totalCount || 0,
          totalPages: result.totalPages || 0,
        };
      } catch (error) {
        log('Error getting agent group list: %O', error);
        throw new TRPCError({
          cause: error,
          code: 'INTERNAL_SERVER_ERROR',
          message: error instanceof Error ? error.message : 'Failed to get agent group list',
        });
      }
    }),

  /**
   * Publish agent group
   * POST /market/agent-group/:identifier/publish
   */
  publishAgentGroup: agentGroupWriteProcedure
    .input(z.object({ identifier: z.string() }))
    .mutation(async ({ input, ctx }) => {
      log('publishAgentGroup input: %O', input);

      try {
        const publishUrl = `${MARKET_BASE_URL}/api/v1/agent-groups/${input.identifier}/publish`;

        const headers: Record<string, string> = {
          'Content-Type': 'application/json',
        };

        const userInfo = ctx.marketUserInfo as TrustedClientUserInfo | undefined;
        const accessToken = (ctx as { marketOidcAccessToken?: string }).marketOidcAccessToken;

        if (userInfo) {
          const trustedClientToken = generateTrustedClientToken(userInfo);
          if (trustedClientToken) {
            headers['x-lobe-trust-token'] = trustedClientToken;
          }
        }

        if (!headers['x-lobe-trust-token'] && accessToken) {
          headers['Authorization'] = `Bearer ${accessToken}`;
        }

        const response = await fetch(publishUrl, {
          headers,
          method: 'POST',
        });

        if (!response.ok) {
          const errorText = await response.text();
          log(
            'Publish agent group failed: %s %s - %s',
            response.status,
            response.statusText,
            errorText,
          );
          throw new Error(`Failed to publish agent group: ${response.statusText}`);
        }

        log('Publish agent group success');
        return { success: true };
      } catch (error) {
        log('Error publishing agent group: %O', error);
        throw new TRPCError({
          cause: error,
          code: 'INTERNAL_SERVER_ERROR',
          message: error instanceof Error ? error.message : 'Failed to publish agent group',
        });
      }
    }),

  /**
   * Unified publish or create agent group flow
   * 1. Check if identifier exists and if current user is owner
   * 2. If not owner or no identifier, create new group
   * 3. Create new version for the group if updating
   */
  publishOrCreate: agentGroupWriteProcedure
    .input(publishOrCreateGroupSchema)
    .mutation(async ({ input, ctx }) => {
      log('publishOrCreate input: %O', input);

      const { actAs, identifier: inputIdentifier, name, memberAgents, ...groupData } = input;
      let finalIdentifier = inputIdentifier;
      let isNewGroup = false;

      try {
        // Step 1: Check ownership if identifier is provided
        if (inputIdentifier) {
          try {
            const groupDetail =
              await ctx.marketSDK.agentGroups.getAgentGroupDetail(inputIdentifier);
            log('Group detail for ownership check: ownerId=%s', groupDetail?.group.ownerId);

            const userInfo = ctx.marketUserInfo as TrustedClientUserInfo | undefined;
            const accessToken = (ctx as { marketOidcAccessToken?: string }).marketOidcAccessToken;
            let currentAccountId: number | null = null;

            const marketUserInfoResult = await fetchMarketUserInfo({ accessToken, userInfo });
            currentAccountId = marketUserInfoResult?.accountId ?? null;
            log('Market user info: accountId=%s', currentAccountId);

            const ownerId = groupDetail?.group.ownerId;

            log('Ownership check: currentAccountId=%s, ownerId=%s', currentAccountId, ownerId);

            const actingAccountId = actAs ?? currentAccountId;

            if (!actingAccountId || `${ownerId}` !== `${actingAccountId}`) {
              // Not the owner, need to create a new group
              log('User is not owner, will create new group');
              finalIdentifier = undefined;
              isNewGroup = true;
            }
          } catch (detailError) {
            // Group not found or error, create new
            log('Group not found or error, will create new: %O', detailError);
            finalIdentifier = undefined;
            isNewGroup = true;
          }
        } else {
          isNewGroup = true;
        }

        // Step 2: Create new group or update existing
        if (!finalIdentifier || isNewGroup) {
          // Generate a unique 8-character identifier
          finalIdentifier = generateMarketIdentifier();
          isNewGroup = true;

          log('Creating new group with identifier: %s', finalIdentifier);

          await withActingAccountHeader(ctx.marketSDK, actAs, () =>
            ctx.marketSDK.agentGroups.createAgentGroup({
              ...groupData,
              identifier: finalIdentifier!,
              // @ts-ignore
              memberAgents,
              name,
            }),
          );
        } else {
          // Update existing group - create new version
          log('Creating new version for group: %s', finalIdentifier);

          await withActingAccountHeader(ctx.marketSDK, actAs, () =>
            ctx.marketSDK.agentGroups.createAgentGroupVersion({
              ...groupData,
              identifier: finalIdentifier!,
              // @ts-ignore
              memberAgents,
              name,
            }),
          );
        }

        return {
          identifier: finalIdentifier,
          isNewGroup,
          success: true,
        };
      } catch (error) {
        log('Error in publishOrCreate: %O', error);
        throw new TRPCError({
          cause: error,
          code: 'INTERNAL_SERVER_ERROR',
          message: error instanceof Error ? error.message : 'Failed to publish group',
        });
      }
    }),

  /**
   * Unpublish agent group
   * POST /market/agent-group/:identifier/unpublish
   */
  unpublishAgentGroup: agentGroupWriteProcedure
    .input(z.object({ identifier: z.string() }))
    .mutation(async ({ input, ctx }) => {
      log('unpublishAgentGroup input: %O', input);

      try {
        const unpublishUrl = `${MARKET_BASE_URL}/api/v1/agent-groups/${input.identifier}/unpublish`;

        const headers: Record<string, string> = {
          'Content-Type': 'application/json',
        };

        const userInfo = ctx.marketUserInfo as TrustedClientUserInfo | undefined;
        const accessToken = (ctx as { marketOidcAccessToken?: string }).marketOidcAccessToken;

        if (userInfo) {
          const trustedClientToken = generateTrustedClientToken(userInfo);
          if (trustedClientToken) {
            headers['x-lobe-trust-token'] = trustedClientToken;
          }
        }

        if (!headers['x-lobe-trust-token'] && accessToken) {
          headers['Authorization'] = `Bearer ${accessToken}`;
        }

        const response = await fetch(unpublishUrl, {
          headers,
          method: 'POST',
        });

        if (!response.ok) {
          const errorText = await response.text();
          log(
            'Unpublish agent group failed: %s %s - %s',
            response.status,
            response.statusText,
            errorText,
          );
          throw new Error(`Failed to unpublish agent group: ${response.statusText}`);
        }

        log('Unpublish agent group success');
        return { success: true };
      } catch (error) {
        log('Error unpublishing agent group: %O', error);
        throw new TRPCError({
          cause: error,
          code: 'INTERNAL_SERVER_ERROR',
          message: error instanceof Error ? error.message : 'Failed to unpublish agent group',
        });
      }
    }),
});

export type AgentGroupRouter = typeof agentGroupRouter;
