unit frm_CalidadHitos;

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
  TfrmCalidadHitos = 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;
  private
    procedure dbGridMainCellClick(Column: TColumn);
    procedure dbGridMainKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
  public
    { Public declarations }
  end;

var
  frmCalidadHitos: TfrmCalidadHitos;

implementation

uses
  dmg_Main, frm_CalidadHitosEditor, uDbErrorHandler;

{$R *.dfm}

procedure TfrmCalidadHitos.FormShow(Sender: TObject);
begin
  AlphaFilterField := 'nombre';
  StatusFilterField := 'activo';
  StatusValues.Clear;
  StatusValues.Add('Activo');
  StatusValues.Add('Inactivo');
  DateFilterField := 'created_at';

  inherited;
  frmCalidadHitos := Self;
  OnDestroy := FormDestroy;
  pnlSearch.Visible := True;
  lblSearch.Caption := 'Buscar Hito Operativo:';

  dbGridMain.Options := dbGridMain.Options + [dgEditing] - [dgRowSelect];
  dbGridMain.OnCellClick := dbGridMainCellClick;
  dbGridMain.OnKeyDown := dbGridMainKeyDown;
end;

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

procedure TfrmCalidadHitos.btnRefreshClick(Sender: TObject);
var
  LSql: string;
begin
  FQryMain.Close;
  LSql :=
    'SELECT h.id, h.codigo, h.nombre, h.modulo_origen, h.evento_disparador, ' +
    '       CAST(h.descripcion AS CHAR(255)) as descripcion, h.es_bloqueante, h.activo, h.created_at, ' +
    '       (SELECT COUNT(*) FROM ge_calidad_hitos_documentos hd WHERE hd.id_hito = h.id AND hd.activo = 1) AS num_docs ' +
    'FROM ge_calidad_hitos h ';

  if Trim(edtSearch.Text) <> '' then
  begin
    LSql := LSql + 'WHERE h.nombre LIKE :search OR h.codigo LIKE :search OR h.modulo_origen LIKE :search ';
  end;
  LSql := LSql + 'ORDER BY h.modulo_origen, h.nombre';

  FQryMain.SQL.Text := LSql;

  if Trim(edtSearch.Text) <> '' then
    FQryMain.ParamByName('search').AsString := '%' + Trim(edtSearch.Text) + '%';

  FQryMain.Open;

  // Configurar FireDAC para permitir edición in-situ
  FQryMain.UpdateOptions.UpdateTableName := 'ge_calidad_hitos';
  FQryMain.UpdateOptions.KeyFields := 'id';
  FQryMain.UpdateOptions.ReadOnly := False;

  if FQryMain.FindField('activo') <> nil then
    FQryMain.FieldByName('activo').ReadOnly := False;

  // Configurar columnas de la rejilla
  dbGridMain.Columns.Clear;
  with dbGridMain.Columns.Add do
  begin
    FieldName := 'id';
    Title.Caption := 'ID';
    Width := 45;
    ReadOnly := True;
  end;
  with dbGridMain.Columns.Add do
  begin
    FieldName := 'codigo';
    Title.Caption := 'Código Hito';
    Width := 150;
    ReadOnly := True;
  end;
  with dbGridMain.Columns.Add do
  begin
    FieldName := 'nombre';
    Title.Caption := 'Nombre del Hito Operativo';
    Width := 240;
    ReadOnly := True;
  end;
  with dbGridMain.Columns.Add do
  begin
    FieldName := 'modulo_origen';
    Title.Caption := 'Departamento / Módulo';
    Width := 130;
    ReadOnly := True;
  end;
  with dbGridMain.Columns.Add do
  begin
    FieldName := 'evento_disparador';
    Title.Caption := 'Evento Disparador';
    Width := 150;
    ReadOnly := True;
  end;
  with dbGridMain.Columns.Add do
  begin
    FieldName := 'num_docs';
    Title.Caption := 'Nº Docs';
    Width := 65;
    ReadOnly := True;
  end;
  with dbGridMain.Columns.Add do
  begin
    FieldName := 'es_bloqueante';
    Title.Caption := 'Bloqueante';
    Width := 75;
    ReadOnly := True;
  end;
  with dbGridMain.Columns.Add do
  begin
    FieldName := 'activo';
    Title.Caption := 'Activo';
    Width := 60;
  end;

  inherited btnRefreshClick(Sender);
