unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages,
  System.SysUtils, System.Variants, System.Classes,
  Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls,
  IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient,
  IdIOHandler, IdIOHandlerSocket, IdIOHandlerStack, IdGlobal;

type
  TForm1 = class(TForm)
    ButtonConnect: TButton;
    ButtonDisconnect: TButton;
    LabelStatus: TLabel;
    TCPClient: TIdTCPClient;
    ButtonClosePump: TButton;
    Button1: TButton;
    Edit1: TEdit;
    gp: TEdit;
    gr: TEdit;
    dp: TEdit;
    dr: TEdit;
    kr: TEdit;
    rc: TEdit;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    Label4: TLabel;
    Label5: TLabel;
    Label6: TLabel;
    Button2: TButton; // aquí lo usabas como ID (001,002, etc). Mantengo el nombre para no romper el DFM.
    procedure ButtonConnectClick(Sender: TObject);
    procedure ButtonDisconnectClick(Sender: TObject);
    procedure ButtonClosePumpClick(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    const DEFAULT_PORT = 3011;

    function GetPumpId3: string;
    procedure UpdateStatus(const AMsg: string; AColor: TColor);
    procedure EnsureConnected;
    procedure SendRawCommand(const ACmd: string);
  public
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  // Configuración Indy recomendada
  TCPClient.Port := DEFAULT_PORT;
  TCPClient.ConnectTimeout := 3000;
  TCPClient.ReadTimeout := 3000;

  // Asegura que se envía como texto "plano" (ASCII) y sin conversiones raras.
  if Assigned(TCPClient.IOHandler) then
  begin
    TCPClient.IOHandler.DefStringEncoding := IndyTextEncoding_ASCII;
  end;

  // Valor por defecto del ID (si usas Edit1 para el ID)
  if Trim(Edit1.Text) = '' then
    Edit1.Text := '001';

  UpdateStatus('Desconectado', clRed);
end;

procedure TForm1.UpdateStatus(const AMsg: string; AColor: TColor);
begin
  LabelStatus.Caption := AMsg;
  LabelStatus.Font.Color := AColor;
end;

function TForm1.GetPumpId3: string;
var
  n: Integer;
  s: string;
begin
  // Soporta que el usuario escriba 1, 01, 001, etc.
  s := Trim(Edit1.Text);
  if s = '' then
    s := '1';

  if TryStrToInt(s, n) then
    Result := Format('%.3d', [n])
  else
  begin
    // si no es numérico, intentamos usarlo tal cual pero truncado/ajustado a 3
    s := StringReplace(s, ' ', '', [rfReplaceAll]);
    if Length(s) >= 3 then
      Result := Copy(s, Length(s) - 2, 3)
    else
      Result := StringOfChar('0', 3 - Length(s)) + s;
  end;
end;

procedure TForm1.EnsureConnected;
begin
  if TCPClient.Connected then
    Exit;

  // IMPORTANTE:
  // En tu código original el Host estaba hardcodeado. Aquí seguimos usando el Host del componente (DFM),
  // pero si quieres tomarlo de un Edit para IP, dímelo y te lo ajusto al DFM.
  // Por ahora, respeta TCPClient.Host definido en el diseñador (DFM).

  TCPClient.Connect;
end;

procedure TForm1.SendRawCommand(const ACmd: string);
begin
  // Enviar EXACTO: NO WriteLn (agrega CRLF), usar Write
  // Hercules/PHP suelen mandar en crudo, por eso funciona allí.
  if not TCPClient.Connected then
    raise Exception.Create('No hay conexión activa.');

  // Asegura encoding ASCII
  TCPClient.IOHandler.DefStringEncoding := IndyTextEncoding_ASCII;

  // Envío en crudo (sin CRLF)
  TCPClient.IOHandler.Write(ACmd);

  // Si tu equipo requiere "flush": Indy generalmente envía al instante, pero por seguridad:
  TCPClient.IOHandler.WriteBufferFlush;
end;

procedure TForm1.ButtonConnectClick(Sender: TObject);
begin
  try
    // Host/Port
    TCPClient.Port := DEFAULT_PORT;

    EnsureConnected;

    if TCPClient.Connected then
      UpdateStatus('Conectado', clGreen);
  except
    on E: Exception do
      UpdateStatus('No se pudo conectar: ' + E.Message, clRed);
  end;
end;

procedure TForm1.ButtonDisconnectClick(Sender: TObject);
begin
  try
    if TCPClient.Connected then
    begin
      TCPClient.Disconnect;
      UpdateStatus('Desconectado', clRed);
    end
    else
      UpdateStatus('No hay conexión activa', clBlack);
  except
    on E: Exception do
      UpdateStatus('Error al desconectar: ' + E.Message, clRed);
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  Command: string;
begin
  // ABRIR surtidor
  Command := '00033|5|2||POST|REQ_PUMP_OPEN_ID_' + GetPumpId3 + '||||^';

  try
    EnsureConnected;
    SendRawCommand(Command);
    UpdateStatus('Instrucción enviada: Abrir surtidor', clBlue);
  except
    on E: Exception do
      UpdateStatus('Error al enviar (Abrir): ' + E.Message, clRed);
  end;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  Command: string;
  Command2: string;
begin
  // CERRAR surtidor
  Command := '00218|5|2||POST|REQ_PRICES_SET_NEW_PRICE_CHANGE|||QTY=6|G01NR=1|G01LV=1|G01PR='+gp.Text+'|G02NR=2|G02LV=1|G02PR='+gr.Text;
  Command2:='|G03NR=4|G03LV=1|G03PR='+dr.Text+'|G04NR=3|G04LV=1|G04PR='+dp.Text+'|G05NR=5|G05LV=1|G05PR='+kr.Text+'|G06NR=6|G06LV=1|G06PR='+rc.Text+'||^';
  try
    EnsureConnected;
    SendRawCommand(Command+Command2);
    UpdateStatus('Instrucción enviada: Cerrar surtidor', clBlue);
  except
    on E: Exception do
      UpdateStatus('Error al enviar (Cerrar): ' + E.Message, clRed);
  end;

end;

procedure TForm1.ButtonClosePumpClick(Sender: TObject);
var
  Command: string;
begin
  // CERRAR surtidor
  Command := '00034|5|2||POST|REQ_PUMP_CLOSE_ID_' + GetPumpId3 + '||||^';

  try
    EnsureConnected;
    SendRawCommand(Command);
    UpdateStatus('Instrucción enviada: Cerrar surtidor', clBlue);
  except
    on E: Exception do
      UpdateStatus('Error al enviar (Cerrar): ' + E.Message, clRed);
  end;
end;

end.