unit frm_TiendasEditor;

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, System.UITypes, uAppTheme;

type
  TfrmTiendasEditor = class(TForm)
    pnlTop: TPanel;
    lblTitulo: TLabel;
    lblSubtitulo: TLabel;
    pnlBody: TPanel;
    lblEmpresa: TLabel;
    cbEmpresa: TComboBox;
    lblCodigo: TLabel;
    edtCodigo: TEdit;
    lblNombre: TLabel;
    edtNombre: TEdit;
    lblAlmacen: TLabel;
    cbAlmacen: TComboBox;
    btnCrearAlmacenAuto: TButton;
    lblDireccion: TLabel;
    edtDireccion: TEdit;
    lblPoblacion: TLabel;
    edtPoblacion: TEdit;
    lblCp: TLabel;
    edtCp: TEdit;
    lblProvincia: TLabel;
    edtProvincia: TEdit;
    lblTelefono: TLabel;
    edtTelefono: TEdit;
    lblEmail: TLabel;
    edtEmail: TEdit;
    chkActivo: TCheckBox;
    pnlBottom: TPanel;
    btnGuardar: TBitBtn;
    btnCancelar: TBitBtn;

    procedure FormCreate(Sender: TObject);
    procedure FormShow(Sender: TObject);
    procedure cbEmpresaChange(Sender: TObject);
    procedure btnCrearAlmacenAutoClick(Sender: TObject);
    procedure btnGuardarClick(Sender: TObject);

  private
    FTiendaId: Integer;
    procedure CargarEmpresas;
    procedure CargarAlmacenes(AEmpresaId: Integer);
    procedure CargarDatos;
    function GetSelectedEmpresaId: Integer;
    function GetSelectedAlmacenId: Integer;
  public
    property TiendaId: Integer read FTiendaId write FTiendaId;
  end;

var
  frmTiendasEditor: TfrmTiendasEditor;

implementation

uses
  dmg_Main, uDbErrorHandler;

{$R *.dfm}

procedure TfrmTiendasEditor.FormCreate(Sender: TObject);
begin
  FTiendaId := 0;
  // Aislamiento de tags
  cbEmpresa.Tag := 999;
  cbAlmacen.Tag := 999;
  btnCrearAlmacenAuto.Tag := 999;
  btnGuardar.Tag := 999;
  btnCancelar.Tag := 999;
end;

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

  if FTiendaId > 0 then
  begin
    lblTitulo.Caption := '✏️ Modificar Tienda';
    lblSubtitulo.Caption := 'Actualice la información del punto de venta y su almacén asociado';
    CargarDatos;
  end
  else
  begin
    lblTitulo.Caption := '➕ Nueva Tienda';
    lblSubtitulo.Caption := 'Introduzca los datos para el nuevo punto de venta';
    edtCodigo.Text := '';
    edtNombre.Text := '';
    edtDireccion.Text := '';
    edtPoblacion.Text := '';
    edtCp.Text := '';
    edtProvincia.Text := '';
    edtTelefono.Text := '';
    edtEmail.Text := '';
    chkActivo.Checked := True;
    CargarAlmacenes(GetSelectedEmpresaId);
  end;
end;

procedure TfrmTiendasEditor.CargarEmpresas;
var
  LQry: TFDQuery;
  LIdx, LDefIdx: Integer;
  LCurrEmpId: Integer;
begin
  cbEmpresa.Items.Clear;
  LDefIdx := 0;
  LCurrEmpId := StrToIntDef(dmgMain.CurrentCompanyId, 1);

  LQry := TFDQuery.Create(nil);
  try
    LQry.Connection := dmgMain.dbConn;
    LQry.SQL.Text := 'SELECT id, nombre FROM ge_empresas WHERE activo = 1 ORDER BY nombre ASC';
    LQry.Open;
    while not LQry.Eof do
    begin
      LIdx := cbEmpresa.Items.AddObject(
        LQry.FieldByName('nombre').AsString,
        TObject(NativeInt(LQry.FieldByName('id').AsInteger))
      );
      if LQry.FieldByName('id').AsInteger = LCurrEmpId then
        LDefIdx := LIdx;
      LQry.Next;
    end;
  finally
    LQry.Free;
  end;

  if (cbEmpresa.ItemIndex < 0) and (cbEmpresa.Items.Count > 0) then
    cbEmpresa.ItemIndex := LDefIdx;
end;

procedure TfrmTiendasEditor.CargarAlmacenes(AEmpresaId: Integer);
var
  LQry: TFDQuery;
