﻿unit uConfigEmail;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls, Vcl.ComCtrls, Data.DB, ZAbstractRODataset,
  ZAbstractDataset, ZDataset, System.UITypes, Vcl.ExtDlgs, IdCoderMIME, Winapi.ShellAPI,
  SHDocVw, Vcl.OleCtrls, MSHTML, ActiveX;

type
  TfConfigEmail = class(TForm)
    pnlBottom: TPanel;
    btnGuardar: TButton;
    btnCancelar: TButton;
    PageControl: TPageControl;
    tsEmail: TTabSheet;
    tsFirma: TTabSheet;
    GroupBox1: TGroupBox;
    Label1: TLabel;
    edtSmtpHost: TEdit;
    Label2: TLabel;
    edtSmtpPuerto: TEdit;
    chkSmtpSSL: TCheckBox;
    Label3: TLabel;
    edtSmtpUsuario: TEdit;
    Label4: TLabel;
    edtSmtpPassword: TEdit;
    Label5: TLabel;
    edtSmtpNombre: TEdit;
    btnProbar: TButton;
    GroupBox3: TGroupBox;
    Label9: TLabel;
    edtTplEmailAsunto: TEdit;
    Label10: TLabel;
    mmoTplEmailCuerpo: TMemo;
    pnlTop: TPanel;
    Label12: TLabel;
    cboCuentas: TComboBox;
    btnNueva: TButton;
    btnEliminar: TButton;
    edtNombrePerfil: TEdit;
    // Pestaña Firma
    pnlFirmaTop: TPanel;
    btnInsertarImagen: TButton;
    btnVistaPreviaFirma: TButton;
    Label13: TLabel;
    mmoFirmaHTML: TMemo;
    splFirma: TSplitter;
    procedure cboCuentasChange(Sender: TObject);
    procedure btnNuevaClick(Sender: TObject);
    procedure btnEliminarClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure btnGuardarClick(Sender: TObject);
    procedure btnCancelarClick(Sender: TObject);
    procedure btnProbarClick(Sender: TObject);
    procedure btnInsertarImagenClick(Sender: TObject);
    procedure btnVistaPreviaFirmaClick(Sender: TObject);
    procedure mmoFirmaHTMLChange(Sender: TObject);
    procedure FormShow(Sender: TObject);
  private
    { Private declarations }
    wbrFirmaPreview: TWebBrowser;
    qryConfig: TZQuery;    // Creado en FormCreate, no en DFM
    FActualizandoPreview: Boolean;
    procedure CargarConfiguracion;
    procedure GuardarConfiguracion;
    function ImagenABase64HTML(const RutaImagen: string): string;
    procedure ActualizarPreviewFirma;
  public
    { Public declarations }
  end;

var
  fConfigEmail: TfConfigEmail;

implementation

{$R *.dfm}

uses datos;

// Convierte un fichero de imagen a una etiqueta <img> con datos en base64
function TfConfigEmail.ImagenABase64HTML(const RutaImagen: string): string;
var
  FS: TFileStream;
  B64: string;
  Ext, MimeType: string;
begin
  Result := '';
  if not FileExists(RutaImagen) then Exit;

  Ext := LowerCase(ExtractFileExt(RutaImagen));
  if Ext = '.jpg' then MimeType := 'image/jpeg'
  else if Ext = '.jpeg' then MimeType := 'image/jpeg'
  else if Ext = '.png' then MimeType := 'image/png'
  else if Ext = '.gif' then MimeType := 'image/gif'
  else if Ext = '.bmp' then MimeType := 'image/bmp'
  else if Ext = '.svg' then MimeType := 'image/svg+xml'
  else MimeType := 'image/jpeg';

  FS := TFileStream.Create(RutaImagen, fmOpenRead or fmShareDenyWrite);
  try
    B64 := TIdEncoderMIME.EncodeStream(FS);
  finally
    FS.Free;
  end;

  Result := '<img src="data:' + MimeType + ';base64,' + B64 + '" style="max-width:300px;">';
