unit frm_Eventos;

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, Vcl.Buttons, uAppTheme, FireDAC.Stan.Param, FireDAC.Comp.Client,
  frm_BaseList, Vcl.ComCtrls, System.UITypes;

type
  TfrmEventos = class(TfrmBaseList)
    procedure FormShow(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure btnRefreshClick(Sender: TObject); override;
    procedure btnNewClick(Sender: TObject); override;
    procedure btnEditClick(Sender: TObject); override;
    procedure btnDeleteClick(Sender: TObject); override;
    procedure btnPrintClick(Sender: TObject); override;
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  frmEventos: TfrmEventos;

implementation

uses
  dmg_Main, uDbErrorHandler, frm_EventosEditor, frxClass, frxDBSet;

{$R *.dfm}

procedure TfrmEventos.FormShow(Sender: TObject);
begin
  AlphaFilterField := 'nombre';
  StatusFilterField := 'activo';
  StatusValues.Add('Activo');
  StatusValues.Add('Inactivo');
  DateFilterField := 'fecha_inicio';
  inherited;
  frmEventos := Self;
  OnDestroy := FormDestroy;
  pnlSearch.Visible := True;
  lblSearch.Caption := 'Buscar Evento:';
end;

procedure TfrmEventos.FormDestroy(Sender: TObject);
begin
  if frmEventos = Self then
    frmEventos := nil;
end;

procedure TfrmEventos.btnRefreshClick(Sender: TObject);
var
  LSql: string;
begin
  FQryMain.Close;
  LSql := 'SELECT id, nombre, lugar, fecha_inicio, fecha_fin, activo FROM ge_eventos ';
  
  if Trim(edtSearch.Text) <> '' then
  begin
    LSql := LSql + 'WHERE nombre LIKE :search OR CAST(id AS CHAR) LIKE :search OR lugar LIKE :search ';
  end;
  LSql := LSql + 'ORDER BY fecha_inicio DESC';
  
  FQryMain.SQL.Text := LSql;
  
  if Trim(edtSearch.Text) <> '' then
    FQryMain.ParamByName('search').AsString := '%' + Trim(edtSearch.Text) + '%';
    
  FQryMain.Open;
  
  // Configurar títulos y anchos de columnas de la rejilla
  dbGridMain.Columns.Clear;
  with dbGridMain.Columns.Add do
  begin
    FieldName := 'id';
    Title.Caption := 'ID';
    Width := 80;
  end;
  with dbGridMain.Columns.Add do
  begin
    FieldName := 'nombre';
    Title.Caption := 'Nombre del Evento';
    Width := 250;
  end;
  with dbGridMain.Columns.Add do
  begin
    FieldName := 'lugar';
    Title.Caption := 'Lugar';
    Width := 200;
  end;
  with dbGridMain.Columns.Add do
  begin
    FieldName := 'fecha_inicio';
    Title.Caption := 'Fecha Inicio';
    Width := 130;
  end;
  with dbGridMain.Columns.Add do
  begin
    FieldName := 'fecha_fin';
    Title.Caption := 'Fecha Fin';
    Width := 130;
  end;
  with dbGridMain.Columns.Add do
  begin
    FieldName := 'activo';
    Title.Caption := 'Activo';
    Width := 80;
  end;
end;

procedure TfrmEventos.btnEditClick(Sender: TObject);
begin
  if FQryMain.IsEmpty then Exit;
  
  if not Assigned(frmEventosEditor) then
    Application.CreateForm(TfrmEventosEditor, frmEventosEditor);
  
  frmEventosEditor.ParentForm := Self;
  frmEventosEditor.EventoId := FQryMain.FieldByName('id').AsString;
  if frmEventosEditor.ShowModal = mrOk then
    btnRefreshClick(nil);
end;

procedure TfrmEventos.btnNewClick(Sender: TObject);
begin
  if not Assigned(frmEventosEditor) then
    Application.CreateForm(TfrmEventosEditor, frmEventosEditor);
  
  frmEventosEditor.ParentForm := Self;
  frmEventosEditor.EventoId := '';
  if frmEventosEditor.ShowModal = mrOk then
    btnRefreshClick(nil);
end;

procedure TfrmEventos.btnDeleteClick(Sender: TObject);
begin
  if FQryMain.IsEmpty then Exit;
  
  if MessageDlg('¿Está seguro de que desea eliminar este evento y todos sus materiales asignados?', mtConfirmation, [mbYes, mbNo], 0) = mrYes then
  begin
    try
      dmgMain.qryExec.Close;
      dmgMain.qryExec.SQL.Text := 'DELETE FROM ge_eventos WHERE id = :id';
      dmgMain.qryExec.ParamByName('id').AsString := FQryMain.FieldByName('id').AsString;
      dmgMain.qryExec.ExecSQL;
      btnRefreshClick(nil);
    except
      on E: Exception do
        ShowMessage('Error al eliminar el evento: ' + E.Message);
    end;
  end;
end;

procedure TfrmEventos.btnPrintClick(Sender: TObject);
var
  LEventoId, LReportPath, LLogoPath: string;
  QryEvento, QryMateriales, QryLogo: TFDQuery;
  LImgObj: TfrxComponent;
  LStream: TMemoryStream;
begin
  if FQryMain.IsEmpty or (FQryMain.FindField('id') = nil) or (Trim(FQryMain.FieldByName('id').AsString) = '') then
  begin
    ShowMessage('Debe seleccionar un evento de la lista para imprimir.');
    Exit;
  end;

  LEventoId := Trim(FQryMain.FieldByName('id').AsString);

  LReportPath := ExtractFilePath(ParamStr(0)) + 'reportes\EventoDetalle.fr3';
  if not FileExists(LReportPath) then
  begin
    ShowMessage('No se encuentra la plantilla del reporte en: ' + LReportPath);
    Exit;
  end;

  QryEvento := TFDQuery.Create(nil);
  QryMateriales := TFDQuery.Create(nil);
  try
    // Preparar query del evento maestro
    QryEvento.Connection := dmgMain.dbConn;
    QryEvento.SQL.Text :=
      'SELECT id, id as codigo, nombre, lugar, fecha_inicio, fecha_fin, descripcion, activo ' +
      'FROM ge_eventos WHERE id = :id';
    QryEvento.ParamByName('id').AsString := LEventoId;
    QryEvento.Open;

    if QryEvento.IsEmpty then
    begin
      ShowMessage('No se ha encontrado el evento en la base de datos.');
      Exit;
    end;

    // Preparar query de materiales detalle
    QryMateriales.Connection := dmgMain.dbConn;
    QryMateriales.SQL.Text :=
      'SELECT em.cantidad, em.unidad, ' +
      '  IF(em.material_id IS NOT NULL, COALESCE(em.observaciones, ''''), '''') as observaciones, ' +
      '  COALESCE(mc.codigo, '''') as material_codigo, ' +
      '  IF(em.material_id IS NOT NULL, COALESCE(mc.descripcion, ''''), COALESCE(em.observaciones, '''')) as material_descripcion ' +
      'FROM ge_eventos_materiales em ' +
      'LEFT JOIN ge_eventos_materiales_cat mc ON em.material_id = mc.id ' +
      'WHERE em.evento_id = :evento_id ' +
      'ORDER BY em.id ASC';
    QryMateriales.ParamByName('evento_id').AsString := LEventoId;
    QryMateriales.Open;

    // Configurar los frxDBDatasets de diseño
    dmgMain.frxDBMaster.DataSet := QryEvento;
    dmgMain.frxDBMaster.UserName := 'frxDBMaster';

    dmgMain.frxDBDetalle.DataSet := QryMateriales;
    dmgMain.frxDBDetalle.UserName := 'frxDBDetalle';

    // 1. Cargar la plantilla PRIMERO
    dmgMain.frxInforme.LoadFromFile(LReportPath);

    // 2. Cargar logo de empresa en el componente imgLogo de la cabecera
    LImgObj := dmgMain.frxInforme.FindObject('imgLogo');
    if Assigned(LImgObj) and (LImgObj is TfrxPictureView) then
    begin
      QryLogo := TFDQuery.Create(nil);
      try
        QryLogo.Connection := dmgMain.dbConn;
        QryLogo.SQL.Text := 'SELECT logo FROM ge_empresas WHERE id = :emp_id LIMIT 1';
        QryLogo.ParamByName('emp_id').AsString := dmgMain.CurrentCompanyId;
        QryLogo.Open;
        if (not QryLogo.IsEmpty) and (not TBlobField(QryLogo.FieldByName('logo')).IsNull) then
        begin
          LStream := TMemoryStream.Create;
          try
            TBlobField(QryLogo.FieldByName('logo')).SaveToStream(LStream);
            LStream.Position := 0;
            if LStream.Size > 0 then
            begin
              TfrxPictureView(LImgObj).Picture.LoadFromStream(LStream);
              TfrxPictureView(LImgObj).Visible := True;
            end
            else
              TfrxPictureView(LImgObj).Visible := False;
          finally
            LStream.Free;
          end;
        end
        else
        begin
          LLogoPath := ExtractFilePath(ParamStr(0)) + 'logo_raul.png';
          if FileExists(LLogoPath) then
          begin
            TfrxPictureView(LImgObj).Picture.LoadFromFile(LLogoPath);
            TfrxPictureView(LImgObj).Visible := True;
          end
          else
            TfrxPictureView(LImgObj).Visible := False;
        end;
      finally
        QryLogo.Free;
      end;
    end;

    // 3. Registrar datasets DESPUÉS de cargar la plantilla
    dmgMain.frxInforme.DataSets.Clear;
    dmgMain.frxInforme.DataSets.Add(dmgMain.frxDBMaster);
    dmgMain.frxInforme.DataSets.Add(dmgMain.frxDBDetalle);
    dmgMain.frxInforme.EnabledDataSets.Clear;
    dmgMain.frxInforme.EnabledDataSets.Add(dmgMain.frxDBMaster);
    dmgMain.frxInforme.EnabledDataSets.Add(dmgMain.frxDBDetalle);

    // 4. Mostrar el reporte
    dmgMain.frxInforme.ShowReport;
  finally
    QryEvento.Free;
    QryMateriales.Free;
  end;
end;

end.
