import { z } from "zod";
import type { AppConfig } from "@/types/index.js";
import { DEV, SLACK_BOT_USER_ID } from "@/core/constants.js";
import { parseIgnoredCommentLogins } from "@/poller/comment-filter.js";

const configSchema = z
  .object({
    JIRA_EMAIL: z.string().email(),
    JIRA_API_TOKEN: z.string().min(1),
    JIRA_DOMAIN: z.string().min(1),
    JIRA_POLL_ENABLED: z
      .enum(["true", "false"])
      .default("false")
      .transform((v) => v === "true"),
    JIRA_TICKET_REVIEW_ENABLED: z
      .enum(["true", "false"])
      .default("false")
      .transform((v) => v === "true"),
    ATTEND_FEEDBACK_IN_PR_ENABLED: z
      .enum(["true", "false"])
      .default("false")
      .transform((v) => v === "true"),
    PR_MENTION_ENABLED: z
      .enum(["true", "false"])
      .default("false")
      .transform((v) => v === "true"),
    SQUAD_SCOPE: z
      .string()
      .optional()
      .default("*")
      .transform((v) =>
        v === "*" || !v
          ? []
          : v
              .split(",")
              .map((s) => s.trim().toUpperCase())
              .filter(Boolean),
      ),
    GITHUB_BOT_USER: z.string().min(1).default("hu-agent[bot]"),
    IGNORED_COMMENT_LOGINS: z.string().optional().transform(parseIgnoredCommentLogins),
    GITHUB_TOKEN: z.string().optional().default(""),
    GITHUB_APP_ID: z
      .string()
      .optional()
      .transform((v) => (v ? parseInt(v, 10) : undefined)),
    GITHUB_APP_INSTALLATION_ID: z
      .string()
      .optional()
      .transform((v) => (v ? parseInt(v, 10) : undefined)),
    GITHUB_APP_PRIVATE_KEY: z.string().optional().default(""),
    SLACK_BOT_TOKEN: z.string().optional(),
    SLACK_CHANNEL_ID: z.string().optional(),
    SLACK_DAILY_REPORT_CHANNEL_ID: z.string().optional().default("C0ALG71FCHY"),
    SLACK_ALERT_CHANNEL_ID: z.string().optional().default("C0ALL925DJ8"),
    SLACK_PR_COMMENT_CHANNEL_ID: z.string().optional().default("C0ATP60H09E"),
    SLACK_DEV_CHANNEL_ID: z.string().min(1).default(DEV.CHANNEL_ID),
    NODE_ENV: z.string().optional(),
    DAILY_REPORT_ENABLED: z
      .enum(["true", "false"])
      .default("false")
      .transform((v) => v === "true"),
    DAILY_REPORT_HOURS: z
      .string()
      .default("9,17")
      .transform((v) =>
        v
          .split(",")
          .map((s) => parseInt(s.trim(), 10))
          .filter((n) => !isNaN(n) && n >= 0 && n <= 23),
      ),
    DAILY_REPORT_TIMEZONE: z.string().min(1).default("America/Argentina/Buenos_Aires"),
    WORKDIR_PATH: z.string().min(1).default("./workdir"),
    // Optional like ANTHROPIC_API_KEY; the .refine() below requires it only when AGENT_PROVIDER=cursor.
    CURSOR_API_KEY: z.string().optional().default(""),
    CURSOR_MODEL: z.string().min(1).default("auto"),
    AGENT_PROVIDER: z.enum(["claude", "cursor"]).default("cursor"),
    // Empty-string default keeps AppConfig.anthropicApiKey typed as string (non-optional);
    // the .refine() below enforces a real value only when AGENT_PROVIDER=claude.
    ANTHROPIC_API_KEY: z.string().optional().default(""),
    ANTHROPIC_MODEL: z.string().min(1).default("claude-opus-4-8"),
    ANTHROPIC_BASE_URL: z.string().url().optional(),
    PORT: z.coerce.number().int().positive().default(3000),
    LOG_LEVEL: z.enum(["fatal", "error", "warn", "info", "debug", "trace"]).default("info"),
    CODEARTIFACT_DOMAIN: z.string().min(1).default("humand"),
    CODEARTIFACT_DOMAIN_OWNER: z.string().min(1).default("518514628507"),
    CODEARTIFACT_REGION: z.string().min(1).default("us-east-1"),
    DATADOG_API_KEY: z.string().optional().default(""),
    DATADOG_APP_KEY: z.string().optional().default(""),
    DATADOG_SITE: z.string().min(1).default("us5.datadoghq.com"),
    SLACK_MENTIONS_ENABLED: z
      .enum(["true", "false"])
      .default("false")
      .transform((v) => v === "true"),
    SLACK_BOT_USER_ID: z.string().optional().default(SLACK_BOT_USER_ID),
    DYNAMODB_TABLE_NAME: z.string().optional().default(""),
    VIDEO_ATTACHMENTS_ENABLED: z
      .enum(["true", "false"])
      .default("false")
      .transform((v) => v === "true"),
    FFMPEG_PATH: z.string().min(1).default("ffmpeg"),
    FFPROBE_PATH: z.string().min(1).default("ffprobe"),
    DD_METRICS_ENABLED: z.enum(["true", "false"]).optional(),
    DD_AGENT_HOST: z.string().min(1).default("localhost"),
    DD_DOGSTATSD_PORT: z.coerce.number().int().positive().default(8125),
    DD_ENV: z.string().default("dev"),
    SANDBOX_MODE: z
      .enum(["true", "false"])
      .default("false")
      .transform((v) => v === "true"),
  })
  .refine(
    (data) => {
      const hasToken = data.GITHUB_TOKEN != null && data.GITHUB_TOKEN.length > 0;
      const hasApp =
        data.GITHUB_APP_ID != null &&
        data.GITHUB_APP_INSTALLATION_ID != null &&
        data.GITHUB_APP_PRIVATE_KEY != null &&
        data.GITHUB_APP_PRIVATE_KEY.length > 0;
      return hasToken || hasApp;
    },
    {
      message:
        "Set either GITHUB_TOKEN or GITHUB_APP_ID + GITHUB_APP_INSTALLATION_ID + GITHUB_APP_PRIVATE_KEY",
    },
  )
  .refine((data) => data.AGENT_PROVIDER !== "claude" || data.ANTHROPIC_API_KEY.length > 0, {
    message: "ANTHROPIC_API_KEY is required when AGENT_PROVIDER=claude",
    path: ["ANTHROPIC_API_KEY"],
  })
  .refine((data) => data.AGENT_PROVIDER !== "cursor" || data.CURSOR_API_KEY.length > 0, {
    message: "CURSOR_API_KEY is required when AGENT_PROVIDER=cursor",
    path: ["CURSOR_API_KEY"],
  });