end;

procedure TfConfigEmail.FormCreate(Sender: TObject);
begin
  // El WebBrowser se creará en FormShow para asegurar que los handles del sistema estén listos
  wbrFirmaPreview := nil;

  // Crear el query de configuración en código (no está en el DFM)
  qryConfig := TZQuery.Create(Self);
  qryConfig.Connection := DM.DBagrigest;
  CargarConfiguracion;
end;

procedure TfConfigEmail.FormShow(Sender: TObject);
begin
  if Assigned(wbrFirmaPreview) then Exit;

  try
    // Asegurar inicialización COM
    OleInitialize(nil);

    wbrFirmaPreview := TWebBrowser.Create(Self);
    TWinControl(wbrFirmaPreview).Parent := tsFirma;
    wbrFirmaPreview.Align := alClient;
    wbrFirmaPreview.Visible := True;
    
    // Cargar el contenido si ya hay algo en el memo
    if mmoFirmaHTML.Text <> '' then
      ActualizarPreviewFirma;
  except
    on E: Exception do
    begin
      wbrFirmaPreview := nil;
      // Silenciamos el error para que la ventana pueda usarse
    end;
  end;
end;

procedure TfConfigEmail.FormDestroy(Sender: TObject);
begin
  qryConfig.Free;
end;

// Renderiza el HTML del memo en el TWebBrowser sin fichero temporal
procedure TfConfigEmail.ActualizarPreviewFirma;
var
  Doc: IHTMLDocument2;
  HTML: WideString;
  V: OleVariant;
begin
  if FActualizandoPreview then Exit;
  FActualizandoPreview := True;
  try
    HTML := '<!DOCTYPE html><html><head><meta charset="UTF-8">' +
            '<style>body{font-family:Tahoma,sans-serif;font-size:10pt;}</style></head><body>' +
            mmoFirmaHTML.Text + '</body></html>';

    if not Assigned(wbrFirmaPreview) then Exit;
    if not wbrFirmaPreview.HandleAllocated then Exit;
    
    wbrFirmaPreview.Navigate('about:blank');
    // Esperar sin bloquear la UI
    while wbrFirmaPreview.ReadyState < READYSTATE_COMPLETE do
      Application.ProcessMessages;

    Doc := wbrFirmaPreview.Document as IHTMLDocument2;
    if Assigned(Doc) then
    begin
      // Usar VarArray para cargar HTML directamente (compatible con todas las versiones de Delphi)
      V := VarArrayCreate([0, 0], varVariant);
      V[0] := HTML;
      Doc.Write(PSafeArray(TVarData(V).VArray));
      Doc.Close;
    end;
  finally
    FActualizandoPreview := False;
  end;
end;

procedure TfConfigEmail.mmoFirmaHTMLChange(Sender: TObject);
begin
  // Actualizar el preview de forma diferida mientras el usuario escribe
  ActualizarPreviewFirma;
end;

procedure TfConfigEmail.CargarConfiguracion;
var
  SelID: Integer;
