package quant.rich.emoney.util;
import java.security.SecureRandom;

public class ArithmeticCaptchaGen {

    private static final SecureRandom RND = new SecureRandom();
    private static final char[] OPS = new char[]{'+', '-', '×', '÷'};

    public static class Captcha {
        public final int a;
        public final int b;
        public final char op;

        public Captcha(int a, int b, char op) {
            this.a = a;
            this.b = b;
            this.op = op;
        }

        public String expr() {
            return a + " " + op + " " + b;
        }

        public int answer() {
            return switch (op) {
                case '+' -> a + b;
                case '-' -> a - b;
                case '×' -> a * b;
                case '÷' -> a / b; // 保证整除
                default -> throw new IllegalStateException("Unexpected op: " + op);
            };
        }

        @Override
        public String toString() {
            return expr() + " = ?";
        }
    }

    /** 对外：随机生成一题 */
    public static Captcha generate() {
        char op = OPS[RND.nextInt(OPS.length)];
        return generate(op);
    }

    /** 对外：指定运算符生成 */
    public static Captcha generate(char op) {
        return switch (op) {
            case '+' -> genAddCarryAllowedButIfCarryUnitsZero();
            case '-' -> genSubNoBorrowNonNegative();
            case '×' -> genMulNoCarryOneDigit();
            case '÷' -> genDivExact();
            default -> throw new IllegalArgumentException("Unsupported op: " + op);
        };
    }

 // ---------------- +：允许进位；若发生进位，则结果个位必须为 0；且和 <= 100 ----------------
    private static Captcha genAddCarryAllowedButIfCarryUnitsZero() {
        // 仍保留 100 的特殊题（不是必须，但能保证覆盖 100）
        if (RND.nextInt(20) == 0) { // 5% 概率出 100
            if (RND.nextBoolean()) return new Captcha(100, 0, '+');
            return new Captcha(0, 100, '+');
        }

        while (true) {
            int a = RND.nextInt(101); // 0..100
            int b = RND.nextInt(101); // 0..100
            int sum = a + b;
            if (sum > 100) continue;

            if (carryHappened(a, b)) {
                // 发生进位：个位必须为 0
                if (sum % 10 == 0) return new Captcha(a, b, '+');
            } else {
                // 未发生进位：不限制个位
                return new Captcha(a, b, '+');
            }
        }
    }

    /** 判断十进制逐位相加是否发生过进位（任意一位） */
    private static boolean carryHappened(int a, int b) {
        int carry = 0;
        while (a > 0 || b > 0) {
            int da = a % 10;
            int db = b % 10;
            int s = da + db + carry;
            if (s >= 10) return true;
            carry = 0; // 因为 s<10 时 carry 必为 0
            a /= 10;
            b /= 10;
        }
        return false;
    }

    // ---------------- -：无退位，差 >= 0 ----------------
    private static Captcha genSubNoBorrowNonNegative() {
        while (true) {
            int a = RND.nextInt(100); // 0..99
            int b = RND.nextInt(100); // 0..99

            int aT = a / 10, aU = a % 10;
            int bT = b / 10, bU = b % 10;

            // 无退位：每一位都要 a>=b；且整体差>=0
            if (aU >= bU && aT >= bT) {
                return new Captcha(a, b, '-'); // 此时 a>=b 自然成立
            }
        }
    }

    // ---------------- *：无进位；一元为 0..9；另一元每位*d < 10 ----------------
    private static Captcha genMulNoCarryOneDigit() {
        while (true) {
            int d = RND.nextInt(10);   // 0..9 其中一个因子
            int x = RND.nextInt(100);  // 另一元 0..99（你可自行放大范围）

            // 如果 d=0，任何 x 都满足
            if (d == 0) return orderMulOperands(d, x);

            // 对 x 的每一位要求：digit*d < 10 才不会在该位产生进位
            if (allDigitsMulLessThan10(x, d)) {
                return orderMulOperands(d, x);
            }
        }
    }

    private static Captcha orderMulOperands(int d, int x) {
        // 随机决定把 0..9 放左边还是右边
        if (RND.nextBoolean()) return new Captcha(d, x, '×');
        return new Captcha(x, d, '×');
    }

    private static boolean allDigitsMulLessThan10(int x, int d) {
        // x 是非负
        if (x == 0) return true;
        int t = x;
        while (t > 0) {
            int digit = t % 10;
            if (digit * d >= 10) return false;
            t /= 10;
        }
        return true;
    }

    // ---------------- /：必须整除 ----------------
    private static Captcha genDivExact() {
        // 控制题目大小： dividend <= 100
        while (true) {
            int b = 1 + RND.nextInt(10);     // 除数 1..10
            int q = RND.nextInt(21);         // 商 0..20
            int a = b * q;                   // 被除数
            if (a <= 100) return new Captcha(a, b, '÷');
        }
    }

    // demo
    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            Captcha c = generate();
            System.out.println(c.expr() + " = " + c.answer());
        }
    }
}