import { McpServer, ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js';
import { Logger } from '../../utils/logger.js';
import { AtlassianConfig, getJiraV2Client } from '../../utils/atlassian-api-base.js';
import { usersListSchema, userSchema } from '../../schemas/jira.js';
import { Config, Resources } from '../../utils/mcp-helpers.js';

const logger = Logger.getLogger('JiraResource:Users');

/**
 * Helper function to get the list of users from Jira (supports pagination)
 */
async function getUsers(config: AtlassianConfig, startAt = 0, maxResults = 20, accountId?: string, username?: string): Promise<any[]> {
  try {
    const jiraClient = getJiraV2Client(config);
    // jira.js findUsers maps to /rest/api/2/user/search
    return await jiraClient.userSearch.findUsers({
      startAt,
      maxResults,
      accountId: accountId && accountId.trim() ? accountId.trim() : undefined,
      username: username && username.trim() ? username.trim() : undefined
    });
  } catch (error) {
    logger.error(`Error getting Jira users:`, error);
    throw error;
  }
}

/**
 * Helper function to get user details from Jira
 */
async function getUser(config: AtlassianConfig, accountId: string): Promise<any> {
  try {
    const jiraClient = getJiraV2Client(config);
    return await jiraClient.users.getUser({ accountId });
  } catch (error) {
    logger.error(`Error getting Jira user:`, error);
    throw error;
  }
}

/**
 * Register Jira user-related resources
 * @param server MCP Server instance
 */
export function registerUserResources(server: McpServer) {
  logger.info('Registering Jira user resources...');

  // Resource: Root users resource
  server.resource(
    'jira-users-root',
    new ResourceTemplate('jira://users', {
      list: async (_extra) => ({
        resources: [
          {
            uri: 'jira://users',
            name: 'Jira Users',
            description: 'List and search all Jira users (use filters)',
            mimeType: 'application/json'
          }
        ]
      })
    }),
    async (uri, _params, _extra) => {
      const uriString = typeof uri === 'string' ? uri : uri.href;
      return {
        contents: [{
          uri: uriString,
          mimeType: 'application/json',
          text: JSON.stringify({
            message: "Please use a more specific user resource. The Jira API requires parameters to search users.",
            suggestedResources: [
              "jira://users/{accountId} - Get details for a specific user",
              "jira://users/assignable/{projectKey} - Get users who can be assigned in a project",
              "jira://users/role/{projectKey}/{roleId} - Get users with specific role in a project"
            ]
          })
        }]
      };
    }
  );

  // Resource: User details
  server.resource(
    'jira-user-details',
    new ResourceTemplate('jira://users/{accountId}', {
      list: async (_extra) => ({
        resources: [
          {
            uri: 'jira://users/{accountId}',
            name: 'Jira User Details',
            description: 'Get details for a specific Jira user by accountId. Replace {accountId} with the user accountId.',
            mimeType: 'application/json'
          }
        ]
      })
    }),
    async (uri, params, _extra) => {
      let normalizedAccountId = '';
      try {
        const config = Config.getAtlassianConfigFromEnv();
        if (!params.accountId) {
          throw new Error('Missing accountId in URI');
        }
        normalizedAccountId = Array.isArray(params.accountId) ? params.accountId[0] : params.accountId;
        logger.info(`Getting details for Jira user: ${normalizedAccountId}`);
        const user = await getUser(config, normalizedAccountId);
        // Format returned data
        const formattedUser = {
          accountId: user.accountId,
          displayName: user.displayName,
          emailAddress: user.emailAddress,
          active: user.active,
          avatarUrl: user.avatarUrls?.['48x48'] || '',
          timeZone: user.timeZone,
          locale: user.locale
        };

        const uriString = typeof uri === 'string' ? uri : uri.href;
        // Chuẩn hóa metadata/schema cho resource chi tiết user
        return Resources.createStandardResource(
          uriString,
          [formattedUser],
          'user',
          userSchema,
          1,
          1,
          0,
          user.self || ''
        );
      } catch (error) {
        logger.error(`Error getting Jira user ${normalizedAccountId}:`, error);
        throw error;
      }
    }
  );

  // Resource: List of assignable users for a project
  server.resource(
    'jira-users-assignable',
    new ResourceTemplate('jira://users/assignable/{projectKey}', {
      list: async (_extra) => ({
        resources: [
          {
            uri: 'jira://users/assignable/{projectKey}',
            name: 'Jira Assignable Users',
            description: 'List assignable users for a Jira project. Replace {projectKey} with the project key.',
            mimeType: 'application/json'
          }
        ]
      })
    }),
    async (uri, params, _extra) => {
      try {
        const config = Config.getAtlassianConfigFromEnv();
        const projectKey = Array.isArray(params.projectKey) ? params.projectKey[0] : params.projectKey;
        if (!projectKey) throw new Error('Missing projectKey');

        logger.info(`Getting assignable users for project ${projectKey}`);
        const jiraClient = getJiraV2Client(config);

        // Use findAssignableUsers which maps to /rest/api/2/user/assignable/search
        const users = await jiraClient.userSearch.findAssignableUsers({ project: projectKey });

        const formattedUsers = (users || []).map((user: any) => ({
          accountId: user.accountId,
          displayName: user.displayName,
          emailAddress: user.emailAddress,
          active: user.active,
          avatarUrl: user.avatarUrls?.['48x48'] || '',
        }));

        const uriString = typeof uri === 'string' ? uri : uri.href;
        // Chuẩn hóa metadata/schema
        return Resources.createStandardResource(
          uriString,
          formattedUsers,
          'users',
          usersListSchema,
          formattedUsers.length,
          formattedUsers.length,
          0,
          `${config.baseUrl}/jira/people`
        );
      } catch (error) {
        logger.error(`Error getting assignable users for project:`, error);
        throw error;
      }
    }
  );

  // Resource: List of users by role in a project
  server.resource(
    'jira-users-role',
    new ResourceTemplate('jira://users/role/{projectKey}/{roleId}', {
      list: async (_extra) => ({
        resources: [
          {
            uri: 'jira://users/role/{projectKey}/{roleId}',
            name: 'Jira Users by Role',
            description: 'List users by role in a Jira project. Replace {projectKey} and {roleId} with the project key and role ID.',
            mimeType: 'application/json'
          }
        ]
      })
    }),
    async (uri, params, _extra) => {
      try {
        const config = Config.getAtlassianConfigFromEnv();
        const projectKey = Array.isArray(params.projectKey) ? params.projectKey[0] : params.projectKey;
        const roleId = Array.isArray(params.roleId) ? params.roleId[0] : params.roleId;
        if (!projectKey || !roleId) throw new Error('Missing projectKey or roleId');

        logger.info(`Getting users in role for project ${projectKey}, role ${roleId}`);
        const jiraClient = getJiraV2Client(config);

        // API: /rest/api/2/project/{projectIdOrKey}/role/{id}
        // jira.js: client.projectRoles.getProjectRole
        const roleData = await jiraClient.projectRoles.getProjectRole({
          projectIdOrKey: projectKey,
          id: Number(roleId)
        });

        const formattedUsers = (roleData.actors || [])
          .filter((actor: any) => actor.actorUser && actor.actorUser.accountId)
          .map((actor: any) => ({
            accountId: actor.actorUser.accountId,
            displayName: actor.displayName,
            type: 'atlassian-user-role-actor',
            roleId: roleId
          }));

        const uriString = typeof uri === 'string' ? uri : uri.href;
        return Resources.createStandardResource(
          uriString,
          formattedUsers,
          'users',
          usersListSchema,
          formattedUsers.length,
          formattedUsers.length,
          0,
          `${config.baseUrl}/jira/projects/${projectKey}/people`
        );
      } catch (error) {
        logger.error(`Error getting users by role:`, error);
        throw error;
      }
    }
  );

  logger.info('Jira user resources registered successfully');
}