﻿unit uCursosDocumentos;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, Vcl.StdCtrls, Vcl.Grids, Vcl.DBGrids,
  Data.DB, ZDataset, System.IOUtils, ZAbstractRODataset, ZAbstractDataset;

type
  TfCursosDocumentos = class(TForm)
    pnlTop: TPanel;
    pnlBottom: TPanel;
    pnlLeft: TPanel;
    pnlMain: TPanel;
    gridTrabajadores: TDBGrid;
    gridDocumentos: TDBGrid;
    qryTrabajadores: TZQuery;
    dsTrabajadores: TDataSource;
    qryDocumentos: TZQuery;
    dsDocumentos: TDataSource;
    chkSoloActivos: TCheckBox;
    btnEnviar: TButton;
    btnCerrar: TButton;
    Label1: TLabel;
    cboCuentasEnvio: TComboBox;
    pnlUpload: TPanel;
    Label2: TLabel;
    lblArchivoSeleccionado: TLabel;
    edtDescripcion: TEdit;
    btnSeleccionar: TButton;
    btnSubir: TButton;
    OpenDialog1: TOpenDialog;
    btnBorrar: TButton;
    procedure FormCreate(Sender: TObject);
    procedure FormShow(Sender: TObject);
    procedure btnCerrarClick(Sender: TObject);
    procedure chkSoloActivosClick(Sender: TObject);
    procedure btnEnviarClick(Sender: TObject);
    procedure cboCuentasEnvioChange(Sender: TObject);
    procedure btnSeleccionarClick(Sender: TObject);
    procedure btnSubirClick(Sender: TObject);
    procedure btnBorrarClick(Sender: TObject);

  private
    { Private declarations }
    procedure CargarTrabajadores;
    procedure CargarDocumentos;
    procedure CargarCuentas;
    function GuardarTemporal(Field: TBlobField; const NomArchivo: string): string;
  public
    { Public declarations }
  end;

var
  fCursosDocumentos: TfCursosDocumentos;

implementation

{$R *.dfm}

uses datos, uEmailWhatsApp, uEnviarDocumento;

procedure TfCursosDocumentos.FormCreate(Sender: TObject);
begin
//  ShowMessage('Iniciando FormCreate');
  CargarCuentas;
//  ShowMessage('Fin FormCreate');
end;



procedure TfCursosDocumentos.FormShow(Sender: TObject);
begin
//  ShowMessage('Iniciando FormShow');
  CargarTrabajadores;
//  ShowMessage('Trabajadores cargados');
  CargarDocumentos;
//  ShowMessage('Fin FormShow');
end;



procedure TfCursosDocumentos.CargarCuentas;
var
  Qry: TZQuery;
begin
  cboCuentasEnvio.Items.Clear;
  Qry := TZQuery.Create(nil);
  try
    Qry.Connection := DM.DBagrigest;
    Qry.SQL.Text := 'SELECT id, nombre_perfil FROM config_envio ORDER BY id';
    Qry.Open;
    while not Qry.Eof do
    begin
      cboCuentasEnvio.AddItem(Qry.FieldByName('nombre_perfil').AsString, TObject(Qry.FieldByName('id').AsInteger));
      Qry.Next;
    end;
  finally
    Qry.Free;
  end;

  if cboCuentasEnvio.Items.Count > 0 then
    cboCuentasEnvio.ItemIndex := 0;
end;

procedure TfCursosDocumentos.CargarTrabajadores;
begin
  qryTrabajadores.Close;
  qryTrabajadores.SQL.Text := 'SELECT id, nombre, email, activo FROM trabajadores';
  if chkSoloActivos.Checked then
    qryTrabajadores.SQL.Add(' WHERE activo = 1');
  qryTrabajadores.SQL.Add(' ORDER BY nombre');
  qryTrabajadores.Open;
end;