begin
  cbAlmacen.Items.Clear;
  cbAlmacen.Items.AddObject('[Sin Almacén Asignado]', TObject(NativeInt(0)));

  LQry := TFDQuery.Create(nil);
  try
    LQry.Connection := dmgMain.dbConn;
    LQry.SQL.Text :=
      'SELECT id, descripcion FROM ge_almacenes ' +
      'WHERE (id_empresa = :emp OR :emp = 0 OR compartido = 1) AND activo = 1 ' +
      'ORDER BY descripcion ASC';
    LQry.ParamByName('emp').AsInteger := AEmpresaId;
    LQry.Open;

    while not LQry.Eof do
    begin
      cbAlmacen.Items.AddObject(
        LQry.FieldByName('descripcion').AsString,
        TObject(NativeInt(LQry.FieldByName('id').AsInteger))
      );
      LQry.Next;
    end;
  finally
    LQry.Free;
  end;

  if cbAlmacen.Items.Count > 0 then
    cbAlmacen.ItemIndex := 0;
end;

function TfrmTiendasEditor.GetSelectedEmpresaId: Integer;
begin
  Result := 0;
  if cbEmpresa.ItemIndex >= 0 then
    Result := NativeInt(cbEmpresa.Items.Objects[cbEmpresa.ItemIndex]);
end;

function TfrmTiendasEditor.GetSelectedAlmacenId: Integer;
begin
  Result := 0;
  if cbAlmacen.ItemIndex >= 0 then
    Result := NativeInt(cbAlmacen.Items.Objects[cbAlmacen.ItemIndex]);
end;

procedure TfrmTiendasEditor.cbEmpresaChange(Sender: TObject);
begin
  CargarAlmacenes(GetSelectedEmpresaId);
end;

procedure TfrmTiendasEditor.btnCrearAlmacenAutoClick(Sender: TObject);
var
  LNombreAlm: string;
  LEmpId, LUserId, LNewId: Integer;
  LQry: TFDQuery;
begin
  if Trim(edtNombre.Text) = '' then
  begin
    ShowMessage('Por favor, indique primero el nombre de la tienda.');
    edtNombre.SetFocus;
    Exit;
  end;

  LEmpId := GetSelectedEmpresaId;
  if LEmpId <= 0 then
  begin
    ShowMessage('Por favor, seleccione una empresa.');
    cbEmpresa.SetFocus;
    Exit;
  end;

  LNombreAlm := 'Almacén Tienda ' + Trim(edtNombre.Text);
  if MessageDlg(Format('¿Desea crear automáticamente el almacén "%s" para esta tienda?', [LNombreAlm]),
    mtConfirmation, [mbYes, mbNo], 0) <> mrYes then
    Exit;

  LUserId := StrToIntDef(dmgMain.CurrentUserId, 1);
  LQry := TFDQuery.Create(nil);
  try
    LQry.Connection := dmgMain.dbConn;
    LQry.SQL.Text :=
      'INSERT INTO ge_almacenes (id_empresa, descripcion, activo, compartido, created_at, id_user_creator) ' +
      'VALUES (:emp, :desc, 1, 0, NOW(), :usr)';
    LQry.ParamByName('emp').AsInteger := LEmpId;
    LQry.ParamByName('desc').AsString := LNombreAlm;
    LQry.ParamByName('usr').AsInteger := LUserId;
    LQry.ExecSQL;

    // Obtener ID generado
    LQry.SQL.Text := 'SELECT LAST_INSERT_ID() AS new_id';
    LQry.Open;
    LNewId := LQry.FieldByName('new_id').AsInteger;

    CargarAlmacenes(LEmpId);

    // Seleccionar el nuevo almacén creado
    for var I := 0 to cbAlmacen.Items.Count - 1 do
    begin
      if NativeInt(cbAlmacen.Items.Objects[I]) = LNewId then
      begin
        cbAlmacen.ItemIndex := I;
        Break;
      end;
    end;

    ShowMessage('Almacén creado y vinculado con éxito.');
  finally
    LQry.Free;
  end;
end;

procedure TfrmTiendasEditor.CargarDatos;
var
  LQry: TFDQuery;
  LEmpId, LAlmId, I: Integer;
