import { createClient } from "https://esm.sh/@supabase/supabase-js@2";
import { z } from "../_shared/deps.ts";
import { parseJsonBody } from "../_shared/validate.ts";

const BodySchema = z.object({
  phone: z.string().regex(/^1\d{10}$/, "请输入有效的11位手机号"),
});

const corsHeaders = {
  "Access-Control-Allow-Origin": "*",
  "Access-Control-Allow-Headers":
    "authorization, x-client-info, apikey, content-type",
};

function percentEncode(str: string): string {
  return encodeURIComponent(str)
    .replace(/!/g, "%21")
    .replace(/'/g, "%27")
    .replace(/\(/g, "%28")
    .replace(/\)/g, "%29")
    .replace(/\*/g, "%2A");
}

async function buildAliyunSignature(
  method: string,
  params: Record<string, string>,
  secret: string
): Promise<string> {
  const sorted = Object.keys(params).sort();
  const query = sorted
    .map((k) => `${percentEncode(k)}=${percentEncode(params[k])}`)
    .join("&");
  const sts = `${method}&${percentEncode("/")}&${percentEncode(query)}`;
  const key = new TextEncoder().encode(secret + "&");
  const data = new TextEncoder().encode(sts);
  const ck = await crypto.subtle.importKey(
    "raw",
    key,
    { name: "HMAC", hash: "SHA-1" },
    false,
    ["sign"]
  );
  const sig = await crypto.subtle.sign("HMAC", ck, data);
  return btoa(String.fromCharCode(...new Uint8Array(sig)));
}

Deno.serve(async (req) => {
  if (req.method === "OPTIONS")
    return new Response(null, { headers: corsHeaders });

  try {
    const parsed = await parseJsonBody(req, BodySchema);
    if (!parsed.ok) {
      return new Response(
        JSON.stringify({ error: parsed.message, details: parsed.issues }),
        { status: 400, headers: { ...corsHeaders, "Content-Type": "application/json" } }
      );
    }
    const { phone } = parsed.data;

    const supabase = createClient(
      Deno.env.get("SUPABASE_URL")!,
      Deno.env.get("SUPABASE_SERVICE_ROLE_KEY")!
    );

    await supabase.rpc("cleanup_expired_sms_codes");

    // Rate limit: 60s per phone
    const { data: recent } = await supabase
      .from("sms_verification_codes")
      .select("created_at")
      .eq("phone", phone)
      .eq("verified", false)
      .gte("created_at", new Date(Date.now() - 60000).toISOString())
      .maybeSingle();

    if (recent)
      return new Response(
        JSON.stringify({ error: "发送太频繁，请60秒后重试" }),
        { status: 429, headers: { ...corsHeaders, "Content-Type": "application/json" } }
      );

    const accessKeyId = Deno.env.get("ALIYUN_ACCESS_KEY_ID")!;
    const accessKeySecret = Deno.env.get("ALIYUN_ACCESS_KEY_SECRET")!;
    // 硬编码避免 Supabase Secrets UTF-8 编码问题
    const signName = "速通互联验证码";
    const templateCode = Deno.env.get("ALIYUN_SMS_TEMPLATE_CODE")?.trim() || "100001";

    const now = new Date();
    const params: Record<string, string> = {
      Action: "SendSmsVerifyCode",
      Version: "2017-05-25",
      Format: "JSON",
      AccessKeyId: accessKeyId,
      SignatureMethod: "HMAC-SHA1",
      Timestamp: now.toISOString().replace(/\.\d{3}Z$/, "Z"),
      SignatureVersion: "1.0",
      SignatureNonce: crypto.randomUUID(),
      CountryCode: "86",
      PhoneNumber: phone,
      SignName: signName,
      TemplateCode: templateCode,
      TemplateParam: '{"code":"##code##","min":"5"}',
      CodeType: "1",
      CodeLength: "4",
      ValidTime: "300",
      DuplicatePolicy: "1",
      Interval: "60",
      ReturnVerifyCode: "true",
    };
    params.Signature = await buildAliyunSignature("POST", params, accessKeySecret);

    const formBody = Object.entries(params)
      .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`)
      .join("&");

    console.log("[send-sms-code] DYPNS API call for phone:", phone, "signName:", signName, "templateCode:", templateCode);

    const apiResp = await fetch("https://dypnsapi.aliyuncs.com/", {
      method: "POST",
      headers: { "Content-Type": "application/x-www-form-urlencoded" },
      body: formBody,
    });
    const apiResult = await apiResp.json();

    console.log("[send-sms-code] Aliyun response:", JSON.stringify(apiResult));

    if (apiResult.Code !== "OK")
      return new Response(
        JSON.stringify({ error: apiResult.Message || "短信发送失败" }),
        { status: 500, headers: { ...corsHeaders, "Content-Type": "application/json" } }
      );

    // Verification is performed by Aliyun DYPNS CheckSmsVerifyCode API.
    // We intentionally do NOT persist the plaintext code; this row only
    // tracks send rate-limiting (1 / 60s per phone).
    await supabase.from("sms_verification_codes").delete().eq("phone", phone);
    await supabase.from("sms_verification_codes").insert({
      phone,
      code: null,
      expires_at: new Date(Date.now() + 5 * 60 * 1000).toISOString(),
    });

    return new Response(
      JSON.stringify({ success: true, message: "验证码已发送" }),
      { headers: { ...corsHeaders, "Content-Type": "application/json" } }
    );
  } catch (err) {
    console.error("send-sms-code error:", err);
    return new Response(
      JSON.stringify({ error: "服务器错误" }),
      { status: 500, headers: { ...corsHeaders, "Content-Type": "application/json" } }
    );
  }
});
