unit frm_TrabajadoresGruposEditor;

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.Buttons, Data.DB, FireDAC.Comp.Client, FireDAC.Stan.Param, uAppTheme;

type
  TfrmTrabajadoresGruposEditor = class(TForm)
    pnlTop: TPanel;
    lblTitle: TLabel;
    pnlClient: TPanel;
    lblCodigo: TLabel;
    edtCodigo: TEdit;
    lblNombre: TLabel;
    edtNombre: TEdit;
    chkActivo: TCheckBox;
    lblInfoTrabajadores: TLabel;
    pnlBottom: TPanel;
    btnGuardar: TBitBtn;
    btnCancelar: TBitBtn;

    procedure FormShow(Sender: TObject);
    procedure btnGuardarClick(Sender: TObject);
    procedure btnCancelarClick(Sender: TObject);
  private
    FGrupoId: Integer;

    procedure LoadData;
    function GetNextCodigo: Integer;
    function ExisteCodigo(const ACodigo, AIdExcluir: Integer): Boolean;
  public
    property GrupoId: Integer read FGrupoId write FGrupoId;
  end;

var
  frmTrabajadoresGruposEditor: TfrmTrabajadoresGruposEditor;

implementation

uses
  dmg_Main, uDbErrorHandler;

{$R *.dfm}

procedure TfrmTrabajadoresGruposEditor.FormShow(Sender: TObject);
begin
  TAppTheme.ApplyToForm(Self);

  if FGrupoId > 0 then
  begin
    lblTitle.Caption := '✏️ Editar Grupo de Trabajadores';
    LoadData;
  end
  else
  begin
    lblTitle.Caption := '➕ Nuevo Grupo de Trabajadores';
    edtCodigo.Text := IntToStr(GetNextCodigo);
    edtNombre.Clear;
    chkActivo.Checked := True;
    lblInfoTrabajadores.Caption := '';
    if edtNombre.CanFocus then
      edtNombre.SetFocus;
  end;
end;

function TfrmTrabajadoresGruposEditor.GetNextCodigo: Integer;
var
  LQry: TFDQuery;
begin
  Result := 1;
  LQry := TFDQuery.Create(nil);
  try
    LQry.Connection := dmgMain.dbConn;
    LQry.SQL.Text := 'SELECT COALESCE(MAX(codigo), 0) + 1 AS next_cod FROM ge_trabajadores_grupos';
    LQry.Open;
    if not LQry.IsEmpty then
      Result := LQry.FieldByName('next_cod').AsInteger;
  finally
    LQry.Free;
  end;
end;

function TfrmTrabajadoresGruposEditor.ExisteCodigo(const ACodigo, AIdExcluir: Integer): Boolean;
var
  LQry: TFDQuery;
begin
  LQry := TFDQuery.Create(nil);
  try
    LQry.Connection := dmgMain.dbConn;
    LQry.SQL.Text := 'SELECT id FROM ge_trabajadores_grupos WHERE codigo = :cod AND id <> :id LIMIT 1';
    LQry.ParamByName('cod').AsInteger := ACodigo;
    LQry.ParamByName('id').AsInteger := AIdExcluir;
    LQry.Open;
    Result := not LQry.IsEmpty;
  finally
    LQry.Free;
  end;
end;

procedure TfrmTrabajadoresGruposEditor.LoadData;
var
  LQry: TFDQuery;
  LCount: Integer;
