# typed: strict
# frozen_string_literal: true

module Stats
  # Simplified plotting class with extracted common functionality
  class Plotter
    extend T::Sig

    sig do
      params(
        title: String,
        train_x: T::Array[Float],
        train_y: T::Array[Float],
        eval_x: T::Array[Float],
        eval_y: T::Array[Float],
      ).void
    end
    def plot_train_eval_scatter(title, train_x, train_y, eval_x, eval_y)
      plot_with_error_handling(title) do
        plot =
          UnicodePlot.scatterplot(
            train_x,
            train_y,
            title: title,
            name: "Training Data",
            width: 80,
            height: 20,
            xlabel: "fav_fa_id",
            ylabel: date_axis_label(train_y + eval_y),
          )
        UnicodePlot.scatterplot!(plot, eval_x, eval_y, name: "Evaluation Data")
        plot
      end
    end

    sig do
      params(
        title: String,
        x_values: T::Array[Float],
        y_values: T::Array[Float],
      ).void
    end
    def plot_scatter(title, x_values, y_values)
      plot_with_error_handling(title) do
        UnicodePlot.scatterplot(
          x_values,
          y_values,
          title: title,
          width: 80,
          height: 20,
          xlabel: "fav_fa_id",
          ylabel: date_axis_label(y_values),
        )
      end
    end

    sig { params(title: String, result: Stats::RegressionResult).void }
    def plot_regression(title, result)
      subtitle =
        "#{title.split.first} fit (Training R² = #{result.training_r_squared.round(3)}, Evaluation R² = #{result.evaluation_r_squared.round(3)})"
      plot_with_error_handling("#{title} - #{subtitle}") do
        UnicodePlot.lineplot(
          result.x_values,
          result.y_values,
          title: title,
          width: 80,
          height: 20,
          xlabel: "fav_fa_id",
          ylabel: date_axis_label(result.y_values),
        )
      end
    end

    sig do
      params(
        x_values: T::Array[Float],
        y_values: T::Array[Float],
        regressions:
          T::Array[
            [TrainedRegressionModel::ModelType, Stats::RegressionResult]
          ],
      ).void
    end
    def plot_combined(x_values, y_values, regressions)
      plot_with_error_handling("📈 Combined Visualization:") do
        # Base scatter plot
        plot =
          UnicodePlot.scatterplot(
            x_values,
            y_values,
            title: "FaUserPostFav Analysis: Original Data vs Regression Models",
            name: "Original Data",
            width: 100,
            height: 25,
            xlabel: "fav_id",
            ylabel: date_axis_label(y_values),
          )

        # Add regression lines
        regressions.each do |model_type, result|
          UnicodePlot.lineplot!(
            plot,
            result.x_values,
            result.y_values,
            name:
              "#{model_type.serialize.humanize} (Train R²=#{result.training_r_squared.round(3)}, Eval R²=#{result.evaluation_r_squared.round(3)})",
          )
        end
        plot
      end
    end

    private

    sig { params(y_values: T::Array[Float]).returns(String) }
    def date_axis_label(y_values)
      y_min, y_max = y_values.minmax
      start_date = Time.at(y_min).strftime("%Y-%m-%d")
      end_date = Time.at(y_max).strftime("%Y-%m-%d")
      "#{start_date} to #{end_date}"
    end

    sig { params(title: String, block: T.proc.returns(T.untyped)).void }
    def plot_with_error_handling(title, &block)
      puts "\n#{title}"
      begin
        plot = block.call
        puts plot.render
      rescue LoadError
        puts "⚠️  UnicodePlot gem not available. Install with: gem install unicode_plot"
      rescue => e
        puts "⚠️  Error generating plot: #{e.message}"
      end
    end
  end
end