end;

procedure TfrmCalidadHitos.btnNewClick(Sender: TObject);
var
  LFrm: TfrmCalidadHitosEditor;
begin
  inherited;
  LFrm := TfrmCalidadHitosEditor.Create(Application);
  try
    LFrm.HitoId := 0;
    LFrm.ParentForm := Self;
    if LFrm.ShowModal = mrOk then
      btnRefreshClick(nil);
  finally
    LFrm.Free;
  end;
end;

procedure TfrmCalidadHitos.btnEditClick(Sender: TObject);
var
  LFrm: TfrmCalidadHitosEditor;
begin
  inherited;
  if FQryMain.IsEmpty then Exit;

  LFrm := TfrmCalidadHitosEditor.Create(Application);
  try
    LFrm.HitoId := FQryMain.FieldByName('id').AsInteger;
    LFrm.ParentForm := Self;
    if LFrm.ShowModal = mrOk then
      btnRefreshClick(nil);
  finally
    LFrm.Free;
  end;
end;

procedure TfrmCalidadHitos.btnDeleteClick(Sender: TObject);
var
  LId: Integer;
begin
  if FQryMain.IsEmpty then Exit;

  if MessageDlg('¿Está seguro de que desea eliminar el hito seleccionado y sus asociaciones documentales?',
    mtConfirmation, [mbYes, mbNo], 0) = mrYes then
  begin
    LId := FQryMain.FieldByName('id').AsInteger;
    dmgMain.qryExec.Close;
    dmgMain.qryExec.SQL.Text := 'DELETE FROM ge_calidad_hitos WHERE id = :id';
    dmgMain.qryExec.ParamByName('id').AsInteger := LId;
    try
      dmgMain.qryExec.ExecSQL;
      btnRefreshClick(nil);
    except
      on E: Exception do
        ShowMessage('No se pudo eliminar el hito: ' + E.Message);
    end;
  end;
end;

function GetFieldBool(AField: TField): Boolean;
begin
  if (AField = nil) or AField.IsNull then
    Result := False
  else if AField.DataType = ftBoolean then
    Result := AField.AsBoolean
  else if AField.DataType in [ftSmallint, ftInteger, ftWord, ftShortint, ftLargeint] then
    Result := (AField.AsInteger <> 0)
  else
    Result := (AField.AsString = '1') or SameText(AField.AsString, 'True') or SameText(AField.AsString, 'S') or SameText(AField.AsString, 'T');
end;

procedure TfrmCalidadHitos.dbGridMainCellClick(Column: TColumn);
var
  LNewVal: Integer;
begin
  if not Assigned(Column) or (Column.FieldName <> 'activo') then Exit;
  if FQryMain.IsEmpty then Exit;

  if GetFieldBool(FQryMain.FieldByName('activo')) then
    LNewVal := 0
  else
    LNewVal := 1;

  try
    dmgMain.qryExec.Close;
    dmgMain.qryExec.SQL.Text :=
      'UPDATE ge_calidad_hitos SET activo = :act, updated_at = NOW(), id_user_update = :user WHERE id = :id';
    dmgMain.qryExec.ParamByName('act').AsInteger := LNewVal;
    dmgMain.qryExec.ParamByName('user').AsString := dmgMain.CurrentUserId;
    dmgMain.qryExec.ParamByName('id').AsInteger := FQryMain.FieldByName('id').AsInteger;
    dmgMain.qryExec.ExecSQL;

    FQryMain.Edit;
    if FQryMain.FieldByName('activo').DataType = ftBoolean then
      FQryMain.FieldByName('activo').AsBoolean := (LNewVal = 1)
    else
      FQryMain.FieldByName('activo').AsInteger := LNewVal;
    FQryMain.Post;
  except
    on E: Exception do
      ShowMessage('Error al actualizar el estado del hito: ' + E.Message);
  end;
end;

procedure TfrmCalidadHitos.dbGridMainKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
  if Key = VK_SPACE then
  begin
    if (dbGridMain.SelectedField <> nil) and (dbGridMain.SelectedField.FieldName = 'activo') then
    begin
      dbGridMainCellClick(dbGridMain.Columns[dbGridMain.SelectedIndex]);
      Key := 0;
    end;
  end;
end;

end.
