#include "TFile.h"
#include "TH1.h"
#include "TH2D.h"
#include "TCanvas.h"
#include "TPad.h"
#include "TLegend.h"
#include "TLatex.h"
#include "TVector2.h"
#include "TRandom3.h"
#include "TObject.h"

#include <iostream>
#include <string>

using namespace std;

namespace {

TH2D* MakeToyHist2D(const char* name, int nX, double xMin, double xMax, int nY, double yMin, double yMax, int nFill, int seed)
{
  TH2D* h = new TH2D(name, name, nX, xMin, xMax, nY, yMin, yMax);
  h->SetDirectory(nullptr);

  TRandom3 rng(seed);
  for (int i = 0; i < nFill; ++i) {
    const double x = rng.Gaus(0.0, 2.0);
    const double y = rng.Gaus(0.6, 0.35);
    h->Fill(x, y);
  }
  return h;
}

} // namespace

int Process(const string& inputFileName)
{
  // Minimal structure similar to the original code:
  // open file, get histograms, detach ownership, close file,
  // then continue projections + drawing with many heap objects.

  TH2D* h_data_2d = nullptr;
  TH2D* h_mc_2d = nullptr;
  double potscale = 1.0;

  TFile* input_file_ptr = nullptr;
  if (!inputFileName.empty()) {
    input_file_ptr = TFile::Open(inputFileName.c_str(), "READ");
  }

  if (input_file_ptr && !input_file_ptr->IsZombie()) {
    h_data_2d = dynamic_cast<TH2D*>(input_file_ptr->Get("h_ptrecpsiprime_data_bkgsub"));
    h_mc_2d = dynamic_cast<TH2D*>(input_file_ptr->Get("h_ptrecpsiprime_qelike"));

    if (h_data_2d) h_data_2d->SetDirectory(nullptr);
    if (h_mc_2d) h_mc_2d->SetDirectory(nullptr);

    TVector2* pot = dynamic_cast<TVector2*>(input_file_ptr->Get("pot"));
    if (pot && pot->Y() != 0.0) {
      potscale = pot->X() / pot->Y();
    }

    // Same pattern used in your phase-1 patch.
    input_file_ptr->Close();
    delete input_file_ptr;
    input_file_ptr = nullptr;
  }

  // Fallback so the reproducer can run without an input file.
  if (!h_data_2d || !h_mc_2d) {
    h_data_2d = MakeToyHist2D("h_data_2d", 48, -10.0, 10.0, 24, 0.0, 1.5, 35000, 12345);
    h_mc_2d = MakeToyHist2D("h_mc_2d", 48, -10.0, 10.0, 24, 0.0, 1.5, 36000, 56789);
    potscale = 1.0;
  }

  // Derived objects (no large loops, no output files).
  TH1D* h_data_x = h_data_2d->ProjectionX("h_data_x");
  TH1D* h_mc_x = h_mc_2d->ProjectionX("h_mc_x");
  TH1D* h_data_y = h_data_2d->ProjectionY("h_data_y");
  TH1D* h_mc_y = h_mc_2d->ProjectionY("h_mc_y");

  h_data_x->SetDirectory(nullptr);
  h_mc_x->SetDirectory(nullptr);
  h_data_y->SetDirectory(nullptr);
  h_mc_y->SetDirectory(nullptr);

  h_data_x->Scale(1.0, "width");
  h_mc_x->Scale(potscale, "width");
  h_data_y->Scale(1.0, "width");
  h_mc_y->Scale(potscale, "width");

  TH1D* h_data_x_copy = static_cast<TH1D*>(h_data_x->Clone("h_data_x_copy"));
  TH1D* h_mc_x_copy = static_cast<TH1D*>(h_mc_x->Clone("h_mc_x_copy"));
  TH1D* h_data_y_copy = static_cast<TH1D*>(h_data_y->Clone("h_data_y_copy"));
  TH1D* h_mc_y_copy = static_cast<TH1D*>(h_mc_y->Clone("h_mc_y_copy"));

  h_data_x_copy->SetDirectory(nullptr);
  h_mc_x_copy->SetDirectory(nullptr);
  h_data_y_copy->SetDirectory(nullptr);
  h_mc_y_copy->SetDirectory(nullptr);

  TCanvas* c_main = new TCanvas("c_main_repro", "repro main", 1400, 700);
  c_main->Divide(2, 1);

  c_main->cd(1);
  h_mc_x_copy->SetFillColorAlpha(kRed + 1, 0.30);
  h_mc_x_copy->SetLineColor(kRed + 1);
  h_mc_x_copy->Draw("E2");
  h_data_x_copy->SetMarkerStyle(20);
  h_data_x_copy->SetMarkerSize(0.8);
  h_data_x_copy->Draw("E1 SAME");

  TLegend* leg_x = new TLegend(0.58, 0.68, 0.90, 0.88);
  leg_x->SetBorderSize(0);
  leg_x->SetFillStyle(0);
  leg_x->AddEntry(h_data_x_copy, "Data", "lep");
  leg_x->AddEntry(h_mc_x_copy, "MC", "f");
  leg_x->Draw();

  TLatex* tx1 = new TLatex();
  tx1->SetNDC();
  tx1->SetTextAlign(22);
  tx1->SetTextSize(0.045);
  tx1->DrawLatex(0.50, 0.95, "X projection");

  c_main->cd(2);
  TPad* p_inner = new TPad("p_inner_repro", "", 0.08, 0.10, 0.98, 0.98);
  p_inner->SetBorderMode(0);
  p_inner->Draw();
  p_inner->cd();

  h_mc_y_copy->SetFillColorAlpha(kBlue + 1, 0.30);
  h_mc_y_copy->SetLineColor(kBlue + 1);
  h_mc_y_copy->Draw("E2");
  h_data_y_copy->SetMarkerStyle(20);
  h_data_y_copy->SetMarkerSize(0.8);
  h_data_y_copy->Draw("E1 SAME");

  TLegend* leg_y = new TLegend(0.58, 0.68, 0.90, 0.88);
  leg_y->SetBorderSize(0);
  leg_y->SetFillStyle(0);
  leg_y->AddEntry(h_data_y_copy, "Data", "lep");
  leg_y->AddEntry(h_mc_y_copy, "MC", "f");
  leg_y->Draw();

  TLatex* tx2 = new TLatex();
  tx2->SetNDC();
  tx2->SetTextAlign(22);
  tx2->SetTextSize(0.045);
  tx2->DrawLatex(0.50, 0.95, "Y projection");

  // Same primitive scan style as the original code.
  for (TObject* o : *gPad->GetListOfPrimitives()) {
    TH1* h = dynamic_cast<TH1*>(o);
    if (h) {
      h->GetXaxis()->SetTitle("observable");
      h->GetYaxis()->SetTitle("dN/dx");
    }
  }

  // Intentionally no file/plot outputs.
  // Keep object-lifetime pressure but small scale.
  // Cleanup is intentionally partial to stress shutdown behavior.
  delete c_main;
  delete p_inner;
  delete leg_x;
  delete leg_y;
  delete tx1;
  delete tx2;
  delete h_data_x;
  delete h_mc_x;
  delete h_data_y;
  delete h_mc_y;
  delete h_data_x_copy;
  delete h_mc_x_copy;
  delete h_data_y_copy;
  delete h_mc_y_copy;
  delete h_data_2d;
  delete h_mc_2d;

  return 0;
}

int main(int argc, char* argv[])
{
  TH1::AddDirectory(false);

  string inputFileName;
  if (argc > 1) inputFileName = argv[1];

  cout << "Running reproducer with input: "
       << (inputFileName.empty() ? string("<none, using toy histograms>") : inputFileName)
       << endl;

  return Process(inputFileName);
}