begin
  LQry := TFDQuery.Create(nil);
  try
    LQry.Connection := dmgMain.dbConn;
    LQry.SQL.Text := 'SELECT * FROM ge_tiendas WHERE id = :id';
    LQry.ParamByName('id').AsInteger := FTiendaId;
    LQry.Open;

    if not LQry.IsEmpty then
    begin
      LEmpId := LQry.FieldByName('id_empresa').AsInteger;
      LAlmId := LQry.FieldByName('id_almacen').AsInteger;

      // Seleccionar empresa
      for I := 0 to cbEmpresa.Items.Count - 1 do
      begin
        if NativeInt(cbEmpresa.Items.Objects[I]) = LEmpId then
        begin
          cbEmpresa.ItemIndex := I;
          Break;
        end;
      end;

      CargarAlmacenes(LEmpId);

      // Seleccionar almacén
      for I := 0 to cbAlmacen.Items.Count - 1 do
      begin
        if NativeInt(cbAlmacen.Items.Objects[I]) = LAlmId then
        begin
          cbAlmacen.ItemIndex := I;
          Break;
        end;
      end;

      edtCodigo.Text := LQry.FieldByName('codigo').AsString;
      edtNombre.Text := LQry.FieldByName('nombre').AsString;
      edtDireccion.Text := LQry.FieldByName('direccion').AsString;
      edtPoblacion.Text := LQry.FieldByName('poblacion').AsString;
      edtCp.Text := LQry.FieldByName('cp').AsString;
      edtProvincia.Text := LQry.FieldByName('provincia').AsString;
      edtTelefono.Text := LQry.FieldByName('telefono').AsString;
      edtEmail.Text := LQry.FieldByName('email').AsString;
      chkActivo.Checked := (LQry.FieldByName('activo').AsInteger = 1);
    end;
  finally
    LQry.Free;
  end;
end;

procedure TfrmTiendasEditor.btnGuardarClick(Sender: TObject);
var
  LQry: TFDQuery;
  LEmpId, LAlmId, LUserId: Integer;
begin
  if Trim(edtNombre.Text) = '' then
  begin
    ShowMessage('Por favor, introduzca el nombre de la tienda.');
    edtNombre.SetFocus;
    ModalResult := mrNone;
    Exit;
  end;

  LEmpId := GetSelectedEmpresaId;
  if LEmpId <= 0 then
  begin
    ShowMessage('Por favor, seleccione una empresa.');
    cbEmpresa.SetFocus;
    ModalResult := mrNone;
    Exit;
  end;

  LAlmId := GetSelectedAlmacenId;
  LUserId := StrToIntDef(dmgMain.CurrentUserId, 1);

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

    if FTiendaId > 0 then
    begin
      LQry.SQL.Text :=
        'UPDATE ge_tiendas SET ' +
        '  id_empresa = :emp, ' +
        '  codigo = :cod, ' +
        '  nombre = :nom, ' +
        '  direccion = :dir, ' +
        '  poblacion = :pob, ' +
        '  cp = :cp, ' +
        '  provincia = :prov, ' +
        '  telefono = :tel, ' +
        '  email = :email, ' +
        '  id_almacen = :alm, ' +
        '  activo = :act, ' +
        '  updated_at = NOW(), ' +
        '  id_user_update = :usr ' +
        'WHERE id = :id';
      LQry.ParamByName('id').AsInteger := FTiendaId;
    end
    else
    begin
      LQry.SQL.Text :=
        'INSERT INTO ge_tiendas (id_empresa, codigo, nombre, direccion, poblacion, cp, provincia, ' +
        '  telefono, email, id_almacen, activo, created_at, id_user_creator) ' +
        'VALUES (:emp, :cod, :nom, :dir, :pob, :cp, :prov, :tel, :email, :alm, :act, NOW(), :usr)';
    end;

    LQry.ParamByName('emp').AsInteger := LEmpId;
    LQry.ParamByName('cod').AsString := Trim(edtCodigo.Text);
    LQry.ParamByName('nom').AsString := Trim(edtNombre.Text);
    LQry.ParamByName('dir').AsString := Trim(edtDireccion.Text);
    LQry.ParamByName('pob').AsString := Trim(edtPoblacion.Text);
    LQry.ParamByName('cp').AsString := Trim(edtCp.Text);
    LQry.ParamByName('prov').AsString := Trim(edtProvincia.Text);
    LQry.ParamByName('tel').AsString := Trim(edtTelefono.Text);
    LQry.ParamByName('email').AsString := Trim(edtEmail.Text);

    if LAlmId > 0 then
      LQry.ParamByName('alm').AsInteger := LAlmId
    else
      LQry.ParamByName('alm').Clear;

    if chkActivo.Checked then
      LQry.ParamByName('act').AsInteger := 1
    else
      LQry.ParamByName('act').AsInteger := 0;

    LQry.ParamByName('usr').AsInteger := LUserId;
    LQry.ExecSQL;

    ModalResult := mrOk;
  except
    on E: Exception do
    begin
      ModalResult := mrNone;
      TDbErrorHandler.HandleException(E, 'Error al guardar la tienda');
    end;
  end;
  LQry.Free;
end;

end.