export function loadConfig(): AppConfig {
  const result = configSchema.safeParse(process.env);

  if (!result.success) {
    const formatted = result.error.issues
      .map((i) => `  ${i.path.join(".")}: ${i.message}`)
      .join("\n");
    throw new Error(`Invalid environment configuration:\n${formatted}`);
  }

  const env = result.data;
  return {
    jiraEmail: env.JIRA_EMAIL,
    jiraApiToken: env.JIRA_API_TOKEN,
    jiraDomain: env.JIRA_DOMAIN,
    jiraPollEnabled: env.JIRA_POLL_ENABLED,
    prReviewEnabled: env.ATTEND_FEEDBACK_IN_PR_ENABLED,
    prMentionEnabled: env.PR_MENTION_ENABLED,
    squadScope: env.SQUAD_SCOPE,
    githubBotUser: env.GITHUB_BOT_USER,
    ignoredCommentLogins: env.IGNORED_COMMENT_LOGINS,
    githubToken: env.GITHUB_TOKEN ?? "",
    githubAppId: env.GITHUB_APP_ID,
    githubAppInstallationId: env.GITHUB_APP_INSTALLATION_ID,
    githubAppPrivateKey: env.GITHUB_APP_PRIVATE_KEY,
    slackBotToken: env.SLACK_BOT_TOKEN,
    slackChannelId: env.SLACK_CHANNEL_ID,
    slackDailyReportChannelId: env.SLACK_DAILY_REPORT_CHANNEL_ID,
    slackAlertChannelId: env.SLACK_ALERT_CHANNEL_ID,
    slackPrCommentChannelId: env.SLACK_PR_COMMENT_CHANNEL_ID,
    dailyReportEnabled: env.DAILY_REPORT_ENABLED,
    dailyReportHours: env.DAILY_REPORT_HOURS,
    dailyReportTimezone: env.DAILY_REPORT_TIMEZONE,
    workdirPath: env.WORKDIR_PATH,
    cursorApiKey: env.CURSOR_API_KEY,
    cursorModel: env.CURSOR_MODEL,
    agentProvider: env.AGENT_PROVIDER,
    anthropicApiKey: env.ANTHROPIC_API_KEY,
    anthropicModel: env.ANTHROPIC_MODEL,
    anthropicBaseUrl: env.ANTHROPIC_BASE_URL,
    port: env.PORT,
    logLevel: env.LOG_LEVEL,
    codeartifactDomain: env.CODEARTIFACT_DOMAIN,
    codeartifactDomainOwner: env.CODEARTIFACT_DOMAIN_OWNER,
    codeartifactRegion: env.CODEARTIFACT_REGION,
    datadogApiKey: env.DATADOG_API_KEY ?? "",
    datadogAppKey: env.DATADOG_APP_KEY ?? "",
    datadogSite: env.DATADOG_SITE,
    slackMentionsEnabled: env.SLACK_MENTIONS_ENABLED,
    slackBotUserId: env.SLACK_BOT_USER_ID ?? "",
    dynamodbTableName: env.DYNAMODB_TABLE_NAME ?? "",
    jiraTicketReviewEnabled: env.JIRA_TICKET_REVIEW_ENABLED,
    isDev: env.NODE_ENV !== "production",
    slackDevChannelId: env.SLACK_DEV_CHANNEL_ID,
    videoAttachmentsEnabled: env.VIDEO_ATTACHMENTS_ENABLED,
    ffmpegPath: env.FFMPEG_PATH,
    ffprobePath: env.FFPROBE_PATH,
    metricsEnabled:
      env.DD_METRICS_ENABLED !== undefined
        ? env.DD_METRICS_ENABLED === "true"
        : env.NODE_ENV === "production",
    ddAgentHost: env.DD_AGENT_HOST,
    ddDogstatsdPort: env.DD_DOGSTATSD_PORT,
    ddEnv: env.DD_ENV,
    sandboxMode: env.SANDBOX_MODE,
  };
}
