# Ruby Calculator - Interactive calculator built with Ruby on Rails
# Author: RSK World (Molla Samser, Founder | Rima Khatun, Designer & Tester)
# Contact: help@rskworld.in | +91 93305 39277
# Website: https://rskworld.in
# Year: 2026
# Description: Build a fully functional calculator using Ruby on Rails with modern UI

class EquationSolver
  def self.solve_linear_equation(equation)
    # Solve equations of form ax + b = c
    cleaned = equation.gsub(/\s+/, '').downcase
    
    if match = cleaned.match(/([+-]?\d*\.?\d*)x([+-]\d+\.?\d*)=([+-]?\d+\.?\d*)/)
      a = match[1].empty? ? 1 : match[1].to_f
      b = match[2].to_f
      c = match[3].to_f
      
      if a != 0
        x = (c - b) / a
        { type: 'linear', solution: x, steps: ["#{a}x + #{b} = #{c}", "#{a}x = #{c - b}", "x = #{(c - b) / a}"] }
      else
        { type: 'linear', solution: nil, error: 'No solution or infinite solutions' }
      end
    else
      { type: 'linear', solution: nil, error: 'Invalid equation format' }
    end
  end
  
  def self.solve_quadratic_equation(equation)
    # Solve equations of form ax² + bx + c = 0
    cleaned = equation.gsub(/\s+/, '').gsub(/\^2/, '²').downcase
    
    if match = cleaned.match(/([+-]?\d*\.?\d*)x²([+-]\d*\.?\d*)x([+-]\d+\.?\d*)=0/)
      a = match[1].empty? ? 1 : match[1].to_f
      b = match[2].empty? ? 0 : match[2].to_f
      c = match[3].to_f
      
      discriminant = b**2 - 4*a*c
      
      if discriminant > 0
        sqrt_discriminant = Math.sqrt(discriminant)
        x1 = (-b + sqrt_discriminant) / (2*a)
        x2 = (-b - sqrt_discriminant) / (2*a)
        
        {
          type: 'quadratic',
          solutions: [x1, x2],
          discriminant: discriminant,
          steps: [
            "#{a}x² + #{b}x + #{c} = 0",
            "Discriminant = #{b}² - 4(#{a})(#{c}) = #{discriminant}",
            "√Discriminant = #{sqrt_discriminant.round(4)}",
            "x₁ = (-#{b} + #{sqrt_discriminant.round(4)}) / (#{2*a}) = #{x1.round(4)}",
            "x₂ = (-#{b} - #{sqrt_discriminant.round(4)}) / (#{2*a}) = #{x2.round(4)}"
          ]
        }
      elsif discriminant == 0
        x = -b / (2*a)
        {
          type: 'quadratic',
          solutions: [x],
          discriminant: discriminant,
          steps: [
            "#{a}x² + #{b}x + #{c} = 0",
            "Discriminant = #{b}² - 4(#{a})(#{c}) = #{discriminant}",
            "x = -#{b} / (#{2*a}) = #{x.round(4)}"
          ]
        }
      else
        {
          type: 'quadratic',
          solutions: [],
          discriminant: discriminant,
          error: 'No real solutions (discriminant < 0)',
          complex_solutions: solve_complex_quadratic(a, b, c)
        }
      end
    else
      { type: 'quadratic', solution: nil, error: 'Invalid quadratic equation format' }
    end
  end
  
  def self.solve_system_of_equations(equations)
    # Solve 2x2 linear system: ax + by = c, dx + ey = f
    eq1 = equations[0].gsub(/\s+/, '').downcase
    eq2 = equations[1].gsub(/\s+/, '').downcase
    
    if eq1.match(/([+-]?\d*\.?\d*)x([+-]\d*\.?\d*)y=([+-]?\d+\.?\d*)/) &&
       eq2.match(/([+-]?\d*\.?\d*)x([+-]\d*\.?\d*)y=([+-]?\d+\.?\d*)/)
      
      match1 = eq1.match(/([+-]?\d*\.?\d*)x([+-]\d*\.?\d*)y=([+-]?\d+\.?\d*)/)
      match2 = eq2.match(/([+-]?\d*\.?\d*)x([+-]\d*\.?\d*)y=([+-]?\d+\.?\d*)/)
      
      a = match1[1].empty? ? 1 : match1[1].to_f
      b = match1[2].to_f
      c = match1[3].to_f
      d = match2[1].empty? ? 1 : match2[1].to_f
      e = match2[2].to_f
      f = match2[3].to_f
      
      determinant = a*e - b*d
      
      if determinant != 0
        x = (c*e - b*f) / determinant
        y = (a*f - c*d) / determinant
        
        {
          type: 'system',
          solutions: { x: x, y: y },
          determinant: determinant,
          steps: [
            "Equation 1: #{a}x + #{b}y = #{c}",
            "Equation 2: #{d}x + #{e}y = #{f}",
            "Determinant = #{a}*#{e} - #{b}*#{d} = #{determinant}",
            "x = (#{c}*#{e} - #{b}*#{f}) / #{determinant} = #{x.round(4)}",
            "y = (#{a}*#{f} - #{c}*#{d}) / #{determinant} = #{y.round(4)}"
          ]
        }
      else
        { type: 'system', solution: nil, error: 'No unique solution (determinant = 0)' }
      end
    else
      { type: 'system', solution: nil, error: 'Invalid system format' }
    end
  end
  
  def self.solve_cubic_equation(equation)
    # Simplified cubic solver for equations of form x³ + ax² + bx + c = 0
    cleaned = equation.gsub(/\s+/, '').gsub(/\^3/, '³').downcase
    
    if match = cleaned.match(/([+-]?\d*\.?\d*)x³([+-]\d*\.?\d*)x²([+-]\d*\.?\d*)x([+-]\d+\.?\d*)=0/)
      a = match[1].empty? ? 1 : match[1].to_f
      b = match[2].empty? ? 0 : match[2].to_f
      c = match[3].empty? ? 0 : match[3].to_f
      d = match[4].to_f
      
      # Normalize to monic form
      if a != 1
        b /= a
        c /= a
        d /= a
        a = 1
      end
      
      # Use Cardano's method (simplified)
      p = c - (b**2)/3
      q = (2*b**3)/27 - (b*c)/3 + d
      
      discriminant = (q**2)/4 + (p**3)/27
      
      if discriminant > 0
        # One real root
        u = Math.cubert(-q/2 + Math.sqrt(discriminant))
        v = Math.cubert(-q/2 - Math.sqrt(discriminant))
        x = u + v - b/3
        
        {
          type: 'cubic',
          solutions: [x],
          discriminant: discriminant,
          steps: ["One real solution: x = #{x.round(4)}"]
        }
      else
        # Three real roots (simplified approximation)
        roots = find_cubic_roots_numerically(a, b, c, d)
        {
          type: 'cubic',
          solutions: roots,
          discriminant: discriminant,
          steps: ["Three real solutions: #{roots.map { |r| r.round(4) }.join(', ')}"]
        }
      end
    else
      { type: 'cubic', solution: nil, error: 'Invalid cubic equation format' }
    end
  end
  
  private
  
  def self.solve_complex_quadratic(a, b, c)
    discriminant = b**2 - 4*a*c
    sqrt_discriminant = Math.sqrt(-discriminant)
    
    real_part = -b / (2*a)
    imag_part = sqrt_discriminant / (2*a)
    
    [
      { real: real_part, imaginary: imag_part },
      { real: real_part, imaginary: -imag_part }
    ]
  end
  
  def self.find_cubic_roots_numerically(a, b, c, d)
    # Simple numerical approach for finding cubic roots
    roots = []
    
    # Try different initial guesses
    [-10, -5, -2, -1, -0.5, 0, 0.5, 1, 2, 5, 10].each do |initial|
      root = newton_method_cubic(a, b, c, d, initial)
      if root && !roots.any? { |r| (r - root).abs < 0.001 }
        roots << root
        break if roots.length >= 3
      end
    end
    
    roots
  end
  
  def self.newton_method_cubic(a, b, c, d, initial)
    x = initial
    50.times do
      fx = a*x**3 + b*x**2 + c*x + d
      fpx = 3*a*x**2 + 2*b*x + c
      
      return nil if fpx.abs < 0.0001
      
      x_new = x - fx/fpx
      return x if (x_new - x).abs < 0.0001
      x = x_new
    end
    nil
  end
end
