'''
Created on 24-Jul-2025

@author: bthakur
'''

from .._base import BaseQGen

# BaseSubtractWordProbTemplates
# _base_subtract_int_word_prob_templates

class BaseSubtractWordProbTemplates(BaseQGen):
    """
    20 competition-style, high-quality subtraction word problem templates.
    Each method takes (a, b) and returns (question, explanation).
    All problems reduce to a direct subtraction (a - b).
    Suitable for international-level and creative practice.
    """

    def __init__(self, gen_cls, **kwargs):
        # Call parent constructor and set generator type
        super().__init__(**kwargs)
        self._gen_cls = gen_cls
        self.gen_type = gen_cls.get_gen_type()
        # Initialize templates list
        self.templates = None

    def get_gen_cls(self):
        return self._gen_cls

    def get_templates(self):
        if self.templates is None:
            self.templates = self._init_templates()
        return self.templates

    def _init_templates(self):
        """
        Returns a list of all subtraction word problem template methods.
        """
        return [
            self.chocolate_sharing,
            self.two_stage_race,
            self.multi_step_money_exchange,
            self.hidden_subtraction,
            self.inventory_problem,
            self.school_contest,
            self.temperature_change,
            self.rope_cutting,
            self.book_pages,
            self.split_apples,
            self.marathon_remaining,
            self.bag_of_coins,
            self.time_left_exam,
            self.river_flow,
            self.pencil_length,
            self.points_scored,
            self.missing_number_trick,
            self.bags_of_rice,
            self.chess_tournament,
            self.airplane_fuel
        ]

    # 1. Classic multi-step, but answer is a - b
    def chocolate_sharing(self, a, b):
        """
        Alice takes 1/3 of the chocolates and gives b of those to Bob.
        Find how many chocolates are left in the box.
        """
        alice_take = a // 3
        chocolates_left = self.cal_result(a, alice_take, '-')
        # Precompute all latex representations for clarity
        sp_a = self.sp_latex(a)
        sp_b = self.sp_latex(b)
        sp_alice_take = self.sp_latex(alice_take)
        sp_left_by_alice = self.sp_latex(self.cal_result(alice_take, b, '-'))
        sp_chocolates_left = self.sp_latex(chocolates_left)

        gen_cls = self.get_gen_cls()
        a_str, b_str, result_str, subtraction_block = gen_cls.align_and_subtract_block(a, b, with_steps=False)

        question = (
            f"A box contains <b>${sp_a}$</b> chocolates. Alice takes 1/3 of them and gives <b>${sp_b}$</b> of those to Bob. "
            "How many chocolates are left in the box after Alice and Bob take their shares?"
        )
        explanation = (
            f"Alice takes 1/3 of <b>${sp_a}$</b> = <b>${sp_alice_take}$</b>.<br>"
            f"She gives <b>${sp_b}$</b> to Bob and keeps <b>${sp_left_by_alice}$</b>.<br>"
            f"Chocolates left in the box: <b>${sp_a}$</b> − <b>${sp_alice_take}$</b> = <b>${sp_chocolates_left}$</b>."
            f"{subtraction_block}<br>"
        )
        return question, explanation

    # 2. Subtraction of distance (multi-step)
    def two_stage_race(self, a, b):
        """
        Find the distance Julia has left to walk.
        """
        c = self.get_random_middle_num(a, b)

        walking_stage = self.cal_result(a, c, '-')
        left = self.cal_result(walking_stage, b, '-')
        sp_a = self.sp_latex(a)
        sp_b = self.sp_latex(b)
        sp_c = self.sp_latex(c)
        sp_walking_stage = self.sp_latex(walking_stage)
        sp_left = self.sp_latex(left)
        # This problem is two-step, so we skip align_and_subtract_block

        question = (
            f"In a race, Julia runs the first stage of ${sp_c}$ meters. She then walks the next stage. "
            f"If the total distance is <b>${sp_a}$</b> meters, and she’s already completed <b>${sp_b}$</b> meters of walking, "
            "how many meters does she have left to finish?"
        )
        explanation = (
            f"Walking stage = ${sp_a}$ − ${sp_c}$ = <b>${sp_walking_stage}$</b> meters.<br>"
            f"Completed walking: <b>${sp_b}$</b> meters.<br>"
            f"Left to walk: <b>${sp_walking_stage}$</b> − <b>${sp_b}$</b> = <b>${sp_left}$</b> meters."
        )
        return question, explanation

    # 3. Direct subtraction: Money left after buying
    def multi_step_money_exchange(self, a, b):
        """
        Amit had a dollars, spent b dollars on a book.
        How much money is left?
        """
        money_left = self.cal_result(a, b, '-')
        sp_a = self.sp_latex(a)
        sp_b = self.sp_latex(b)
        sp_money_left = self.sp_latex(money_left)

        gen_cls = self.get_gen_cls()
        a_str, b_str, result_str, subtraction_block = gen_cls.align_and_subtract_block(a, b, with_steps=False)

        question = (
            f"Amit had <b>${sp_a}$</b>. He bought a book for <b>${sp_b}$</b>. How much money does he have left?"
        )
        explanation = (
            f"Money left: <b>${sp_a}$ - ${sp_b}$ = ${sp_money_left}$</b>."
            f"{subtraction_block}<br>"
        )
        return question, explanation

    # 4. Direct subtraction: Marbles left after giving away
    def hidden_subtraction(self, a, b):
        """
        Lisa had a marbles. She gave away b marbles.
        How many does she have left?
        """
        marbles_left = self.cal_result(a, b, '-')
        sp_a = self.sp_latex(a)
        sp_b = self.sp_latex(b)
        sp_marbles_left = self.sp_latex(marbles_left)

        gen_cls = self.get_gen_cls()
        a_str, b_str, result_str, subtraction_block = gen_cls.align_and_subtract_block(a, b, with_steps=False)

        question = (
            f"Lisa had <b>${sp_a}$</b> marbles. She gave away <b>${sp_b}$</b> marbles to her friends. How many marbles does she have left?"
        )
        explanation = (
            f"Marbles left: <b>${sp_a}$ - ${sp_b}$ = ${sp_marbles_left}$</b>."
            f"{subtraction_block}<br>"
        )
        return question, explanation

    def inventory_problem(self, a, b):
        """
        shipment: total shipment quantity (computed as c + a + b)
        a: pencils sold Monday
        b: pencils sold Tuesday
        """
        c = self.get_random_middle_num(a, b)
        shipment = c + a + b
        sp_shipment = self.sp_latex(shipment)
        sp_a = self.sp_latex(a)
        sp_b = self.sp_latex(b)
        sp_after_monday = self.sp_latex(shipment - a)
        sp_remaining = self.sp_latex(shipment - a - b)

        gen_cls = self.get_gen_cls()
        # Step 1: Subtract a from shipment
        s1_str, a_str, after_monday_str, block1 = gen_cls.align_and_subtract_block(shipment, a, with_steps=False)
        # Step 2: Subtract b from previous result
        s2_str, b_str, remaining_str, block2 = gen_cls.align_and_subtract_block(shipment - a, b, with_steps=False)

        question = (
            f"A shop received a shipment of <b>${sp_shipment}$</b> pencils. "
            f"On Monday, <b>${sp_a}$</b> pencils were sold. "
            f"On Tuesday, <b>${sp_b}$</b> pencils were sold. "
            f"How many pencils remain in the shop?"
        )
        explanation = (
            f"After Monday: ${sp_shipment} - {sp_a} = {sp_after_monday}$<br>"
            f"{block1}<br>"
            f"After Tuesday: ${sp_after_monday} - {sp_b} = {sp_remaining}$<br>"
            f"{block2}<br>"
            f"So, <b>${sp_remaining}$</b> pencils remain in the shop."
        )
        return question, explanation


    def school_contest(self, a, b):
        """
        a: total students, b: students left after first round.
        """
        after_first = self.cal_result(a, b, '-')
        final = after_first // 2
        sp_a = self.sp_latex(a)
        sp_b = self.sp_latex(b)
        sp_after_first = self.sp_latex(after_first)
        sp_final = self.sp_latex(final)

        gen_cls = self.get_gen_cls()
        a_str, b_str, result_str, subtraction_block = gen_cls.align_and_subtract_block(a, b, with_steps=False)

        question = (
            f"There are <b>${sp_a}$</b> students in a contest. <b>${sp_b}$</b> left after the first round. "
            "Then, half of the remaining students left after the second round. "
            "How many students stayed till the end?"
        )
        explanation = (
            f"After first round: ${sp_a}$ − ${sp_b}$ = <b>${sp_after_first}$</b>.<br>"
            f"Half left: ${sp_after_first}$ / $2$ = <b>${sp_final}$</b> remain."
            f"{subtraction_block}<br>"
        )
        return question, explanation

    # 7. Temperature after increase/decrease (not subtraction but included for variety)
    def temperature_change(self, a, b):
        """
        a: starting temp, b: increase (could be negative for drop).
        """
        noon = self.cal_result(a, b, '+')
        sp_a = self.sp_latex(a)
        sp_b = self.sp_latex(b)
        sp_noon = self.sp_latex(noon)
        # Not a subtraction problem; don't add subtraction_block here

        question = (
            f"The temperature in Oslo was <b>${sp_a}^\\circ$C</b> in the morning and <b>${sp_b}^\\circ$C</b> higher at noon. "
            "What is the temperature at noon?"
        )
        explanation = (
            f"Noon temperature: <b>${sp_a}$ + ${sp_b}$ = ${sp_noon}^\\circ$C</b>."
        )
        return question, explanation

    # 8. Length left after cut
    def rope_cutting(self, a, b):
        """
        a: original rope, b: left after cutting.
        """
        piece_cut = self.cal_result(a, b, '-')
        sp_a = self.sp_latex(a)
        sp_b = self.sp_latex(b)
        sp_piece_cut = self.sp_latex(piece_cut)

        gen_cls = self.get_gen_cls()
        a_str, b_str, result_str, subtraction_block = gen_cls.align_and_subtract_block(a, b, with_steps=False)

        question = (
            f"A rope is <b>${sp_a}$</b> meters long. After Peter cuts off a piece, <b>${sp_b}$</b> meters remain. "
            "How long was the piece he cut off?"
        )
        explanation = (
            f"Piece cut = <b>${sp_a}$ - ${sp_b}$ = ${sp_piece_cut}$</b> meters."
            f"{subtraction_block}<br>"
        )
        return question, explanation

    # 9. Book pages read
    def book_pages(self, a, b):
        """
        a: total pages, b: left unread.
        """
        read = self.cal_result(a, b, '-')
        sp_a = self.sp_latex(a)
        sp_b = self.sp_latex(b)
        sp_read = self.sp_latex(read)

        gen_cls = self.get_gen_cls()
        a_str, b_str, result_str, subtraction_block = gen_cls.align_and_subtract_block(a, b, with_steps=False)

        question = (
            f"A book has <b>${sp_a}$</b> pages. Sarah reads some pages and has <b>${sp_b}$</b> left unread. "
            "How many pages did she read?"
        )
        explanation = (
            f"Pages read = <b>${sp_a}$ - ${sp_b}$ = ${sp_read}$</b>."
            f"{subtraction_block}<br>"
        )
        return question, explanation

    # 10. Apples left after giving and eating
    def split_apples(self, a, b):
        """
        a: total apples, b: eaten after giving away a//4.
        """
        tom = a // 4
        remain_after_tom = self.cal_result(a, tom, '-')
        left = self.cal_result(remain_after_tom, b, '-')
        sp_a = self.sp_latex(a)
        sp_b = self.sp_latex(b)
        sp_tom = self.sp_latex(tom)
        sp_remain_after_tom = self.sp_latex(remain_after_tom)
        sp_left = self.sp_latex(left)

        gen_cls = self.get_gen_cls()
        a_str, b_str, result_str, subtraction_block = gen_cls.align_and_subtract_block(a, b, with_steps=False)

        question = (
            f"A basket contains <b>${sp_a}$</b> apples. Mary gives 1/4 of them to Tom and then eats <b>${sp_b}$</b> apples herself. "
            "How many apples remain?"
        )
        explanation = (
            f"Mary gives <b>${sp_tom}$</b> to Tom. Apples left: ${sp_a}$ - ${sp_tom}$ = <b>${sp_remain_after_tom}$</b>.<br>"
            f"She eats <b>${sp_b}$</b> more, so apples remaining: ${sp_remain_after_tom}$ - ${sp_b}$ = <b>${sp_left}$</b>."
            f"{subtraction_block}<br>"
        )
        return question, explanation

    # 11. Distance left in marathon
    def marathon_remaining(self, a, b):
        """
        a: marathon total, b: already run.
        """
        left = self.cal_result(a, b, '-')
        sp_a = self.sp_latex(a)
        sp_b = self.sp_latex(b)
        sp_left = self.sp_latex(left)

        gen_cls = self.get_gen_cls()
        a_str, b_str, result_str, subtraction_block = gen_cls.align_and_subtract_block(a, b, with_steps=False)

        question = (
            f"A marathon is <b>${sp_a}$</b> km. If Rohan has run <b>${sp_b}$</b> km and then rests, how much farther does he need to run?"
        )
        explanation = (
            f"Distance left: <b>${sp_a}$ - ${sp_b}$ = ${sp_left}$</b> km."
            f"{subtraction_block}<br>"
        )
        return question, explanation

    # 12. Coins left after spending
    def bag_of_coins(self, a, b):
        """
        a: coins at start, b: spent.
        """
        coins_left = self.cal_result(a, b, '-')
        sp_a = self.sp_latex(a)
        sp_b = self.sp_latex(b)
        sp_coins_left = self.sp_latex(coins_left)

        gen_cls = self.get_gen_cls()
        a_str, b_str, result_str, subtraction_block = gen_cls.align_and_subtract_block(a, b, with_steps=False)

        question = (
            f"Jill had <b>${sp_a}$</b> coins. She spent <b>${sp_b}$</b> coins. How many does she have left?"
        )
        explanation = (
            f"Coins left: <b>${sp_a}$ - ${sp_b}$ = ${sp_coins_left}$</b>."
            f"{subtraction_block}<br>"
        )
        return question, explanation

    # 13. Time left for exam
    def time_left_exam(self, a, b):
        """
        a: total minutes, b: minutes spent.
        """
        left = self.cal_result(a, b, '-')
        sp_a = self.sp_latex(a)
        sp_b = self.sp_latex(b)
        sp_left = self.sp_latex(left)

        gen_cls = self.get_gen_cls()
        a_str, b_str, result_str, subtraction_block = gen_cls.align_and_subtract_block(a, b, with_steps=False)

        question = (
            f"A test lasts <b>${sp_a}$</b> minutes. If Anita spends <b>${sp_b}$</b> minutes on Section A, "
            "how many minutes does she have left for Section B?"
        )
        explanation = (
            f"Time left: <b>${sp_a}$ - ${sp_b}$ = ${sp_left}$</b> minutes."
            f"{subtraction_block}<br>"
        )
        return question, explanation

    # 14. River width left to cross
    def river_flow(self, a, b):
        """
        a: total river width, b: distance swum.
        """
        left = self.cal_result(a, b, '-')
        sp_a = self.sp_latex(a)
        sp_b = self.sp_latex(b)
        sp_left = self.sp_latex(left)

        gen_cls = self.get_gen_cls()
        a_str, b_str, result_str, subtraction_block = gen_cls.align_and_subtract_block(a, b, with_steps=False)

        question = (
            f"A river is <b>${sp_a}$</b> meters wide. John swims <b>${sp_b}$</b> meters across and then walks the rest on a bridge. "
            "How many meters does he still need to cross?"
        )
        explanation = (
            f"Distance left to cross: <b>${sp_a}$ - ${sp_b}$ = ${sp_left}$</b> meters."
            f"{subtraction_block}<br>"
        )
        return question, explanation

    # 15. Pencil length after sharpening
    def pencil_length(self, a, b):
        """
        a: original pencil length, b: sharpened off.
        """
        left = self.cal_result(a, b, '-')
        sp_a = self.sp_latex(a)
        sp_b = self.sp_latex(b)
        sp_left = self.sp_latex(left)

        gen_cls = self.get_gen_cls()
        a_str, b_str, result_str, subtraction_block = gen_cls.align_and_subtract_block(a, b, with_steps=False)

        question = (
            f"A pencil was <b>${sp_a}$</b> cm long. After sharpening, it is <b>${sp_b}$</b> cm shorter. What is its length now?"
        )
        explanation = (
            f"Length now: <b>${sp_a}$ - ${sp_b}$ = ${sp_left}$</b> cm."
            f"{subtraction_block}<br>"
        )
        return question, explanation

    # 16. Score difference in game
    def points_scored(self, a, b):
        """
        a: first half points, b: second half points.
        """
        diff = self.cal_result(a, b, '-')
        sp_a = self.sp_latex(a)
        sp_b = self.sp_latex(b)
        sp_diff = self.sp_latex(diff)

        gen_cls = self.get_gen_cls()
        a_str, b_str, result_str, subtraction_block = gen_cls.align_and_subtract_block(a, b, with_steps=False)

        question = (
            f"A team scored <b>${sp_a}$</b> points in the first half and <b>${sp_b}$</b> in the second half. "
            "By how many points did the team outscore itself in the first half compared to the second?"
        )
        explanation = (
            f"Difference: <b>${sp_a}$ - ${sp_b}$ = ${sp_diff}$</b> points."
            f"{subtraction_block}<br>"
        )
        return question, explanation

    # 17. Stickers left after giving away
    def missing_number_trick(self, a, b):
        """
        a: stickers at start, b: given away.
        """
        left = self.cal_result(a, b, '-')
        sp_a = self.sp_latex(a)
        sp_b = self.sp_latex(b)
        sp_left = self.sp_latex(left)

        gen_cls = self.get_gen_cls()
        a_str, b_str, result_str, subtraction_block = gen_cls.align_and_subtract_block(a, b, with_steps=False)

        question = (
            f"Sarah had <b>${sp_a}$</b> stickers. She gave <b>${sp_b}$</b> to her friend. How many does she have now?"
        )
        explanation = (
            f"Stickers left: <b>${sp_a}$ - ${sp_b}$ = ${sp_left}$</b>."
            f"{subtraction_block}<br>"
        )
        return question, explanation

    # 18. Kilograms of rice bought
    def bags_of_rice(self, a, b):
        """
        a: rice at start, b: remaining.
        """
        bought = self.cal_result(a, b, '-')
        sp_a = self.sp_latex(a)
        sp_b = self.sp_latex(b)
        sp_bought = self.sp_latex(bought)

        gen_cls = self.get_gen_cls()
        a_str, b_str, result_str, subtraction_block = gen_cls.align_and_subtract_block(a, b, with_steps=False)

        question = (
            f"A shop has <b>${sp_a}$</b> kg of rice. A customer buys some, and <b>${sp_b}$</b> kg remain. "
            "How many kilograms did the customer buy?"
        )
        explanation = (
            f"Rice bought: <b>${sp_a}$ - ${sp_b}$ = ${sp_bought}$</b> kg."
            f"{subtraction_block}<br>"
        )
        return question, explanation

    # 19. Chess tournament - players advanced
    def chess_tournament(self, a, b):
        """
        a: players at start, b: eliminated.
        """
        left = self.cal_result(a, b, '-')
        sp_a = self.sp_latex(a)
        sp_b = self.sp_latex(b)
        sp_left = self.sp_latex(left)

        gen_cls = self.get_gen_cls()
        a_str, b_str, result_str, subtraction_block = gen_cls.align_and_subtract_block(a, b, with_steps=False)

        question = (
            f"There were <b>${sp_a}$</b> players in a chess tournament. After the first round, <b>${sp_b}$</b> were eliminated. "
            "How many advanced to the next round?"
        )
        explanation = (
            f"Players advanced: <b>${sp_a}$ - ${sp_b}$ = ${sp_left}$</b>."
            f"{subtraction_block}<br>"
        )
        return question, explanation

    # 20. Fuel left in airplane
    def airplane_fuel(self, a, b):
        """
        a: liters at start, b: used.
        """
        left = self.cal_result(a, b, '-')
        sp_a = self.sp_latex(a)
        sp_b = self.sp_latex(b)
        sp_left = self.sp_latex(left)

        gen_cls = self.get_gen_cls()
        a_str, b_str, result_str, subtraction_block = gen_cls.align_and_subtract_block(a, b, with_steps=False)

        question = (
            f"An airplane starts with <b>${sp_a}$</b> liters of fuel. After flying part of its route, it has used up <b>${sp_b}$</b> liters. "
            "How much fuel does it have left?"
        )
        explanation = (
            f"Fuel left: <b>${sp_a}$ - ${sp_b}$ = ${sp_left}$</b> liters."
            f"{subtraction_block}<br>"
        )
        return question, explanation

