'''
Created on 24-Jul-2025

@author: bthakur
'''

import random

from ._base_subtract_q_gen import BaseSubtractQGen

# SubtractDecQGen
# _subtract_dec_q_gen

class SubtractDecQGen(BaseSubtractQGen):
    """
    Subtraction question generator for decimals.
    Inherits all logic from BaseSubtractQGen, only overrides random pair generation and formatting.
    """
    def __init__(self, min_value=1.00, max_value=99.99, decimal_places=3, **kwargs):
        super().__init__(min_value, max_value, **kwargs)
        self.decimal_places = decimal_places

    def _init_swp_templates(self):
        from ._subtract_dec_word_prob_templates import SubtractDecWordProbTemplates
        swp_templates = SubtractDecWordProbTemplates(self)
        return swp_templates
        pass


    def pattern_recognition(self):
        start, diff = self._rand_pair()
        # Ensure diff is not zero
        while abs(diff) < 1e-6:
            start, diff = self._rand_pair()
        # Generate the pattern
        pattern = [round(start + i * diff, self.decimal_places) for i in range(4)]
        next_term = round(pattern[-1] + diff, self.decimal_places)
        # Calculate actual differences and get subtraction blocks
        differences = []
        subtraction_blocks = []
        for i in range(1, len(pattern)):
            a, b = pattern[i], pattern[i-1]
            diff_val = round(a - b, self.decimal_places)
            differences.append(diff_val)
            _, _, _, block = self.align_and_subtract_block(a, b)
            subtraction_blocks.append(block)
        # Block for next term
        _, _, _, next_term_block = self.align_and_subtract_block(pattern[-1], differences[0],
                                                                 op = "+")
        # Build solution
        solution = "<b>Step 1: Find the difference between consecutive terms using column subtraction:</b><br>"
        for i in range(1, len(pattern)):
            solution += (
                f"${self.sp_latex(pattern[i-1])} \\to {self.sp_latex(pattern[i])}$: "
                f"Difference = ${self.sp_latex(differences[i-1])}$<br>"
                f"<div style='color:#2277bb;margin-left:2em'>{subtraction_blocks[i-1]}</div>"
            )
        solution += "<br><b>Step 2: Check if the difference is common for all pairs.</b><br>"
        all_equal = all(d == differences[0] for d in differences)
        if all_equal:
            solution += f"Yes, all differences are <b>${self.sp_latex(differences[0])}$</b>.<br>"
        else:
            solution += "The differences are not the same. This is not an arithmetic sequence.<br>"
        solution += "<br><b>Step 3: Find the next term by adding the common difference from the last term:</b><br>"
        solution += (
            f"${self.sp_latex(pattern[-1])} + {self.sp_latex(differences[0])} = {self.sp_latex(next_term)}$<br>"
            f"<div style='color:#2277bb;margin-left:2em'>{next_term_block}</div>"
        )
        # Prepare question
        question = (
            f"Find the next number in the pattern:<br>"
            f"{', '.join([f'${self.sp_latex(p)}$' for p in pattern])}, ___"
        )
        return {
            "type": "pattern_recognition",
            "question": question,
            "answer": f"${self.sp_latex(next_term)}$",
            "solution": solution
        }


    def _rand_pair(self):
        # Generate two decimal numbers (a >= b)
        a = round(random.uniform(self.min_value, self.max_value), self.decimal_places)
        b = round(random.uniform(self.min_value, a), self.decimal_places)
        return a, b

    def _align_and_subtract_block(self, a, b, **kwargs):
        op = kwargs.get("op", "-")
        # Map op to a display symbol for block
        op_symbol = {
            '-': '−',
            '+': '+',
            '*': '×',
            '/': '÷'
        }.get(op, op)  # fallback: op itself

        # Compute result
        if op == '-':
            result = a - b
        elif op == '+':
            result = a + b
        elif op == '*':
            result = a * b
        elif op == '/':
            result = a / b  # let Python raise if b == 0
        else:
            result = a - b  # fallback: subtraction

        # Format decimals
        a_int, a_dec = str(a).split('.') if '.' in str(a) else (str(a), '')
        b_int, b_dec = str(b).split('.') if '.' in str(b) else (str(b), '')
        max_int = max(len(a_int), len(b_int))
        max_dec = max(len(a_dec), len(b_dec))
        a_str = a_int.zfill(max_int) + '.' + a_dec.ljust(max_dec, '0')
        b_str = b_int.zfill(max_int) + '.' + b_dec.ljust(max_dec, '0')
        # Ensure correct decimal places in result
        try:
            result_str = f"{float(a_str)} {op} {float(b_str)}"
            result_value = {
                '-': float(a_str) - float(b_str),
                '+': float(a_str) + float(b_str),
                '*': float(a_str) * float(b_str),
                '/': float(a_str) / float(b_str)
            }.get(op, float(a_str) - float(b_str))
            result_str = f"{result_value:0.{max_dec}f}"
        except Exception:
            # fallback to Python result
            result_str = str(result)

        width = max(len(a_str), len(b_str), len(result_str)) + 4
        solid_line = "─" * width
        block = (
            f"<pre style='font-size:1.2em; margin-bottom:0;'>"
            f"{a_str.rjust(width)}\n"
            f"{op_symbol + ' ' + b_str.rjust(width-2)}\n"
            f"{solid_line}\n"
            f"{result_str.rjust(width)}\n"
            f"</pre>"
        )
        return a_str, b_str, result_str, block

    def _result(self, a, b, op = "-"):
        # Result rounded to decimal_places
        self.cal_result(a, b, op)
