import type { NextRequest } from "next/server";
import { z } from "zod";
import { rateLimit } from "@/lib/rate-limit";
import { getClientIp } from "@/lib/current-user";
import { storeOtp } from "@/lib/otp-store";
import { sendOtpSms } from "@/lib/sms";
import { ok, ERR } from "@/lib/api-response";

const Body = z.object({
  phone: z
    .string()
    .regex(/^1[3-9]\d{9}$/, "请输入有效的中国大陆手机号"),
});

/**
 * POST /api/auth/send-otp
 * 发送短信验证码 · 单手机号 60s 限频 / 单 IP 5 分钟 5 次
 */
export async function POST(req: NextRequest) {
  try {
    const parsed = Body.safeParse(await req.json());
    if (!parsed.success) {
      return ERR.VALIDATION(parsed.error.issues[0]?.message ?? "参数错误");
    }
    const { phone } = parsed.data;

    // 限流
    const phoneRl = await rateLimit(`otp:phone:${phone}`, 60, 1);
    if (!phoneRl.allowed) {
      return ERR.RATE_LIMITED();
    }
    const ip = await getClientIp();
    if (ip) {
      const ipRl = await rateLimit(`otp:ip:${ip}`, 300, 5);
      if (!ipRl.allowed) return ERR.RATE_LIMITED();
    }

    // 生成 6 位验证码 + 存储 (Redis 可用走 Redis, 否则走进程内 Map; 始终 5min TTL)
    const code = String(Math.floor(100000 + Math.random() * 900000));
    await storeOtp(phone, code);

    // 开发环境下把验证码打在终端, 方便本地 QA / 排错; 生产不打
    if (process.env.NODE_ENV !== "production") {
      console.log(`[dev-otp] phone=${phone} code=${code} (dev 环境也接受 123456)`);
    }

    // 调阿里云短信发送
    const sms = await sendOtpSms(phone, code);

    if (sms.ok) {
      console.log(`[sms] sent phone=${phone} bizId=${sms.bizId}`);
      return ok({ message: "验证码已发送", expiresIn: 300 });
    }

    // 失败处理：
    //  - SMS 未配置且非生产 → 控制台打 code, 仍返回成功（开发态联调）
    //  - 阿里云明确返回参数 / 触发流控 → 422
    //  - 其它 → 500
    if (sms.errorCode === "SMS_NOT_CONFIGURED") {
      if (process.env.NODE_ENV !== "production") {
        console.log(`[dev-otp] SMS 未配置, 验证码 ${phone}: ${code}（也可用万能码 123456）`);
        return ok({ message: "验证码已发送", expiresIn: 300 });
      }
      console.error("[sms] 生产环境短信未配置, 检查 SMS_* 环境变量");
      return ERR.INTERNAL("短信服务未配置");
    }

    console.error(
      `[sms] 发送失败 phone=${phone} code=${sms.errorCode} message=${sms.errorMessage}`,
    );
    if (sms.errorCode?.startsWith("isv.")) {
      return ERR.VALIDATION(sms.errorMessage ?? "短信发送失败");
    }
    return ERR.INTERNAL("短信发送失败");
  } catch (e) {
    console.error("[POST /api/auth/send-otp]", e);
    return ERR.INTERNAL();
  }
}
