unit frm_EmpresasEditor;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, System.UITypes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls, Vcl.Buttons,
  Vcl.Imaging.jpeg, Vcl.Imaging.pngimage,
  Data.DB, FireDAC.Comp.Client, FireDAC.Stan.Param, uAppTheme, uBaseForm,
  Vcl.ComCtrls, Vcl.Grids, Vcl.DBGrids, Vcl.Menus;

type
  TfrmEmpresasEditor = class(TfrmBase)
    lblNombre: TLabel;
    edtNombre: TEdit;
    lblCIF: TLabel;
    edtCIF: TEdit;
    lblDireccion: TLabel;
    memDireccion: TMemo;
    lblPoblacion: TLabel;
    edtPoblacion: TEdit;
    lblCP: TLabel;
    edtCP: TEdit;
    lblProvincia: TLabel;
    edtProvincia: TEdit;
    lblPais: TLabel;
    edtPais: TEdit;
    lblEmail: TLabel;
    edtEmail: TEdit;
    lblWeb: TLabel;
    edtWeb: TEdit;
    lblTelefono1: TLabel;
    edtTelefono1: TEdit;
    lblTelefono2: TLabel;
    edtTelefono2: TEdit;
    chkActivo: TCheckBox;
    lblEan: TLabel;
    edtEan: TEdit;
    lblIAmodelo: TLabel;
    edtIAmodelo: TEdit;
    lblApiKey: TLabel;
    edtApiKey: TEdit;
    lblId: TLabel;
    edtId: TEdit;
    lblCuenta: TLabel;
    edtCuenta: TEdit;
    grpLogo: TGroupBox;
    imgLogo: TImage;
    btnSubirLogo: TBitBtn;
    btnEliminarLogo: TBitBtn;
    lblLogoInfo: TLabel;
    lblPieDocumentos: TLabel;
    memPieDocumentos: TMemo;

    // Pestaña Acceso Web (WooCommerce)
    tsWeb: TTabSheet;
    pnlWeb: TPanel;
    grpWooCommerce: TGroupBox;
    lblWebServer: TLabel;
    edtWebServer: TEdit;
    lblWebDB: TLabel;
    edtWebDB: TEdit;
    lblWebUser: TLabel;
    edtWebUser: TEdit;
    lblWebPass: TLabel;
    edtWebPass: TEdit;
    btnProbarConexionWeb: TBitBtn;
    lblWebInfo: TLabel;
    
    // Pestaña EDICOM iPaaS
    tsEdicom: TTabSheet;
    pnlEdicom: TPanel;
    grpEdicomConfig: TGroupBox;
    lblEdicomEntorno: TLabel;
    cbEdicomEntorno: TComboBox;
    lblEdicomDatasource: TLabel;
    edtEdicomDatasource: TEdit;
    lblEdicomUrlAuth: TLabel;
    edtEdicomUrlAuth: TEdit;
    lblEdicomUrlApi: TLabel;
    edtEdicomUrlApi: TEdit;
    lblEdicomTipoAuth: TLabel;
    cbEdicomTipoAuth: TComboBox;
    lblEdicomApiKey: TLabel;
    edtEdicomApiKey: TEdit;
    lblEdicomUser: TLabel;
    edtEdicomUser: TEdit;
    lblEdicomPass: TLabel;
    edtEdicomPass: TEdit;
    chkEdicomActivo: TCheckBox;

    // Pestaña SIF / VERI*FACTU
    tsVeriFactu: TTabSheet;
    pnlVeriFactu: TPanel;
    grpSifConfig: TGroupBox;
    lblSifModo: TLabel;
    cbSifModo: TComboBox;
    lblSifNombreSistema: TLabel;
    edtSifNombreSistema: TEdit;
    lblSifVersionSistema: TLabel;
    edtSifVersionSistema: TEdit;
    lblSifNifDesarrollador: TLabel;
    edtSifNifDesarrollador: TEdit;
    lblSifRazonSocialDesarrollador: TLabel;
    edtSifRazonSocialDesarrollador: TEdit;
    lblSifInstalacionId: TLabel;
    edtSifInstalacionId: TEdit;
    lblSifUrlWsTest: TLabel;
    edtSifUrlWsTest: TEdit;
    lblSifUrlWsProd: TLabel;
    edtSifUrlWsProd: TEdit;
    lblSifCertTitular: TLabel;
    edtSifCertTitular: TEdit;
    chkSifActivo: TCheckBox;

    procedure FormShow(Sender: TObject);
    procedure btnSaveClick(Sender: TObject);
    procedure btnSalirClick(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure btnEnviosConfigClick(Sender: TObject);
    procedure mnuTransportistaClick(Sender: TObject);
    procedure btnSubirLogoClick(Sender: TObject);
    procedure btnEliminarLogoClick(Sender: TObject);
    procedure btnProbarConexionWebClick(Sender: TObject);
  protected
    procedure DoShow; override;
    procedure DoAnadir; override;
    procedure DoModificar; override;
    procedure DoPrimero; override;
    procedure DoAnterior; override;
    procedure DoSiguiente; override;
    procedure DoUltimo; override;
  private
    FEmpresaId  : string;
    FParentForm : TForm;
    FMenuTransp : TPopupMenu;   // menú dinámico de transportistas
    FLogoModified: Boolean;
    procedure LoadEdicomData;
    procedure SaveEdicomData;
    procedure LoadSifData;
    procedure SaveSifData;
    procedure LoadLogo;
    procedure SaveLogo;
    procedure BuildTransportistaMenu;
    procedure ClearEditsModified;
  published
    procedure LoadData;
  public
    property EmpresaId: string read FEmpresaId write FEmpresaId;
    property CompanyId: string read FEmpresaId write FEmpresaId;
    property ParentForm: TForm read FParentForm write FParentForm;
  end;

var
  frmEmpresasEditor: TfrmEmpresasEditor;

implementation

uses
  dmg_Main, uDbErrorHandler, frm_Empresas, uValidacionFiscal, frm_EnviosConfig;
{$R *.dfm}

procedure TfrmEmpresasEditor.FormShow(Sender: TObject);
begin
  // Mantener evento vacío para compatibilidad DFM.
  // Toda la lógica de inicialización está en DoShow.
end;

procedure TfrmEmpresasEditor.DoShow;
begin
  inherited DoShow;

  // Tema estándar
  TAppTheme.ApplyToForm(Self);

  // Vincular eventos a la barra superior heredada
  btnGuardar.OnClick := btnSaveClick;
  btnSalir.OnClick := btnSalirClick;

  // Ocultar componentes heredados innecesarios para mantenimiento simple
  pgcDetails.Visible := True;
  TsListado.TabVisible := False;
  pgcDetails.ActivePage := tsDatosEnvio;
  pnlSideToolbar.Visible := False;
  dbgItems.Visible := False;
  pnlFooter.Visible := False;

  if FEmpresaId <> '' then
    LoadData
  else
    DoAnadir;

  ResetChangeTracking;
end;

procedure TfrmEmpresasEditor.FormDestroy(Sender: TObject);
begin
  // No-op
end;

procedure TfrmEmpresasEditor.LoadData;
begin
  if FEmpresaId = '' then Exit;

  dmgMain.qryExec.Close;
  dmgMain.qryExec.SQL.Text := 'SELECT * FROM ge_empresas WHERE id = :id';
  dmgMain.qryExec.ParamByName('id').AsString := FEmpresaId;
  dmgMain.qryExec.Open;
  
  if not dmgMain.qryExec.IsEmpty then
  begin
    edtId.Text := dmgMain.qryExec.FieldByName('id').AsString;
    edtNombre.Text := dmgMain.qryExec.FieldByName('nombre').AsString;
    edtCIF.Text := dmgMain.qryExec.FieldByName('cif_nif').AsString;
    if dmgMain.qryExec.FindField('gln') <> nil then
      edtEan.Text := dmgMain.qryExec.FieldByName('gln').AsString
    else if dmgMain.qryExec.FindField('ean') <> nil then
      edtEan.Text := dmgMain.qryExec.FieldByName('ean').AsString;
    memDireccion.Text := dmgMain.qryExec.FieldByName('direccion').AsString;
    edtPoblacion.Text := dmgMain.qryExec.FieldByName('poblacion').AsString;
    edtCP.Text := dmgMain.qryExec.FieldByName('cp').AsString;
    edtProvincia.Text := dmgMain.qryExec.FieldByName('provincia').AsString;
    edtPais.Text := dmgMain.qryExec.FieldByName('pais').AsString;
    edtEmail.Text := dmgMain.qryExec.FieldByName('email').AsString;
    edtWeb.Text := dmgMain.qryExec.FieldByName('web').AsString;
    edtTelefono1.Text := dmgMain.qryExec.FieldByName('telefono1').AsString;
    edtTelefono2.Text := dmgMain.qryExec.FieldByName('telefono2').AsString;
    chkActivo.Checked := dmgMain.qryExec.FieldByName('activo').AsInteger <> 0;
    edtIAmodelo.Text := dmgMain.qryExec.FieldByName('IAmodelo').AsString;
    edtApiKey.Text := dmgMain.qryExec.FieldByName('apikey').AsString;

    if dmgMain.qryExec.FindField('cuenta') <> nil then
      edtCuenta.Text := dmgMain.qryExec.FieldByName('cuenta').AsString;

    if dmgMain.qryExec.FindField('pie_documentos') <> nil then
      memPieDocumentos.Text := dmgMain.qryExec.FieldByName('pie_documentos').AsString
    else
      memPieDocumentos.Clear;

    if dmgMain.qryExec.FindField('web_server') <> nil then
      edtWebServer.Text := dmgMain.qryExec.FieldByName('web_server').AsString;
    if dmgMain.qryExec.FindField('web_db') <> nil then
      edtWebDB.Text := dmgMain.qryExec.FieldByName('web_db').AsString;
    if dmgMain.qryExec.FindField('web_user') <> nil then
      edtWebUser.Text := dmgMain.qryExec.FieldByName('web_user').AsString;
    if dmgMain.qryExec.FindField('web_password') <> nil then
      edtWebPass.Text := dmgMain.qryExec.FieldByName('web_password').AsString;
  end;
  dmgMain.qryExec.Close;

  LoadEdicomData;
  LoadSifData;
  LoadLogo;
  FLogoModified := False;
  ClearEditsModified;
  ResetChangeTracking;
end;

procedure TfrmEmpresasEditor.LoadEdicomData;
begin
  // Limpiar siempre primero los controles a estado vacío / inactivo
  cbEdicomEntorno.ItemIndex := 0;
  edtEdicomDatasource.Clear;
  edtEdicomUrlAuth.Clear;
  edtEdicomUrlApi.Clear;
  cbEdicomTipoAuth.ItemIndex := 0;
  edtEdicomApiKey.Clear;
  edtEdicomUser.Clear;
  edtEdicomPass.Clear;
  chkEdicomActivo.Checked := False;

  if FEmpresaId = '' then Exit;

  dmgMain.qryExec.Close;
  dmgMain.qryExec.SQL.Text := 'SELECT * FROM ge_edicom_config WHERE id_empresa = :emp LIMIT 1';
  dmgMain.qryExec.ParamByName('emp').AsString := FEmpresaId;
  try
    dmgMain.qryExec.Open;
    if not dmgMain.qryExec.IsEmpty then
    begin
      if dmgMain.qryExec.FieldByName('entorno').AsString = 'PRODUCCION' then
        cbEdicomEntorno.ItemIndex := 1
      else
        cbEdicomEntorno.ItemIndex := 0;

      edtEdicomDatasource.Text := dmgMain.qryExec.FieldByName('datasource_code').AsString;
      edtEdicomUrlAuth.Text := dmgMain.qryExec.FieldByName('url_auth').AsString;
      edtEdicomUrlApi.Text := dmgMain.qryExec.FieldByName('url_api_base').AsString;

      if dmgMain.qryExec.FieldByName('tipo_autenticacion').AsString = 'USER_PASS' then
        cbEdicomTipoAuth.ItemIndex := 1
      else
        cbEdicomTipoAuth.ItemIndex := 0;

      edtEdicomApiKey.Text := dmgMain.qryExec.FieldByName('api_key').AsString;
      edtEdicomUser.Text := dmgMain.qryExec.FieldByName('usuario').AsString;
      edtEdicomPass.Text := dmgMain.qryExec.FieldByName('password').AsString;
      chkEdicomActivo.Checked := dmgMain.qryExec.FieldByName('activo').AsInteger <> 0;
    end;
  except
    // Si la tabla no existe aún en BD o falla la consulta, queda inactivo y vacío
  end;
  dmgMain.qryExec.Close;
end;

procedure TfrmEmpresasEditor.SaveEdicomData;
var
  LEntorno, LTipoAuth, LGLN, LDatasource, LApiKey, LUser: string;
  LHasData: Boolean;
begin
  if FEmpresaId = '' then Exit;

  LDatasource := Trim(edtEdicomDatasource.Text);
  LApiKey := Trim(edtEdicomApiKey.Text);
  LUser := Trim(edtEdicomUser.Text);
  LHasData := chkEdicomActivo.Checked or (LDatasource <> '') or (LApiKey <> '') or (LUser <> '');

  if not LHasData then
  begin
    // Si no está activo y todos los campos están vacíos, desactivar si existiera registro previo
    try
      dmgMain.qryExec.Close;
      dmgMain.qryExec.SQL.Text := 'UPDATE ge_edicom_config SET activo = 0 WHERE id_empresa = :emp';
      dmgMain.qryExec.ParamByName('emp').AsString := FEmpresaId;
      dmgMain.qryExec.ExecSQL;
    except
    end;
    Exit;
  end;

  if cbEdicomEntorno.ItemIndex = 1 then LEntorno := 'PRODUCCION' else LEntorno := 'PREPRODUCCION';
  if cbEdicomTipoAuth.ItemIndex = 1 then LTipoAuth := 'USER_PASS' else LTipoAuth := 'API_KEY';
  LGLN := Trim(edtEan.Text);

  // Si las URLs están vacías al configurar EDICOM, asignar las URLs estándar de Edicom
  if Trim(edtEdicomUrlAuth.Text) = '' then
    edtEdicomUrlAuth.Text := 'https://ipaasgw.edicomgroup.com/auth';
  if Trim(edtEdicomUrlApi.Text) = '' then
    edtEdicomUrlApi.Text := 'https://ipaasgw.edicomgroup.com/api/v1';

  try
    dmgMain.qryExec.Close;
    dmgMain.qryExec.SQL.Text :=
      'INSERT INTO ge_edicom_config ' +
      '  (id_empresa, entorno, datasource_code, url_auth, url_api_base, tipo_autenticacion, api_key, usuario, password, gln_empresa, activo, id_user_creator, id_user_update) ' +
      'VALUES ' +
      '  (:emp, :entorno, :ds, :uauth, :uapi, :tauth, :apikey, :user, :pass, :gln, :act, :ucreator, :uupdate) ' +
      'ON DUPLICATE KEY UPDATE ' +
      '  entorno = VALUES(entorno), ' +
      '  datasource_code = VALUES(datasource_code), ' +
      '  url_auth = VALUES(url_auth), ' +
      '  url_api_base = VALUES(url_api_base), ' +
      '  tipo_autenticacion = VALUES(tipo_autenticacion), ' +
      '  api_key = VALUES(api_key), ' +
      '  usuario = VALUES(usuario), ' +
      '  password = VALUES(password), ' +
      '  gln_empresa = VALUES(gln_empresa), ' +
      '  activo = VALUES(activo), ' +
      '  id_user_update = VALUES(id_user_update), ' +
      '  updated_at = CURRENT_TIMESTAMP';

    dmgMain.qryExec.ParamByName('emp').AsString := FEmpresaId;
    dmgMain.qryExec.ParamByName('entorno').AsString := LEntorno;
    dmgMain.qryExec.ParamByName('ds').AsString := LDatasource;
    dmgMain.qryExec.ParamByName('uauth').AsString := Trim(edtEdicomUrlAuth.Text);
    dmgMain.qryExec.ParamByName('uapi').AsString := Trim(edtEdicomUrlApi.Text);
    dmgMain.qryExec.ParamByName('tauth').AsString := LTipoAuth;
    dmgMain.qryExec.ParamByName('apikey').AsString := LApiKey;
    dmgMain.qryExec.ParamByName('user').AsString := LUser;
    dmgMain.qryExec.ParamByName('pass').AsString := Trim(edtEdicomPass.Text);
    dmgMain.qryExec.ParamByName('gln').AsString := LGLN;
    dmgMain.qryExec.ParamByName('act').AsBoolean := chkEdicomActivo.Checked;
    dmgMain.qryExec.ParamByName('ucreator').AsString := dmgMain.CurrentUserId;
    dmgMain.qryExec.ParamByName('uupdate').AsString := dmgMain.CurrentUserId;

    dmgMain.qryExec.ExecSQL;
  except
    // Silencioso si la tabla ge_edicom_config no está creada aún en la base de datos
  end;
end;

procedure TfrmEmpresasEditor.LoadSifData;
var
  LModoStr: string;
begin
  if FEmpresaId = '' then Exit;

  dmgMain.qryExec.Close;
  dmgMain.qryExec.SQL.Text := 'SELECT * FROM ge_sif_config WHERE empresa_id = :emp LIMIT 1';
  dmgMain.qryExec.ParamByName('emp').AsString := FEmpresaId;
  try
    dmgMain.qryExec.Open;
    if not dmgMain.qryExec.IsEmpty then
    begin
      LModoStr := UpperCase(dmgMain.qryExec.FieldByName('modo_trabajo').AsString);
      if LModoStr = 'VERIFACTU_PROD' then
        cbSifModo.ItemIndex := 1
      else if LModoStr = 'NO_VERIFACTU' then
        cbSifModo.ItemIndex := 2
      else
        cbSifModo.ItemIndex := 0; // VERIFACTU_TEST

      edtSifNombreSistema.Text := dmgMain.qryExec.FieldByName('nombre_sistema').AsString;
      edtSifVersionSistema.Text := dmgMain.qryExec.FieldByName('version_sistema').AsString;
      edtSifNifDesarrollador.Text := dmgMain.qryExec.FieldByName('nif_desarrollador').AsString;
      edtSifRazonSocialDesarrollador.Text := dmgMain.qryExec.FieldByName('razon_social_desarrollador').AsString;
      edtSifInstalacionId.Text := dmgMain.qryExec.FieldByName('instalacion_id').AsString;
      edtSifUrlWsTest.Text := dmgMain.qryExec.FieldByName('url_ws_test').AsString;
      edtSifUrlWsProd.Text := dmgMain.qryExec.FieldByName('url_ws_prod').AsString;
      edtSifCertTitular.Text := dmgMain.qryExec.FieldByName('cert_nombre_titular').AsString;
      chkSifActivo.Checked := dmgMain.qryExec.FieldByName('activo').AsInteger <> 0;
    end
    else
    begin
      cbSifModo.ItemIndex := 0;
      edtSifNombreSistema.Text := 'GESTION--RAUL ASENCIO';
      edtSifVersionSistema.Text := '1.0.0';
      edtSifNifDesarrollador.Text := 'B12345678';
      edtSifRazonSocialDesarrollador.Text := 'SISTEMAS AGRIGEST S.L.';
      edtSifInstalacionId.Text := '01';
      edtSifUrlWsTest.Text := 'https://prewww1.aeat.es/wlpl/TIBA-JDIT/ws/SuministroLRFacturasEmitidas';
      edtSifUrlWsProd.Text := 'https://www1.agenciatributaria.gob.es/wlpl/TIBA-JDIT/ws/SuministroLRFacturasEmitidas';
      edtSifCertTitular.Clear;
      chkSifActivo.Checked := True;
    end;
  except
    // Si la tabla no existe aún en BD
    cbSifModo.ItemIndex := 0;
    edtSifNombreSistema.Text := 'GESTION--RAUL ASENCIO';
    edtSifVersionSistema.Text := '1.0.0';
    edtSifNifDesarrollador.Text := 'B12345678';
    edtSifRazonSocialDesarrollador.Text := 'SISTEMAS AGRIGEST S.L.';
    edtSifInstalacionId.Text := '01';
    edtSifUrlWsTest.Text := 'https://prewww1.aeat.es/wlpl/TIBA-JDIT/ws/SuministroLRFacturasEmitidas';
    edtSifUrlWsProd.Text := 'https://www1.agenciatributaria.gob.es/wlpl/TIBA-JDIT/ws/SuministroLRFacturasEmitidas';
    edtSifCertTitular.Clear;
    chkSifActivo.Checked := True;
  end;
  dmgMain.qryExec.Close;
end;

procedure TfrmEmpresasEditor.SaveSifData;
var
  LModoStr: string;
begin
  if FEmpresaId = '' then Exit;

  case cbSifModo.ItemIndex of
    1: LModoStr := 'VERIFACTU_PROD';
    2: LModoStr := 'NO_VERIFACTU';
  else
    LModoStr := 'VERIFACTU_TEST';
  end;

  try
    dmgMain.qryExec.Close;
    dmgMain.qryExec.SQL.Text :=
      'INSERT INTO ge_sif_config (' +
      '  empresa_id, modo_trabajo, nombre_sistema, version_sistema, ' +
      '  nif_desarrollador, razon_social_desarrollador, instalacion_id, ' +
      '  url_ws_test, url_ws_prod, cert_nombre_titular, activo, ' +
      '  id_user_creator, id_user_update' +
      ') VALUES (' +
      '  :emp, :modo, :nom, :ver, ' +
      '  :nif, :razon, :inst, ' +
      '  :wstest, :wsprod, :cert, :act, ' +
      '  :ucreator, :uupdate' +
      ') ON DUPLICATE KEY UPDATE ' +
      '  modo_trabajo = VALUES(modo_trabajo), ' +
      '  nombre_sistema = VALUES(nombre_sistema), ' +
      '  version_sistema = VALUES(version_sistema), ' +
      '  nif_desarrollador = VALUES(nif_desarrollador), ' +
      '  razon_social_desarrollador = VALUES(razon_social_desarrollador), ' +
      '  instalacion_id = VALUES(instalacion_id), ' +
      '  url_ws_test = VALUES(url_ws_test), ' +
      '  url_ws_prod = VALUES(url_ws_prod), ' +
      '  cert_nombre_titular = VALUES(cert_nombre_titular), ' +
      '  activo = VALUES(activo), ' +
      '  id_user_update = VALUES(id_user_update), ' +
      '  updated_at = CURRENT_TIMESTAMP';

    dmgMain.qryExec.ParamByName('emp').AsInteger := StrToIntDef(FEmpresaId, 0);
    dmgMain.qryExec.ParamByName('modo').AsString := LModoStr;
    dmgMain.qryExec.ParamByName('nom').DataType := ftWideString;
    dmgMain.qryExec.ParamByName('nom').AsWideString := Trim(edtSifNombreSistema.Text);
    dmgMain.qryExec.ParamByName('ver').AsString := Trim(edtSifVersionSistema.Text);
    dmgMain.qryExec.ParamByName('nif').AsString := Trim(edtSifNifDesarrollador.Text);
    dmgMain.qryExec.ParamByName('razon').DataType := ftWideString;
    dmgMain.qryExec.ParamByName('razon').AsWideString := Trim(edtSifRazonSocialDesarrollador.Text);
    dmgMain.qryExec.ParamByName('inst').AsString := Trim(edtSifInstalacionId.Text);
    dmgMain.qryExec.ParamByName('wstest').AsString := Trim(edtSifUrlWsTest.Text);
    dmgMain.qryExec.ParamByName('wsprod').AsString := Trim(edtSifUrlWsProd.Text);
    dmgMain.qryExec.ParamByName('cert').DataType := ftWideString;
    dmgMain.qryExec.ParamByName('cert').AsWideString := Trim(edtSifCertTitular.Text);
    dmgMain.qryExec.ParamByName('act').AsBoolean := chkSifActivo.Checked;
    dmgMain.qryExec.ParamByName('ucreator').AsString := dmgMain.CurrentUserId;
    dmgMain.qryExec.ParamByName('uupdate').AsString := dmgMain.CurrentUserId;

    dmgMain.qryExec.ExecSQL;
  except
    // Silencioso si la tabla ge_sif_config no está creada aún en la base de datos
  end;
end;

procedure TfrmEmpresasEditor.ClearEditsModified;
var
  I: Integer;
begin
  for I := 0 to ComponentCount - 1 do
  begin
    if Components[I] is TCustomEdit then
      TCustomEdit(Components[I]).Modified := False;
  end;
end;

procedure TfrmEmpresasEditor.DoAnadir;
begin
  FEmpresaId := '';
  edtId.Clear;
  edtNombre.Clear;
  edtCIF.Clear;
  edtEan.Clear;
  memDireccion.Clear;
  edtPoblacion.Clear;
  edtCP.Clear;
  edtProvincia.Clear;
  edtPais.Clear;
  edtEmail.Clear;
  edtWeb.Clear;
  edtTelefono1.Clear;
  edtTelefono2.Clear;
  edtIAmodelo.Clear;
  edtApiKey.Clear;
  edtWebServer.Clear;
  edtWebDB.Clear;
  edtWebUser.Clear;
  edtWebPass.Clear;
  edtCuenta.Clear;
  memPieDocumentos.Clear;
  imgLogo.Picture := nil;
  FLogoModified := False;
  chkActivo.Checked := True;

  LoadEdicomData;

  if Assigned(cbSifModo) then cbSifModo.ItemIndex := 0;
  if Assigned(edtSifNombreSistema) then edtSifNombreSistema.Text := 'GESTION--RAUL ASENCIO';
  if Assigned(edtSifVersionSistema) then edtSifVersionSistema.Text := '1.0.0';
  if Assigned(edtSifNifDesarrollador) then edtSifNifDesarrollador.Text := 'B12345678';
  if Assigned(edtSifRazonSocialDesarrollador) then edtSifRazonSocialDesarrollador.Text := 'SISTEMAS AGRIGEST S.L.';
  if Assigned(edtSifInstalacionId) then edtSifInstalacionId.Text := '01';
  if Assigned(edtSifUrlWsTest) then edtSifUrlWsTest.Text := 'https://prewww1.aeat.es/wlpl/TIBA-JDIT/ws/SuministroLRFacturasEmitidas';
  if Assigned(edtSifUrlWsProd) then edtSifUrlWsProd.Text := 'https://www1.agenciatributaria.gob.es/wlpl/TIBA-JDIT/ws/SuministroLRFacturasEmitidas';
  if Assigned(edtSifCertTitular) then edtSifCertTitular.Clear;
  if Assigned(chkSifActivo) then chkSifActivo.Checked := True;

  ClearEditsModified;
  edtNombre.SetFocus;
end;

procedure TfrmEmpresasEditor.DoModificar;
begin
  edtNombre.SetFocus;
end;

procedure TfrmEmpresasEditor.DoPrimero;
var
  LParent: TfrmEmpresas;
begin
  LParent := nil;
  if Assigned(FParentForm) and (FParentForm is TfrmEmpresas) then
    LParent := TfrmEmpresas(FParentForm)
  else if Assigned(frmEmpresas) then
    LParent := frmEmpresas;

  if Assigned(LParent) and Assigned(LParent.QryMain) and not LParent.QryMain.IsEmpty then
  begin
    LParent.QryMain.First;
    FEmpresaId := LParent.QryMain.FieldByName('id').AsString;
    LoadData;
  end;
end;

procedure TfrmEmpresasEditor.DoAnterior;
var
  LParent: TfrmEmpresas;
begin
  LParent := nil;
  if Assigned(FParentForm) and (FParentForm is TfrmEmpresas) then
    LParent := TfrmEmpresas(FParentForm)
  else if Assigned(frmEmpresas) then
    LParent := frmEmpresas;

  if Assigned(LParent) and Assigned(LParent.QryMain) and not LParent.QryMain.IsEmpty then
  begin
    LParent.QryMain.Prior;
    FEmpresaId := LParent.QryMain.FieldByName('id').AsString;
    LoadData;
  end;
end;

procedure TfrmEmpresasEditor.DoSiguiente;
var
  LParent: TfrmEmpresas;
begin
  LParent := nil;
  if Assigned(FParentForm) and (FParentForm is TfrmEmpresas) then
    LParent := TfrmEmpresas(FParentForm)
  else if Assigned(frmEmpresas) then
    LParent := frmEmpresas;

  if Assigned(LParent) and Assigned(LParent.QryMain) and not LParent.QryMain.IsEmpty then
  begin
    LParent.QryMain.Next;
    FEmpresaId := LParent.QryMain.FieldByName('id').AsString;
    LoadData;
  end;
end;

procedure TfrmEmpresasEditor.DoUltimo;
var
  LParent: TfrmEmpresas;
begin
  LParent := nil;
  if Assigned(FParentForm) and (FParentForm is TfrmEmpresas) then
    LParent := TfrmEmpresas(FParentForm)
  else if Assigned(frmEmpresas) then
    LParent := frmEmpresas;

  if Assigned(LParent) and Assigned(LParent.QryMain) and not LParent.QryMain.IsEmpty then
  begin
    LParent.QryMain.Last;
    FEmpresaId := LParent.QryMain.FieldByName('id').AsString;
    LoadData;
  end;
end;

procedure TfrmEmpresasEditor.btnSalirClick(Sender: TObject);
begin
  Close;
end;

procedure TfrmEmpresasEditor.btnSaveClick(Sender: TObject);
var
  LIsNew: Boolean;
  LTipoDoc: TTipoDocumento;
  LCif: string;
begin
  if Trim(edtNombre.Text) = '' then
  begin
    ShowMessage('Debe introducir el nombre de la empresa.');
    edtNombre.SetFocus;
    Exit;
  end;

  // Validación de CIF/NIF (no bloqueante: avisa pero permite guardar)
  LCif := Trim(edtCIF.Text);
  if LCif <> '' then
  begin
    if not TValidacionFiscal.ValidarDocumento(LCif, LTipoDoc) then
    begin
      if MessageDlg(
        'El CIF/NIF "' + LCif + '" no supera la validación del dígito de control.' + sLineBreak +
        '¿Desea guardarlo igualmente?',
        mtWarning, [mbYes, mbNo], 0) = mrNo then
      begin
        edtCIF.SetFocus;
        Exit;
      end;
    end;
  end;

  LIsNew := (FEmpresaId = '');
  try
    dmgMain.qryExec.Close;
    if LIsNew then
    begin
      dmgMain.qryExec.SQL.Text := 
        'INSERT INTO ge_empresas (nombre, cif_nif, gln, direccion, poblacion, cp, provincia, pais, email, web, telefono1, telefono2, activo, IAmodelo, apikey, id_user_creator, id_user_update) ' +
        'VALUES (:nom, :cif, :ean, :dir, :pob, :cp, :prov, :pais, :email, :web, :tel1, :tel2, :act, :iamodel, :apikey, :user, :user)';
    end
    else
    begin
      dmgMain.qryExec.SQL.Text := 
        'UPDATE ge_empresas SET nombre = :nom, cif_nif = :cif, gln = :ean, direccion = :dir, ' +
        'poblacion = :pob, cp = :cp, provincia = :prov, pais = :pais, email = :email, web = :web, telefono1 = :tel1, telefono2 = :tel2, ' +
        'activo = :act, IAmodelo = :iamodel, apikey = :apikey, ' +
        'id_user_update = :user, updated_at = CURRENT_TIMESTAMP ' +
        'WHERE id = :id';
      dmgMain.qryExec.ParamByName('id').AsString := FEmpresaId;
    end;
    dmgMain.qryExec.ParamByName('nom').AsString := Trim(edtNombre.Text);
    dmgMain.qryExec.ParamByName('cif').AsString := Trim(edtCIF.Text);
    dmgMain.qryExec.ParamByName('ean').AsString := Trim(edtEan.Text);
    dmgMain.qryExec.ParamByName('dir').AsString := Trim(memDireccion.Text);
    dmgMain.qryExec.ParamByName('pob').AsString := Trim(edtPoblacion.Text);
    dmgMain.qryExec.ParamByName('cp').AsString := Trim(edtCP.Text);
    dmgMain.qryExec.ParamByName('prov').AsString := Trim(edtProvincia.Text);
    dmgMain.qryExec.ParamByName('pais').AsString := Trim(edtPais.Text);
    dmgMain.qryExec.ParamByName('email').AsString := Trim(edtEmail.Text);
    dmgMain.qryExec.ParamByName('web').AsString := Trim(edtWeb.Text);
    dmgMain.qryExec.ParamByName('tel1').AsString := Trim(edtTelefono1.Text);
    dmgMain.qryExec.ParamByName('tel2').AsString := Trim(edtTelefono2.Text);
    dmgMain.qryExec.ParamByName('act').AsBoolean := chkActivo.Checked;
    dmgMain.qryExec.ParamByName('iamodel').AsString := Trim(edtIAmodelo.Text);
    dmgMain.qryExec.ParamByName('apikey').AsString := Trim(edtApiKey.Text);
    dmgMain.qryExec.ParamByName('user').AsString := dmgMain.CurrentUserId;
    
    dmgMain.qryExec.ExecSQL;

    // Intentar actualizar campos de WooCommerce si existen en la tabla
    try
      dmgMain.qryExec.Close;
      dmgMain.qryExec.SQL.Text := 'UPDATE ge_empresas SET web_server = :wserv, web_db = :wdb, web_user = :wuser, web_password = :wpass WHERE id = :id';
      if LIsNew then
      begin
        dmgMain.qryExec.Close;
        dmgMain.qryExec.SQL.Text := 'SELECT LAST_INSERT_ID() as new_id';
        dmgMain.qryExec.Open;
        FEmpresaId := dmgMain.qryExec.FieldByName('new_id').AsString;
        dmgMain.qryExec.Close;
        dmgMain.qryExec.SQL.Text := 'UPDATE ge_empresas SET web_server = :wserv, web_db = :wdb, web_user = :wuser, web_password = :wpass WHERE id = :id';
      end;
      dmgMain.qryExec.ParamByName('id').AsString := FEmpresaId;
      dmgMain.qryExec.ParamByName('wserv').AsString := Trim(edtWebServer.Text);
      dmgMain.qryExec.ParamByName('wdb').AsString := Trim(edtWebDB.Text);
      dmgMain.qryExec.ParamByName('wuser').AsString := Trim(edtWebUser.Text);
      dmgMain.qryExec.ParamByName('wpass').AsString := Trim(edtWebPass.Text);
      dmgMain.qryExec.ExecSQL;
    except
      // Ignorar si la tabla local ge_empresas no incluye aún las columnas opcionales web_server
    end;

    if LIsNew and (FEmpresaId = '') then
    begin
      dmgMain.qryExec.Close;
      dmgMain.qryExec.SQL.Text := 'SELECT LAST_INSERT_ID() as new_id';
      dmgMain.qryExec.Open;
      FEmpresaId := dmgMain.qryExec.FieldByName('new_id').AsString;
      dmgMain.qryExec.Close;
    end;

    // Guardar campo cuenta en ge_empresas (si existe la columna)
    try
      dmgMain.qryExec.Close;
      dmgMain.qryExec.SQL.Text := 'UPDATE ge_empresas SET cuenta = :cuenta WHERE id = :id';
      dmgMain.qryExec.ParamByName('id').AsString := FEmpresaId;
      dmgMain.qryExec.ParamByName('cuenta').AsString := Trim(edtCuenta.Text);
      dmgMain.qryExec.ExecSQL;
    except
      // Ignorar si la columna cuenta no existe aún
    end;

    // Guardar campo pie_documentos en ge_empresas
    try
      dmgMain.qryExec.Close;
      dmgMain.qryExec.SQL.Text := 'UPDATE ge_empresas SET pie_documentos = :pie WHERE id = :id';
      dmgMain.qryExec.ParamByName('id').AsString := FEmpresaId;
      dmgMain.qryExec.ParamByName('pie').DataType := ftWideMemo;
      dmgMain.qryExec.ParamByName('pie').AsWideMemo := memPieDocumentos.Lines.Text;
      dmgMain.qryExec.ExecSQL;
    except
      // Ignorar si la columna pie_documentos no existe aún
    end;

    SaveLogo;
    SaveEdicomData;
    SaveSifData;
    FLogoModified := False;
    ResetModifiedState;
    ResetChangeTracking;
    if Assigned(FParentForm) and (FParentForm is TfrmEmpresas) then
      TfrmEmpresas(FParentForm).btnRefreshClick(nil);
    ShowMessage('Empresa guardada correctamente.');
  except
    on E: Exception do
    begin
      TDbErrorHandler.HandleException(E, 'Error al guardar la empresa');
    end;
  end;
end;

// ---------------------------------------------------------------------------
// Construye el PopupMenu de transportistas desde ge_envios_transportistas
// ---------------------------------------------------------------------------
procedure TfrmEmpresasEditor.BuildTransportistaMenu;
var
  Qry  : TFDQuery;
  LItem: TMenuItem;
 begin
  if not Assigned(FMenuTransp) then
    FMenuTransp := TPopupMenu.Create(Self);

  FMenuTransp.Items.Clear;

  Qry := TFDQuery.Create(nil);
  try
    Qry.Connection := dmgMain.dbConn;
    Qry.SQL.Text :=
      'SELECT id, nombre FROM ge_envios_transportistas WHERE activo = 1 ORDER BY nombre';
    Qry.Open;
    if Qry.IsEmpty then
    begin
      LItem := TMenuItem.Create(FMenuTransp);
      LItem.Caption := '(Sin transportistas disponibles)';
      LItem.Enabled := False;
      FMenuTransp.Items.Add(LItem);
    end
    else
      while not Qry.Eof do
      begin
        LItem := TMenuItem.Create(FMenuTransp);
        LItem.Caption := Qry.FieldByName('nombre').AsString;
        LItem.Tag     := Qry.FieldByName('id').AsInteger;
        LItem.OnClick := mnuTransportistaClick;
        FMenuTransp.Items.Add(LItem);
        Qry.Next;
      end;
  finally
    Qry.Free;
  end;
end;

// ---------------------------------------------------------------------------
// Clic en el botón Config. Envíos: muestra el menú de transportistas
// ---------------------------------------------------------------------------
procedure TfrmEmpresasEditor.btnEnviosConfigClick(Sender: TObject);
var
  LPt: TPoint;
begin
  if FEmpresaId = '' then
  begin
    ShowMessage('Guarde primero los datos de la empresa antes de configurar envíos.');
    Exit;
  end;

  BuildTransportistaMenu;

  FMenuTransp.Popup(LPt.X, LPt.Y);
end;

// ---------------------------------------------------------------------------
// El usuario elige un transportista del menú
// ---------------------------------------------------------------------------
procedure TfrmEmpresasEditor.mnuTransportistaClick(Sender: TObject);
var
  LTranspId: Integer;
begin
  LTranspId := (Sender as TMenuItem).Tag;

  if not Assigned(frmEnviosConfig) then
    Application.CreateForm(TfrmEnviosConfig, frmEnviosConfig);

  frmEnviosConfig.EmpresaId       := StrToIntDef(FEmpresaId, 0);
  frmEnviosConfig.TransportistaId := LTranspId;
  frmEnviosConfig.ParentForm      := Self;
  frmEnviosConfig.ShowModal;
end;

// ---------------------------------------------------------------------------
// Carga el logo desde el campo BLOB ge_empresas.logo
// ---------------------------------------------------------------------------
procedure TfrmEmpresasEditor.LoadLogo;
var
  Qry: TFDQuery;
  Stream: TMemoryStream;
begin
  imgLogo.Picture := nil;
  if FEmpresaId = '' then Exit;

  Qry := TFDQuery.Create(nil);
  try
    Qry.Connection := dmgMain.dbConn;
    Qry.SQL.Text := 'SELECT logo FROM ge_empresas WHERE id = :id';
    Qry.ParamByName('id').AsString := FEmpresaId;
    try
      Qry.Open;
      if not Qry.IsEmpty and (Qry.FindField('logo') <> nil) and
         not Qry.FieldByName('logo').IsNull then
      begin
        Stream := TMemoryStream.Create;
        try
          TBlobField(Qry.FieldByName('logo')).SaveToStream(Stream);
          Stream.Position := 0;
          if Stream.Size > 0 then
            imgLogo.Picture.LoadFromStream(Stream);
        finally
          Stream.Free;
        end;
      end;
    except
      // Si la columna logo no existe aún
    end;
  finally
    Qry.Free;
  end;
end;

// ---------------------------------------------------------------------------
// Guarda el logo en el campo BLOB ge_empresas.logo
// ---------------------------------------------------------------------------
procedure TfrmEmpresasEditor.SaveLogo;
var
  Stream: TMemoryStream;
begin
  if (FEmpresaId = '') or not FLogoModified then Exit;

  try
    dmgMain.qryExec.Close;
    dmgMain.qryExec.SQL.Text := 'UPDATE ge_empresas SET logo = :logo WHERE id = :id';
    dmgMain.qryExec.ParamByName('id').AsString := FEmpresaId;

    if (imgLogo.Picture.Graphic = nil) or imgLogo.Picture.Graphic.Empty then
    begin
      dmgMain.qryExec.ParamByName('logo').DataType := ftBlob;
      dmgMain.qryExec.ParamByName('logo').Clear;
    end
    else
    begin
      Stream := TMemoryStream.Create;
      try
        imgLogo.Picture.Graphic.SaveToStream(Stream);
        Stream.Position := 0;
        dmgMain.qryExec.ParamByName('logo').LoadFromStream(Stream, ftBlob);
      finally
        Stream.Free;
      end;
    end;

    dmgMain.qryExec.ExecSQL;
  except
    // Ignorar si la columna logo no existe aún en ge_empresas
  end;
end;

// ---------------------------------------------------------------------------
// Botón "Subir Logo...": abre un diálogo para seleccionar imagen
// ---------------------------------------------------------------------------
procedure TfrmEmpresasEditor.btnSubirLogoClick(Sender: TObject);
var
  OpenDlg: TOpenDialog;
begin
  OpenDlg := TOpenDialog.Create(nil);
  try
    OpenDlg.Title := 'Seleccionar logo de empresa';
    OpenDlg.Filter := 'Imágenes (*.png;*.jpg;*.jpeg;*.bmp)|*.png;*.jpg;*.jpeg;*.bmp';
    if OpenDlg.Execute then
    begin
      imgLogo.Picture.LoadFromFile(OpenDlg.FileName);
      FLogoModified := True;
    end;
  finally
    OpenDlg.Free;
  end;
end;

// ---------------------------------------------------------------------------
// Botón "Eliminar Logo": limpia la imagen y marca como modificado
// ---------------------------------------------------------------------------
procedure TfrmEmpresasEditor.btnEliminarLogoClick(Sender: TObject);
begin
  if (imgLogo.Picture.Graphic <> nil) and not imgLogo.Picture.Graphic.Empty then
  begin
    if MessageDlg('¿Está seguro de que desea eliminar el logo de la empresa?',
      mtConfirmation, [mbYes, mbNo], 0) = mrYes then
    begin
      imgLogo.Picture := nil;
      FLogoModified := True;
    end;
  end;
end;

// ---------------------------------------------------------------------------
// Botón "Probar Conexión Web": prueba la conexión directa MySQL con WooCommerce
// ---------------------------------------------------------------------------
procedure TfrmEmpresasEditor.btnProbarConexionWebClick(Sender: TObject);
var
  LConn: TFDConnection;
  LServer, LDB, LUser, LPass: string;
begin
  LServer := Trim(edtWebServer.Text);
  LDB := Trim(edtWebDB.Text);
  LUser := Trim(edtWebUser.Text);
  LPass := Trim(edtWebPass.Text);

  if (LServer = '') or (LDB = '') or (LUser = '') then
  begin
    ShowMessage('Debe rellenar los campos Servidor, Base de Datos y Usuario para probar la conexión.');
    Exit;
  end;

  LConn := TFDConnection.Create(nil);
  try
    LConn.DriverName := 'MySQL';
    LConn.Params.Add('Server=' + LServer);
    LConn.Params.Add('Database=' + LDB);
    LConn.Params.Add('User_Name=' + LUser);
    LConn.Params.Add('Password=' + LPass);
    LConn.Params.Add('Port=3306');
    LConn.Params.Add('CharacterSet=utf8mb4');
    LConn.Params.Add('LoginTimeout=5');
    LConn.Connected := True;
    ShowMessage('¡Conexión establecida con éxito con la base de datos web (' + LDB + ')!');
  except
    on E: Exception do
      ShowMessage('Error al conectar con la base de datos web:' + sLineBreak + E.Message);
  end;
  LConn.Free;
end;

end.