procedure TfCursosDocumentos.CargarDocumentos;
begin
  qryDocumentos.Close;
  // NO cargar el campo 'archivo' (BLOB) en el grid para evitar lentitud y posibles cuelgues
  qryDocumentos.SQL.Text := 'SELECT id, fecha, descripcion, nomarchivo, extension FROM documentos where iddoc=1';
  qryDocumentos.SQL.Add(' ORDER BY fecha DESC, id DESC');
  try
    qryDocumentos.Open;
  except
    on E: Exception do
      MessageDlg('Error al cargar documentos: ' + E.Message, mtError, [mbOK], 0);
  end;
end;


procedure TfCursosDocumentos.chkSoloActivosClick(Sender: TObject);
begin
  CargarTrabajadores;
end;

procedure TfCursosDocumentos.btnBorrarClick(Sender: TObject);
var Qry: TZQuery;
begin
  Qry := TZQuery.Create(nil);
  try
    Qry.Connection := DM.DBagrigest;
    Qry.SQL.Text := 'delete from documentos where id=:id';
    Qry.ParamByName('id').AsInteger := qryDocumentos.FieldByName('id').asinteger;
    qry.execsql;
    cargardocumentos;
  finally
    qry.free
  end;
 end;

procedure TfCursosDocumentos.btnCerrarClick(Sender: TObject);
begin
  Close;
end;

function TfCursosDocumentos.GuardarTemporal(Field: TBlobField; const NomArchivo: string): string;
var
  TempDir, FullPath: string;
  MS: TMemoryStream;
begin
  Result := '';
  if Field.IsNull then Exit;

  TempDir := TPath.GetTempPath;
  FullPath := TPath.Combine(TempDir, NomArchivo);

  MS := TMemoryStream.Create;
  try
    Field.SaveToStream(MS);
    MS.Position := 0;
    MS.SaveToFile(FullPath);
    Result := FullPath;
  finally
    MS.Free;
  end;
end;

procedure TfCursosDocumentos.btnEnviarClick(Sender: TObject);
var
  i: Integer;
  RutaAdjunto: string;
  NomArchivo: string;
  SelConfigID: Integer;
  SmtpHost, SmtpUsuario, SmtpPassword, SmtpNombre: string;
  SmtpPuerto, WaModo: Integer;
  SmtpSSL: Boolean;
  WaTelefono, WaApiKey, TplEmailAsunto, TplEmailCuerpo, TplWaMensaje, FirmaHTML: string;
  ParaStr, CCOStr: string;
begin
  if cboCuentasEnvio.ItemIndex = -1 then
  begin
    MessageDlg('Seleccione una cuenta de envío.', mtWarning, [mbOK], 0);
    Exit;
  end;

  if qryDocumentos.IsEmpty then
  begin
    MessageDlg('No hay documentos seleccionados.', mtWarning, [mbOK], 0);
    Exit;
  end;

  if gridTrabajadores.SelectedRows.Count = 0 then
  begin
    MessageDlg('Seleccione al menos un trabajador.', mtWarning, [mbOK], 0);
    Exit;
  end;

  SelConfigID := Integer(cboCuentasEnvio.Items.Objects[cboCuentasEnvio.ItemIndex]);

  // Cargar configuración para obtener el correo de envío y plantillas
  LeerConfiguracion(SelConfigID, SmtpHost, SmtpPuerto, SmtpSSL, SmtpUsuario, SmtpPassword, SmtpNombre,
    WaModo, WaTelefono, WaApiKey, TplEmailAsunto, TplEmailCuerpo, TplWaMensaje, FirmaHTML);

  // Obtener el BLOB del documento seleccionado por ID
  with TZQuery.Create(nil) do
  try
    Connection := DM.DBagrigest;
    SQL.Text := 'SELECT nomarchivo, extension, archivo FROM documentos WHERE id = :id';
    ParamByName('id').AsInteger := qryDocumentos.FieldByName('id').AsInteger;
    Open;

    NomArchivo := FieldByName('nomarchivo').AsString;
    if NomArchivo = '' then NomArchivo := 'documento' + qryDocumentos.FieldByName('id').AsString + '.' + qryDocumentos.FieldByName('extension').AsString;

    RutaAdjunto := GuardarTemporal(TBlobField(FieldByName('archivo')), NomArchivo);
  finally
    Free;
  end;

  if RutaAdjunto = '' then
  begin
    MessageDlg('No se pudo generar el archivo temporal del documento.', mtError, [mbOK], 0);
    Exit;
  end;

  ParaStr := '';
  CCOStr := SmtpUsuario; // Añadir el propio correo de envío al principio

  for i := 0 to gridTrabajadores.SelectedRows.Count - 1 do
  begin
    qryTrabajadores.GotoBookmark(gridTrabajadores.SelectedRows.Items[i]);

    if ParaStr = '' then
      ParaStr := qryTrabajadores.FieldByName('email').AsString
    else
    begin
      if CCOStr <> '' then CCOStr := CCOStr + '; ';
      CCOStr := CCOStr + qryTrabajadores.FieldByName('email').AsString;
    end;
  end;

  // Abrir formulario de envío en lugar de enviar directamente
  with TfEnviarDocumento.Create(Self) do
  try
    RutaPDF := RutaAdjunto;
    InitData('', ParaStr, CCOStr, qryDocumentos.FieldByName('descripcion').AsString, '');
    ShowModal;
  finally
    Free;
    if FileExists(RutaAdjunto) then TFile.Delete(RutaAdjunto);
  end;