begin
  if FGrupoId <= 0 then Exit;

  LQry := TFDQuery.Create(nil);
  try
    LQry.Connection := dmgMain.dbConn;
    LQry.SQL.Text :=
      'SELECT g.id, g.codigo, g.nombre, g.activo, ' +
      '  (SELECT COUNT(*) FROM ge_trabajadores_empresas te WHERE te.id_grupo = g.id AND te.activo = 1) AS num_activos ' +
      'FROM ge_trabajadores_grupos g WHERE g.id = :id';
    LQry.ParamByName('id').AsInteger := FGrupoId;
    LQry.Open;

    if not LQry.IsEmpty then
    begin
      edtCodigo.Text := LQry.FieldByName('codigo').AsString;
      edtNombre.Text := LQry.FieldByName('nombre').AsString;
      chkActivo.Checked := (LQry.FieldByName('activo').AsInteger = 1);

      LCount := LQry.FieldByName('num_activos').AsInteger;
      if LCount = 1 then
        lblInfoTrabajadores.Caption := 'ℹ️ Este grupo tiene 1 trabajador asignado en activo.'
      else if LCount > 1 then
        lblInfoTrabajadores.Caption := Format('ℹ️ Este grupo tiene %d trabajadores asignados en activo.', [LCount])
      else
        lblInfoTrabajadores.Caption := 'ℹ️ No hay trabajadores asignados a este grupo actualmente.';
    end;
  finally
    LQry.Free;
  end;

  if edtNombre.CanFocus then
    edtNombre.SetFocus;
end;

procedure TfrmTrabajadoresGruposEditor.btnGuardarClick(Sender: TObject);
var
  LQry: TFDQuery;
  LCodigo: Integer;
  LNombre: string;
  LActivo: Integer;
begin
  LNombre := Trim(edtNombre.Text);
  if LNombre = '' then
  begin
    ShowMessage('Debe indicar un nombre para el grupo de trabajadores.');
    if edtNombre.CanFocus then
      edtNombre.SetFocus;
    Exit;
  end;

  LCodigo := StrToIntDef(Trim(edtCodigo.Text), 0);
  if LCodigo <= 0 then
  begin
    ShowMessage('El código del grupo debe ser un número entero mayor que cero.');
    if edtCodigo.CanFocus then
      edtCodigo.SetFocus;
    Exit;
  end;

  if ExisteCodigo(LCodigo, FGrupoId) then
  begin
    ShowMessage(Format('Ya existe otro grupo de trabajadores con el código %d. Por favor, asigne otro distinto.', [LCodigo]));
    if edtCodigo.CanFocus then
      edtCodigo.SetFocus;
    Exit;
  end;

  if chkActivo.Checked then
    LActivo := 1
  else
    LActivo := 0;

  LQry := TFDQuery.Create(nil);
  try
    try
      LQry.Connection := dmgMain.dbConn;

      if FGrupoId <= 0 then
      begin
        LQry.SQL.Text :=
          'INSERT INTO ge_trabajadores_grupos (codigo, nombre, activo) ' +
          'VALUES (:cod, :nom, :act)';
        LQry.ParamByName('cod').AsInteger := LCodigo;
        LQry.ParamByName('nom').AsString := LNombre;
        LQry.ParamByName('act').AsInteger := LActivo;
        LQry.ExecSQL;

        LQry.Close;
        LQry.SQL.Text := 'SELECT LAST_INSERT_ID() AS new_id';
        LQry.Open;
        if not LQry.IsEmpty then
          FGrupoId := LQry.FieldByName('new_id').AsInteger;
      end
      else
      begin
        LQry.SQL.Text :=
          'UPDATE ge_trabajadores_grupos ' +
          'SET codigo = :cod, nombre = :nom, activo = :act ' +
          'WHERE id = :id';
        LQry.ParamByName('cod').AsInteger := LCodigo;
        LQry.ParamByName('nom').AsString := LNombre;
        LQry.ParamByName('act').AsInteger := LActivo;
        LQry.ParamByName('id').AsInteger := FGrupoId;
        LQry.ExecSQL;
      end;

      ModalResult := mrOk;
    except
      on E: Exception do
        TDbErrorHandler.HandleException(E, 'Error al guardar el grupo de trabajadores');
    end;
  finally
    LQry.Free;
  end;
end;

procedure TfrmTrabajadoresGruposEditor.btnCancelarClick(Sender: TObject);
begin
  ModalResult := mrCancel;
  Close;
end;

end.