begin
  // Listar cuentas si el combo esta vacio
  if cboCuentas.Items.Count = 0 then
  begin
    qryConfig.Close;
    qryConfig.SQL.Text := 'SELECT id, nombre_perfil FROM config_envio ORDER BY id';
    qryConfig.Open;
    while not qryConfig.Eof do
    begin
      cboCuentas.AddItem(qryConfig.FieldByName('nombre_perfil').AsString, TObject(qryConfig.FieldByName('id').AsInteger));
      qryConfig.Next;
    end;
    if cboCuentas.Items.Count > 0 then
      cboCuentas.ItemIndex := 0;
  end;

  if cboCuentas.ItemIndex = -1 then Exit;
  
  SelID := Integer(cboCuentas.Items.Objects[cboCuentas.ItemIndex]);

  qryConfig.Close;
  qryConfig.SQL.Text := 'SELECT * FROM config_envio WHERE id = :id';
  qryConfig.ParamByName('id').AsInteger := SelID;
  qryConfig.Open;

  if not qryConfig.IsEmpty then
  begin
    edtNombrePerfil.Text := qryConfig.FieldByName('nombre_perfil').AsString;
    edtSmtpHost.Text := qryConfig.FieldByName('smtp_host').AsString;
    edtSmtpPuerto.Text := qryConfig.FieldByName('smtp_puerto').AsString;
    chkSmtpSSL.Checked := qryConfig.FieldByName('smtp_ssl').AsInteger = 1;
    edtSmtpUsuario.Text := qryConfig.FieldByName('smtp_usuario').AsString;
    edtSmtpPassword.Text := qryConfig.FieldByName('smtp_password').AsString;
    edtSmtpNombre.Text := qryConfig.FieldByName('smtp_nombre').AsString;
    
    edtTplEmailAsunto.Text := qryConfig.FieldByName('tpl_email_asunto').AsString;
    mmoTplEmailCuerpo.Text := qryConfig.FieldByName('tpl_email_cuerpo').AsString;

    // Cargar firma HTML (campo puede que no exista aun)
    try
      mmoFirmaHTML.Text := qryConfig.FieldByName('firma_html').AsString;
    except
      mmoFirmaHTML.Text := '';
    end;
  end;
  qryConfig.Close;
end;

procedure TfConfigEmail.GuardarConfiguracion;
var
  SelID: Integer;
begin
  SelID := 0;
  if cboCuentas.ItemIndex <> -1 then
    SelID := Integer(cboCuentas.Items.Objects[cboCuentas.ItemIndex]);

  qryConfig.Close;
  qryConfig.SQL.Text := 'SELECT * FROM config_envio WHERE id = :id';
  qryConfig.ParamByName('id').AsInteger := SelID;
  qryConfig.Open;

  if qryConfig.IsEmpty then
  begin
    // Buscamos el ID más alto actual antes de insertar
    with TZQuery.Create(nil) do
    try
      Connection := DM.DBagrigest;
      SQL.Text := 'SELECT MAX(id) FROM config_envio';
      Open;
      SelID := Fields[0].AsInteger + 1;
      Close;
    finally
      Free;
    end;

    qryConfig.Insert;
    qryConfig.FieldByName('id').AsInteger := SelID;
  end
  else
    qryConfig.Edit;

  qryConfig.FieldByName('nombre_perfil').AsString := edtNombrePerfil.Text;
  qryConfig.FieldByName('smtp_host').AsString := edtSmtpHost.Text;
  qryConfig.FieldByName('smtp_puerto').AsString := edtSmtpPuerto.Text;
  if chkSmtpSSL.Checked then
    qryConfig.FieldByName('smtp_ssl').AsInteger := 1
  else
    qryConfig.FieldByName('smtp_ssl').AsInteger := 0;
    
  qryConfig.FieldByName('smtp_usuario').AsString := edtSmtpUsuario.Text;
  qryConfig.FieldByName('smtp_password').AsString := edtSmtpPassword.Text;
  qryConfig.FieldByName('smtp_nombre').AsString := edtSmtpNombre.Text;

  qryConfig.FieldByName('tpl_email_asunto').AsString := edtTplEmailAsunto.Text;
  qryConfig.FieldByName('tpl_email_cuerpo').AsString := mmoTplEmailCuerpo.Text;

  // Guardar firma HTML
  try
    qryConfig.FieldByName('firma_html').AsString := mmoFirmaHTML.Text;
  except
    // Si el campo aún no existe en la BD, no fallar
  end;

  qryConfig.Post;
  qryConfig.Close;
  
  // Refrescar lista
  cboCuentas.Clear;
  CargarConfiguracion;
end;

procedure TfConfigEmail.btnCancelarClick(Sender: TObject);
begin
  Close;
end;

procedure TfConfigEmail.btnGuardarClick(Sender: TObject);
begin
  GuardarConfiguracion;
  MessageDlg('Configuración guardada correctamente.', mtInformation, [mbOK], 0);
  Close;
end;