end;

procedure TfCursosDocumentos.cboCuentasEnvioChange(Sender: TObject);
begin
  // No hay mucho que hacer aquí, se usa al enviar
end;

procedure TfCursosDocumentos.btnSeleccionarClick(Sender: TObject);
begin
  if OpenDialog1.Execute then
  begin
    lblArchivoSeleccionado.Tag := 1; // Mark as selected
    lblArchivoSeleccionado.Caption := ExtractFileName(OpenDialog1.FileName);
    if Trim(edtDescripcion.Text) = '' then
      edtDescripcion.Text := ChangeFileExt(ExtractFileName(OpenDialog1.FileName), '');
  end;
end;

procedure TfCursosDocumentos.btnSubirClick(Sender: TObject);
var
  Qry: TZQuery;
  FileStream: TFileStream;
  Ext: string;
begin
  if lblArchivoSeleccionado.Tag = 0 then
  begin
    MessageDlg('Debe seleccionar un archivo primero.', mtWarning, [mbOK], 0);
    Exit;
  end;

  if Trim(edtDescripcion.Text) = '' then
  begin
    MessageDlg('Debe introducir una descripción.', mtWarning, [mbOK], 0);
    Exit;
  end;

  Screen.Cursor := crHourGlass;
  Qry := TZQuery.Create(nil);
  try
    Qry.Connection := DM.DBagrigest;
    Qry.SQL.Text := 'INSERT INTO documentos (fecha, descripcion, nomarchivo, extension, archivo,iddoc) ' +
                   'VALUES (:fecha, :desc, :nom, :ext, :blob,1)';
    Qry.ParamByName('fecha').AsDateTime := Date;
    Qry.ParamByName('desc').AsString := edtDescripcion.Text;
    Qry.ParamByName('nom').AsString := ExtractFileName(OpenDialog1.FileName);
    Ext := ExtractFileExt(OpenDialog1.FileName);
    if Pos('.', Ext) = 1 then Delete(Ext, 1, 1);
    Qry.ParamByName('ext').AsString := Ext;

    FileStream := TFileStream.Create(OpenDialog1.FileName, fmOpenRead);
    try
      Qry.ParamByName('blob').LoadFromStream(FileStream, ftBlob);
    finally
      FileStream.Free;
    end;

    Qry.ExecSQL;

    MessageDlg('Documento guardado correctamente.', mtInformation, [mbOK], 0);

    // Limpiar campos
    edtDescripcion.Text := '';
    lblArchivoSeleccionado.Caption := 'Ningún archivo elegido';
    lblArchivoSeleccionado.Tag := 0;

    // Recargar lista
    CargarDocumentos;
  finally
    Qry.Free;
    Screen.Cursor := crDefault;
  end;
end;


end.
