import { z } from 'zod';
import { createSubcommand } from "../../../types.js";
import * as tui from "../../../tui.js";
import { projectGet, orgEnvGet } from '@agentuity/server';
import { getCommand } from "../../../command-prefix.js";
import { resolveOrgId, isOrgScope } from "./org-util.js";
const EnvItemSchema = z.object({
    value: z.string().describe('Variable value'),
    secret: z.boolean().describe('Whether this is a secret'),
    scope: z.enum(['project', 'org']).describe('The scope of the variable'),
});
const EnvListResponseSchema = z.record(z.string(), EnvItemSchema);
export const listSubcommand = createSubcommand({
    name: 'list',
    aliases: ['ls'],
    description: 'List all environment variables and secrets',
    tags: ['read-only', 'fast', 'requires-auth'],
    examples: [
        { command: getCommand('env list'), description: 'List all variables (project + org merged)' },
        { command: getCommand('env list --no-mask'), description: 'Show unmasked values' },
        { command: getCommand('env list --secrets'), description: 'List only secrets' },
        { command: getCommand('env list --env-only'), description: 'List only env vars' },
        {
            command: getCommand('env list --org'),
            description: 'List only organization-level variables',
        },
    ],
    requires: { auth: true, apiClient: true },
    optional: { project: true },
    idempotent: true,
    schema: {
        options: z.object({
            mask: z
                .boolean()
                .default(true)
                .describe('mask secret values in output (use --no-mask to show values)'),
            secrets: z.boolean().default(false).describe('list only secrets'),
            'env-only': z.boolean().default(false).describe('list only environment variables'),
            org: z
                .union([z.boolean(), z.string()])
                .optional()
                .describe('list organization-level variables only (use --org for default org)'),
            orgId: z.string().optional().describe('filter by organization id'),
            projectId: z.string().optional().describe('filter by project id'),
        }),
        response: EnvListResponseSchema,
    },
    webUrl: (ctx) => {
        // If --org flag is used, link to org settings; otherwise link to project settings
        if (ctx.opts?.org) {
            return `/settings/organization/env`;
        }
        return ctx.project
            ? `/projects/${encodeURIComponent(ctx.project.projectId)}/settings`
            : undefined;
    },
    async handler(ctx) {
        const { opts, apiClient, project, options, config } = ctx;
        if (opts?.orgId && opts?.projectId) {
            tui.fatal('--org-id and --project-id are mutually exclusive. Use one or the other.');
        }
        const useOrgScope = isOrgScope(opts?.org) || !!opts?.orgId;
        // Build combined result with type info and scope
        const result = {};
        // Filter based on options
        const showEnv = !opts?.secrets;
        const showSecrets = !opts?.['env-only'];
        if (useOrgScope) {
            // Organization scope only
            const orgId = opts?.orgId ??
                (opts?.org ? await resolveOrgId(apiClient, config, opts.org) : undefined);
            if (!orgId) {
                tui.fatal('Organization ID is required. Use --org-id or --org flag.');
            }
            const orgData = await tui.spinner('Fetching organization variables', () => {
                return orgEnvGet(apiClient, { id: orgId, mask: false });
            });
            const orgEnv = orgData.env || {};
            const orgSecrets = orgData.secrets || {};
            if (showEnv) {
                for (const [key, value] of Object.entries(orgEnv)) {
                    result[key] = { value, secret: false, scope: 'org' };
                }
            }
            if (showSecrets) {
                for (const [key, value] of Object.entries(orgSecrets)) {
                    result[key] = { value, secret: true, scope: 'org' };
                }
            }
        }
        else if (opts?.projectId || project) {
            // Project context: show merged view (org + project, project takes precedence)
            // First, get project's org ID and fetch org env
            const effectiveProjectId = opts?.projectId || project.projectId;
            const projectData = await tui.spinner('Fetching variables', () => {
                return projectGet(apiClient, { id: effectiveProjectId, mask: false });
            });
            const projectEnv = projectData.env || {};
            const projectSecrets = projectData.secrets || {};
            // Try to get org-level env (may fail if no access, that's ok)
            let orgEnv = {};
            let orgSecrets = {};
            if (projectData.orgId) {
                try {
                    const orgData = await orgEnvGet(apiClient, { id: projectData.orgId, mask: false });
                    orgEnv = orgData.env || {};
                    orgSecrets = orgData.secrets || {};
                }
                catch {
                    // Ignore errors - user may not have org env access
                }
            }
            // Add org-level first (will be overridden by project-level)
            if (showEnv) {
                for (const [key, value] of Object.entries(orgEnv)) {
                    result[key] = { value, secret: false, scope: 'org' };
                }
            }
            if (showSecrets) {
                for (const [key, value] of Object.entries(orgSecrets)) {
                    result[key] = { value, secret: true, scope: 'org' };
                }
            }
            // Add project-level (overrides org-level)
            if (showEnv) {
                for (const [key, value] of Object.entries(projectEnv)) {
                    result[key] = { value, secret: false, scope: 'project' };
                }
            }
            if (showSecrets) {
                for (const [key, value] of Object.entries(projectSecrets)) {
                    result[key] = { value, secret: true, scope: 'project' };
                }
            }
        }
        else {
            tui.fatal('Project context required. Run from a project directory or use --org for organization scope.');
        }
        // Skip TUI output in JSON mode
        if (!options.json) {
            if (Object.keys(result).length === 0) {
                tui.info('No variables found');
            }
            else {
                tui.newline();
                const projectCount = Object.values(result).filter((v) => v.scope === 'project').length;
                const orgCount = Object.values(result).filter((v) => v.scope === 'org').length;
                const secretCount = Object.values(result).filter((v) => v.secret).length;
                const envCount = Object.values(result).filter((v) => !v.secret).length;
                const parts = [];
                if (envCount > 0)
                    parts.push(`${envCount} env`);
                if (secretCount > 0)
                    parts.push(`${secretCount} secret${secretCount !== 1 ? 's' : ''}`);
                if (!useOrgScope && projectCount > 0 && orgCount > 0) {
                    parts.push(`${projectCount} project, ${orgCount} org`);
                }
                tui.info(`Variables (${parts.join(', ')}):`);
                tui.newline();
                const sortedKeys = Object.keys(result).sort();
                const shouldMask = opts?.mask !== false;
                for (const key of sortedKeys) {
                    const entry = result[key];
                    if (!entry)
                        continue;
                    const { value, secret, scope } = entry;
                    const displayValue = shouldMask && secret ? tui.maskSecret(value) : value;
                    const typeIndicator = secret ? ' [secret]' : '';
                    const scopeIndicator = !useOrgScope ? ` [${scope}]` : '';
                    console.log(`${tui.bold(key)}=${displayValue}${tui.muted(typeIndicator + scopeIndicator)}`);
                }
            }
        }
        return result;
    },
});
//# sourceMappingURL=list.js.map