// cboWaModoChange ya no existe porque se eliminaron los controles WhatsApp del formulario

procedure TfConfigEmail.btnProbarClick(Sender: TObject);
begin
  MessageDlg('Por implementar: lógica de prueba SMTP.', mtWarning, [mbOK], 0);
end;

procedure TfConfigEmail.cboCuentasChange(Sender: TObject);
begin
  CargarConfiguracion;
end;

procedure TfConfigEmail.btnNuevaClick(Sender: TObject);
begin
  edtNombrePerfil.Text := 'Nueva Cuenta';
  edtSmtpHost.Text := '';
  edtSmtpPuerto.Text := '587';
  chkSmtpSSL.Checked := True;
  edtSmtpUsuario.Text := '';
  edtSmtpPassword.Text := '';
  edtSmtpNombre.Text := '';
  mmoFirmaHTML.Text := '';
  cboCuentas.ItemIndex := -1;
end;

procedure TfConfigEmail.btnEliminarClick(Sender: TObject);
var
  SelID: Integer;
begin
  if cboCuentas.ItemIndex = -1 then Exit;
  if MessageDlg('¿Confirma eliminar esta cuenta?', mtConfirmation, [mbYes, mbNo], 0) = mrNo then Exit;
  
  SelID := Integer(cboCuentas.Items.Objects[cboCuentas.ItemIndex]);
  qryConfig.Close;
  qryConfig.SQL.Text := 'DELETE FROM config_envio WHERE id = :id';
  qryConfig.ParamByName('id').AsInteger := SelID;
  qryConfig.ExecSQL;
  
  cboCuentas.Clear;
  CargarConfiguracion;
end;

procedure TfConfigEmail.btnInsertarImagenClick(Sender: TObject);
var
  dlg: TOpenPictureDialog;
  TagImg: string;
begin
  dlg := TOpenPictureDialog.Create(Self);
  try
    dlg.Filter := 'Imágenes|*.jpg;*.jpeg;*.png;*.gif;*.bmp;*.svg|Todos los ficheros|*.*';
    dlg.Title := 'Seleccionar imagen para la firma';
    if dlg.Execute then
    begin
      TagImg := ImagenABase64HTML(dlg.FileName);
      if TagImg <> '' then
      begin
        // Insertar en la posición actual del cursor en el memo
        mmoFirmaHTML.SelText := TagImg;
        PageControl.ActivePage := tsFirma;
        MessageDlg('Imagen insertada correctamente.' + #13#10 +
          'La imagen está incrustada en el HTML (no necesita fichero externo).', mtInformation, [mbOK], 0);
      end;
    end;
  finally
    dlg.Free;
  end;
end;

procedure TfConfigEmail.btnVistaPreviaFirmaClick(Sender: TObject);
var
  TempPath, HtmlPath: string;
  FS: TFileStream;
  HTMLDoc: AnsiString;
begin
  if Trim(mmoFirmaHTML.Text) = '' then
  begin
    MessageDlg('La firma está vacía. Escribe el HTML de tu firma primero.', mtInformation, [mbOK], 0);
    Exit;
  end;

  TempPath := IncludeTrailingPathDelimiter(GetEnvironmentVariable('TEMP'));
  HtmlPath := TempPath + 'firma_preview_agrigest.html';

  HTMLDoc := AnsiString(
    '<!DOCTYPE html><html><head><meta charset="UTF-8">' +
    '<title>Vista Previa de Firma</title></head><body>' +
    '<h3 style="font-family:sans-serif;color:#555;">Vista Previa de la Firma</h3>' +
    '<hr style="border:none;border-top:1px solid #ccc;">' +
    mmoFirmaHTML.Text +
    '</body></html>');

  FS := TFileStream.Create(HtmlPath, fmCreate);
  try
    FS.WriteBuffer(HTMLDoc[1], Length(HTMLDoc));
  finally
    FS.Free;
  end;

  ShellExecute(0, 'open', PChar(HtmlPath), nil, nil, SW_SHOWNORMAL);
end;

end.
