unit frm_Main;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, System.UITypes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.Menus, Vcl.ComCtrls, Vcl.ExtCtrls,
  Vcl.StdCtrls, Vcl.Themes, Vcl.Styles, Vcl.Buttons, uAppTheme, System.ImageList, Vcl.BaseImageCollection, FireDAC.Phys.MySQL,
  FireDAC.Phys.MySQLDef, Vcl.ImageCollection, Vcl.VirtualImageList, System.Types, Winapi.ShellAPI;

const
  WM_RESET_WORKSPACE = WM_USER + 101;
  WM_CHECK_WEB_ORDERS = WM_USER + 102;

type
  TfrmMain = class(TForm)
    StatusBar1: TStatusBar;
    pnlTop: TPanel;
    pcWorkspace: TPageControl;
    PageControl1: TPageControl;
    TabComercial: TTabSheet;
    TabProduccion: TTabSheet;
    TabLogistica: TTabSheet;
    TabUtilidades: TTabSheet;
    TabEmpresas: TTabSheet;
    pmTabs: TPopupMenu;
    m_CerrarTab: TMenuItem;
    pnlWorkspaceContainer: TPanel;
    btnLotesRibbon: TSpeedButton;
    btnEmpresasRibbon: TSpeedButton;
    btnImportarfactusol: TSpeedButton;
    btnConfigConexion: TSpeedButton;
    TabRecursosHumanos: TTabSheet;
    btnTrabajadoresRibbon: TSpeedButton;
    btnTrabajadoresGruposRibbon: TSpeedButton;
    btnFichajesRibbon: TSpeedButton;
    btnCalendarioLaboralRibbon: TSpeedButton;
    btnTiemposAreasRibbon: TSpeedButton;
    btnCostesManoObraRibbon: TSpeedButton;
    btnTerminalPlantaRibbon: TSpeedButton;
    TabCalidad: TTabSheet;
    btnCalidadDocumentos: TSpeedButton;
    btnCalidadRegistros: TSpeedButton;
    btnCalidadPrerrequisitos: TSpeedButton;
    btnCalidadIncidencias: TSpeedButton;
    btnCalidadVerificacion: TSpeedButton;
    btnCalidadTrazabilidad: TSpeedButton;
    TabInicio: TTabSheet;
    btnSeries: TSpeedButton;
    btnMateriasPrimas: TSpeedButton;
    btnRecetas: TSpeedButton;
    btnUsuarios: TSpeedButton;
    btnTiposIva: TSpeedButton;
    Splitter1: TSplitter;
    btnAlmacenes: TSpeedButton;
    btnObradores: TSpeedButton;
    btnTiendas: TSpeedButton;
    btnMovimientosStock: TSpeedButton;
    btnCalendarioProduccion: TSpeedButton;
    btnCambiarEmpresa: TSpeedButton;
    Panel1: TPanel;
    btnClientes: TSpeedButton;
    btnPedidos: TSpeedButton;
    btnPresupuestos: TSpeedButton;
    btnAlbaranes: TSpeedButton;
    btnFacturas: TSpeedButton;
    btnProforma: TSpeedButton;
    btnEventos: TSpeedButton;
    Panel2: TPanel;
    btnProveedor: TSpeedButton;
    btnPedidosProv: TSpeedButton;
    btnPresupuestosProv: TSpeedButton;
    btnAlbaranProv: TSpeedButton;
    btnFacturasProv: TSpeedButton;
    btnArticulos: TSpeedButton;
    btnFamilias: TSpeedButton;
    btnAlergenos: TSpeedButton;
    btnEventosMaterialesCat: TSpeedButton;
    btnArticulosProv: TSpeedButton;
    btnProvPreciosVariaciones: TSpeedButton;
    btnInventariosRibbon: TSpeedButton;
    btnEntradasMateriasPrimas: TSpeedButton;
    btnIncidencias: TSpeedButton;
    btnFormatosPresentacion: TSpeedButton;
    btnFormatosEnvio: TSpeedButton;
    btnReportTemplates: TSpeedButton;
    btnConfigEnvio: TSpeedButton;
    btnStockEnvasado: TSpeedButton;
    btnInventarioStockEnvasado: TSpeedButton;
    btnEnvios: TSpeedButton;
    btnPrepararPedidos: TSpeedButton;
    btnChatIA: TSpeedButton;
    btnCodigosBarrasCompleto: TSpeedButton;
    btnClientesGrupos: TSpeedButton;
    btnCalidadGruposControl: TSpeedButton;
    btnCalidadHitos: TSpeedButton;
    btnFormasPago: TSpeedButton;
    btnVentasPreciosHistorico: TSpeedButton;
    btnTermometroBLE: TSpeedButton;
    btnCentrosZonas: TSpeedButton;
    btnTipsaConfig: TSpeedButton;
    procedure pcWorkspaceTabClose(Sender: TObject; var CanClose: Boolean);
    procedure m_CerrarTabClick(Sender: TObject);
    procedure FormShow(Sender: TObject);
    procedure btn_LotesClick(Sender: TObject);
    procedure btn_EmpresasClick(Sender: TObject);
    procedure btn_AlbaranesClick(Sender: TObject);
    procedure btn_FacturasClick(Sender: TObject);
    procedure btn_ArticulosClick(Sender: TObject);
    procedure btn_FamiliasClick(Sender: TObject);
    procedure btn_ImportarFactusolClick(Sender: TObject);
    procedure btn_MateriasPrimasClick(Sender: TObject);
    procedure btnAsignarMateriasPrimasClick(Sender: TObject);
    procedure btn_RecetasClick(Sender: TObject);
    procedure btnOrdenesFabricacionClick(Sender: TObject);
    procedure btnMonitorFabricacionClick(Sender: TObject);
    procedure btnCalendarioProduccionClick(Sender: TObject);
    procedure btnConfigConexionClick(Sender: TObject);
    procedure btnEventosMaterialesCatClick(Sender: TObject);
    procedure btnEventosClick(Sender: TObject);
    procedure btnUsuariosClick(Sender: TObject);
    procedure btnAlergenosClick(Sender: TObject);
    procedure btnTiposIvaClick(Sender: TObject);
    procedure btnFormasPagoClick(Sender: TObject);
    procedure btnSeriesClick(Sender: TObject);
    procedure btn_ClientesClick(Sender: TObject);
    procedure btnClientesGruposClick(Sender: TObject);
    procedure btnAlmacenesClick(Sender: TObject);
    procedure btnObradoresClick(Sender: TObject);
    procedure btnProveedorClick(Sender: TObject);
    procedure btnProvAlbaranesClick(Sender: TObject);
    procedure btnProvFacturasClick(Sender: TObject);
    procedure btnProvPresupuestosClick(Sender: TObject);
    procedure btnArticulosProvClick(Sender: TObject);
    procedure btnProvPreciosVariacionesClick(Sender: TObject);
    procedure btnVentasPreciosHistoricoClick(Sender: TObject);
    procedure btnIncidenciasClick(Sender: TObject);
    procedure btnFormatosPresentacionClick(Sender: TObject);
    procedure btnFormatosEnvioClick(Sender: TObject);
    procedure btnTransportistasClick(Sender: TObject);
    procedure btnReportTemplatesClick(Sender: TObject);
    procedure btnConfigEnvioClick(Sender: TObject);
    procedure btnChatIAClick(Sender: TObject);
    procedure btnPresupuestosClick(Sender: TObject);
    procedure btnCambiarEmpresaClick(Sender: TObject);
    procedure pcWorkspaceMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
    procedure btnCerrarTabClick(Sender: TObject);
    procedure btnEntradasClick(Sender: TObject);
    procedure btnStockEnvasadoClick(Sender: TObject);
    procedure btnInventarioStockEnvasadoClick(Sender: TObject);
    procedure btnInventariosClick(Sender: TObject);
    procedure btnPedidosClick(Sender: TObject);
    procedure btnFeatureInDevelopmentClick(Sender: TObject);
    procedure btnEnviosClick(Sender: TObject);
    procedure btnPrepararPedidosClick(Sender: TObject);
    procedure btnTipsaConfigClick(Sender: TObject);
    procedure btnCodigosBarrasCompletoClick(Sender: TObject);
    procedure btnCalidadDocumentosClick(Sender: TObject);
    procedure btnCalidadRegistrosClick(Sender: TObject);
    procedure btnCalidadPrerrequisitosClick(Sender: TObject);
    procedure btnCalidadIncidenciasClick(Sender: TObject);
    procedure btnCalidadVerificacionClick(Sender: TObject);
    procedure btnCalidadTrazabilidadClick(Sender: TObject);
    procedure btnCalidadGruposControlClick(Sender: TObject);
    procedure btnCalidadHitosClick(Sender: TObject);
    procedure btnCalidadPlannerClick(Sender: TObject);
    procedure btnTrabajadoresRibbonClick(Sender: TObject);
    procedure btnTrabajadoresGruposRibbonClick(Sender: TObject);
    procedure btnFichajesRibbonClick(Sender: TObject);
    procedure btnCalendarioLaboralRibbonClick(Sender: TObject);
    procedure btnTiemposAreasRibbonClick(Sender: TObject);
    procedure btnCostesManoObraRibbonClick(Sender: TObject);
    procedure btnTerminalPlantaRibbonClick(Sender: TObject);
    procedure btnTermometroBLEClick(Sender: TObject);
    procedure btnCentrosZonasClick(Sender: TObject);
    procedure btnTiendasClick(Sender: TObject);
    procedure btnMovimientosStockClick(Sender: TObject);

  private
    FUserRole: string;
    procedure ApplyPrivileges;
    procedure pcWorkspaceDrawTab(Control: TCustomTabControl;
      TabIndex: Integer; const Rect: TRect; Active: Boolean);
    function GetCloseButtonRect(ATabIndex: Integer): TRect;
    procedure CloseTabByIndex(AIndex: Integer);
    procedure WMResetWorkspace(var Message: TMessage); message WM_RESET_WORKSPACE;
    procedure WMCheckWebOrders(var Message: TMessage); message WM_CHECK_WEB_ORDERS;
    procedure ComprobarVariacionesPreciosPendientes;
  public
    { Public declarations }
    function OpenFormInTab(AFormClass: TFormClass; const ACaption: string): TForm;
    procedure ResetWorkspace;
    property UserRole: string read FUserRole write FUserRole;
  end;

var
  frmMain: TfrmMain;

implementation

uses
  dmg_Main, frm_Login, uLotesLogic, frm_Lotes, frm_Empresas, frm_Albaranes, frm_Facturas,
  frm_Articulos, frm_Familias, frm_ImportarFactusol, frm_MateriasPrimas, frm_AsignarMateriasPrimas, frm_Recetas,
  frm_OrdenesFabricacion, frm_MonitorFabricacion, frm_CalendarioProduccion, frm_DbConfig,
  frm_Eventos, frm_EventosMaterialesCat, frm_Usuarios, frm_UsuariosEditor, frm_Clientes, frm_ClientesGrupos,
  frm_Alergenos, frm_TiposIva, frm_FormasPago, frm_Almacenes, frm_Obradores, frm_SelectCompany,
  frm_Proveedores, frm_ProveedoresEditor, frm_ProvAlbaranesEditor, frm_ProvFacturasEditor, frm_ProvPresupuestosEditor,
  frm_ProvAlbaranes, frm_ProvFacturas, frm_ProvPresupuestos, frm_Series, frm_ArticulosProveedor, frm_ProvPreciosVariaciones, frm_Incidencias,
  frm_EntradasMateriasPrimas, frm_Inventarios, frm_Presupuestos, frm_Pedidos,
  frm_FormatosPresentacion, frm_FormatosEnvio, frm_ReportTemplates, frm_ConfigEnvio,
  frm_Transportistas, frm_StockEnvasado, frm_InventarioStockEnvasado, frm_EnviosList, frm_ChatIA,
  FireDAC.Comp.Client, FireDAC.Stan.Param, Data.DB, uEnviosWebImporter, uEdicomWsClient, frm_ImportarPedidosWeb, frm_CodigosBarrasCompleto,
  frm_CalidadRegistrosList, frm_CalidadVerificacionDiaria, frm_CalidadTrazabilidadMaestra,
  frm_CalidadPrerrequisitosEditor, frm_CalidadIncidenciasEditor, frm_CalidadIncidenciasList, frm_CalidadDocumentosList, frm_CalidadGrupos,
  frm_CalidadHitos, frm_CalidadHitosEditor,
  frm_CalidadPlannerList, frm_PrepararPedidos, frm_Trabajadores, frm_TrabajadoresFichajes,
  frm_TrabajadoresGrupos, frm_CalendarioLaboral,
  frm_VentasPreciosHistorico, frm_TermometroMonitor, frm_CentrosZonas, frm_TipsaConfig,
  frm_Tiendas, frm_MovimientosInternos;

{$R *.dfm}

procedure TfrmMain.FormShow(Sender: TObject);
var
  I: Integer;
  LBtn: TSpeedButton;
  LIdx: Integer;
begin
  TAppTheme.ApplyToForm(Self);

  // Asegurar que todos los botones del ribbon tengan su ImageIndex sincronizado con ImageName
  for I := 0 to ComponentCount - 1 do
  begin
    if (Components[I] is TSpeedButton) then
    begin
      LBtn := TSpeedButton(Components[I]);
      if (LBtn.Images = nil) and Assigned(dmgMain) then
        LBtn.Images := dmgMain.imgListRibbon;

      if (LBtn.Images is TVirtualImageList) and (LBtn.ImageName <> '') then
      begin
        LIdx := TVirtualImageList(LBtn.Images).GetIndexByName(LBtn.ImageName);
        if LIdx >= 0 then
          LBtn.ImageIndex := LIdx;
      end;
    end;
  end;
  
  // Activar pestaña de inicio
  PageControl1.ActivePage := TabInicio;

  // Configurar tabs del workspace con owner-draw para dibujar botón ✕
  pcWorkspace.TabPosition := tpTop;
  pcWorkspace.OwnerDraw := True;
  pcWorkspace.TabWidth := 180;  // Ancho fijo para que quepa el texto + botón ✕
  pcWorkspace.TabHeight := 26;
  pcWorkspace.OnDrawTab := pcWorkspaceDrawTab;
  pcWorkspace.OnMouseDown := pcWorkspaceMouseDown;  // Conectar clic en ✕

  // Intentar conectar a la DB al arrancar
  try
    dmgMain.Connect;
    StatusBar1.Panels[0].Text := 'Base de Datos: Conectada';
    StatusBar1.Panels[1].Text := 'Rol: ' + FUserRole;
    StatusBar1.Panels[2].Text := 'Empresa: ' + dmgMain.CurrentCompanyName;
    Self.Caption := 'Gestión - ' + dmgMain.CurrentCompanyName;
    ApplyPrivileges;
  except
    on E: Exception do
      StatusBar1.Panels[0].Text := 'Error DB: ' + E.Message;
  end;
  
  // Enviar mensaje para comprobar pedidos web en segundo plano
  PostMessage(Self.Handle, WM_CHECK_WEB_ORDERS, 0, 0);
end;

{ ---------- Owner-Draw: Dibujar cada pestaña con botón ✕ ---------- }

procedure TfrmMain.pcWorkspaceDrawTab(Control: TCustomTabControl;
  TabIndex: Integer; const Rect: TRect; Active: Boolean);
var
  LCanvas: TCanvas;
  LCaption: string;
  LTextRect, LCloseRect: TRect;
begin
  LCanvas := (Control as TPageControl).Canvas;
  LCaption := (Control as TPageControl).Pages[TabIndex].Caption;

  // Fondo de la pestaña
  if Active then
    LCanvas.Brush.Color := clWhite
  else
    LCanvas.Brush.Color := $00F0F0F0;  // gris muy claro

  LCanvas.FillRect(Rect);

  // Dibujar el texto del caption (dejando espacio para el ✕)
  LTextRect := Rect;
  LTextRect.Left := LTextRect.Left + 6;
  LTextRect.Right := LTextRect.Right - 24;
  LCanvas.Font.Name := 'Segoe UI';
  LCanvas.Font.Size := 9;
  if Active then
    LCanvas.Font.Style := [fsBold]
  else
    LCanvas.Font.Style := [];
  LCanvas.Font.Color := clBlack;
  DrawText(LCanvas.Handle, PChar(LCaption), Length(LCaption), LTextRect,
    DT_SINGLELINE or DT_VCENTER or DT_LEFT or DT_END_ELLIPSIS);

  // Dibujar el botón ✕ con líneas cruzadas
  LCloseRect := GetCloseButtonRect(TabIndex);

  // Fondo redondeado rojo
  LCanvas.Brush.Color := $004040CC;  // rojo
  LCanvas.Pen.Color := $004040CC;
  LCanvas.RoundRect(LCloseRect.Left, LCloseRect.Top,
    LCloseRect.Right, LCloseRect.Bottom, 4, 4);

  // Dibujar la X con líneas blancas
  LCanvas.Pen.Color := clWhite;
  LCanvas.Pen.Width := 2;
  LCanvas.MoveTo(LCloseRect.Left + 4, LCloseRect.Top + 4);
  LCanvas.LineTo(LCloseRect.Right - 4, LCloseRect.Bottom - 4);
  LCanvas.MoveTo(LCloseRect.Right - 4, LCloseRect.Top + 4);
  LCanvas.LineTo(LCloseRect.Left + 4, LCloseRect.Bottom - 4);
  LCanvas.Pen.Width := 1;
end;

function TfrmMain.GetCloseButtonRect(ATabIndex: Integer): TRect;
var
  LTabRect: TRect;
  LBtnSize: Integer;
begin
  LTabRect := pcWorkspace.TabRect(ATabIndex);
  LBtnSize := 16;
  Result.Left := LTabRect.Right - LBtnSize - 6;
  Result.Top := LTabRect.Top + ((LTabRect.Bottom - LTabRect.Top - LBtnSize) div 2);
  Result.Right := Result.Left + LBtnSize;
  Result.Bottom := Result.Top + LBtnSize;
end;

{ ---------- Cerrar pestaña por índice ---------- }

procedure TfrmMain.CloseTabByIndex(AIndex: Integer);
var
  LTab: TTabSheet;
  LCanClose: Boolean;
begin
  if (AIndex < 0) or (AIndex >= pcWorkspace.PageCount) then
    Exit;

  LTab := pcWorkspace.Pages[AIndex];
  LCanClose := True;
  pcWorkspaceTabClose(LTab, LCanClose);
  if LCanClose then
    LTab.Free;
end;

procedure TfrmMain.ApplyPrivileges;
var
  LQuery: TFDQuery;
begin
  LQuery := TFDQuery.Create(nil);
  try
    LQuery.Connection := dmgMain.dbConn;
    
    // 1. Si es Administrador Global o tiene Rol ADMIN, mostramos y habilitamos todo
    LQuery.SQL.Text := 'SELECT es_admin_global, rol FROM ge_usuarios WHERE id = :uid';
    LQuery.ParamByName('uid').AsString := dmgMain.CurrentUserId;
    LQuery.Open;
    
    if not LQuery.IsEmpty and
       ((LQuery.FieldByName('es_admin_global').AsInteger <> 0) or
        (LQuery.FieldByName('rol').AsString = 'ADMIN')) then
    begin
      TabInicio.TabVisible := True;
      TabEmpresas.TabVisible := True;
      TabComercial.TabVisible := True;
      TabProduccion.TabVisible := True;
      TabLogistica.TabVisible := True;
      TabRecursosHumanos.TabVisible := True;
      TabCalidad.TabVisible := True;
      TabUtilidades.TabVisible := True;
      Exit;
    end;
    
    LQuery.Close;
    
    // 2. Si no es administrador global, cargamos dinámicamente sus permisos por módulo
    LQuery.SQL.Text := 
      'SELECT m.slug, MAX(p.puede_leer) as puede_leer ' +
      'FROM ge_usuario_empresa_permisos p ' +
      'JOIN ge_modulos m ON p.modulo_id = m.id ' +
      'WHERE p.usuario_id = :uid ' +
      'GROUP BY m.slug';
    LQuery.ParamByName('uid').AsString := dmgMain.CurrentUserId;
    LQuery.Open;
    
    // Ocultar pestañas por defecto (excepto Inicio)
    TabEmpresas.TabVisible := False;
    TabComercial.TabVisible := False;
    TabProduccion.TabVisible := False;
    TabLogistica.TabVisible := False;
    TabRecursosHumanos.TabVisible := False;
    TabCalidad.TabVisible := True;
    TabUtilidades.TabVisible := False;
    
    while not LQuery.Eof do
    begin
      if LQuery.FieldByName('puede_leer').AsInteger <> 0 then
      begin
        if LQuery.FieldByName('slug').AsString = 'empresa' then TabEmpresas.TabVisible := True
        else if LQuery.FieldByName('slug').AsString = 'comercial' then TabComercial.TabVisible := True
        else if LQuery.FieldByName('slug').AsString = 'produccion' then TabProduccion.TabVisible := True
        else if LQuery.FieldByName('slug').AsString = 'logistica' then TabLogistica.TabVisible := True
        else if LQuery.FieldByName('slug').AsString = 'rrhh' then TabRecursosHumanos.TabVisible := True
        else if LQuery.FieldByName('slug').AsString = 'calidad' then TabCalidad.TabVisible := True
        else if LQuery.FieldByName('slug').AsString = 'utilidades' then TabUtilidades.TabVisible := True;
      end;
      LQuery.Next;
    end;
  finally
    LQuery.Free;
  end;
end;

procedure TfrmMain.btn_AlbaranesClick(Sender: TObject);
begin
  OpenFormInTab(TfrmAlbaranes, 'Albaranes');
end;

procedure TfrmMain.btn_FacturasClick(Sender: TObject);
begin
  OpenFormInTab(TfrmFacturas, 'Facturas');
end;

procedure TfrmMain.btn_EmpresasClick(Sender: TObject);
begin
  OpenFormInTab(TfrmEmpresas, 'Empresas');
end;

procedure TfrmMain.btn_LotesClick(Sender: TObject);
begin
  OpenFormInTab(TfrmLotes, 'Trazabilidad y Lotes');
end;

procedure TfrmMain.btn_ArticulosClick(Sender: TObject);
begin
  OpenFormInTab(TfrmArticulos, 'Artículos');
end;

procedure TfrmMain.btn_FamiliasClick(Sender: TObject);
begin
  OpenFormInTab(TfrmFamilias, 'Familias');
end;

procedure TfrmMain.btn_ImportarFactusolClick(Sender: TObject);
begin
  OpenFormInTab(TfrmImportarFactusol, 'Importar Factusol');
end;

procedure TfrmMain.btn_MateriasPrimasClick(Sender: TObject);
begin
  OpenFormInTab(TfrmMateriasPrimas, 'Materias Primas');
end;

procedure TfrmMain.btnAsignarMateriasPrimasClick(Sender: TObject);
begin
  OpenFormInTab(TfrmAsignarMateriasPrimas, 'Asignar Materias Primas');
end;

procedure TfrmMain.btn_RecetasClick(Sender: TObject);
begin
  OpenFormInTab(TfrmRecetas, 'Recetario Maestro');
end;

procedure TfrmMain.btnOrdenesFabricacionClick(Sender: TObject);
begin
  OpenFormInTab(TfrmOrdenesFabricacion, 'Órdenes de Fabricación');
end;

procedure TfrmMain.btnMonitorFabricacionClick(Sender: TObject);
begin
  OpenFormInTab(TfrmMonitorFabricacion, 'Monitor de Planta');
end;

procedure TfrmMain.btnCalendarioProduccionClick(Sender: TObject);
begin
  OpenFormInTab(TfrmCalendarioProduccion, 'Calendario de Producción');
end;

procedure TfrmMain.btnEventosMaterialesCatClick(Sender: TObject);
begin
  OpenFormInTab(TfrmEventosMaterialesCat, 'Catálogo Materiales Eventos');
end;

procedure TfrmMain.btnEventosClick(Sender: TObject);
begin
  OpenFormInTab(TfrmEventos, 'Gestión de Eventos');
end;

procedure TfrmMain.btnUsuariosClick(Sender: TObject);
begin
  OpenFormInTab(TfrmUsuarios, 'Gestión de Usuarios');
end;

procedure TfrmMain.btnAlergenosClick(Sender: TObject);
begin
  OpenFormInTab(TfrmAlergenos, 'Alérgenos');
end;

procedure TfrmMain.btnTiposIvaClick(Sender: TObject);
begin
  OpenFormInTab(TfrmTiposIva, 'Tipos de IVA');
end;

procedure TfrmMain.btnFormasPagoClick(Sender: TObject);
begin
  OpenFormInTab(TfrmFormasPago, 'Formas de Pago');
end;

procedure TfrmMain.btnSeriesClick(Sender: TObject);
begin
  OpenFormInTab(TfrmSeries, 'Series');
end;

procedure TfrmMain.btn_ClientesClick(Sender: TObject);
begin
  OpenFormInTab(TfrmClientes, 'Clientes');
end;

procedure TfrmMain.btnClientesGruposClick(Sender: TObject);
begin
  OpenFormInTab(TfrmClientesGrupos, 'Grupos de Clientes');
end;

procedure TfrmMain.btnAlmacenesClick(Sender: TObject);
begin
  OpenFormInTab(TfrmAlmacenes, 'Almacenes');
end;

procedure TfrmMain.btnObradoresClick(Sender: TObject);
begin
  OpenFormInTab(TfrmObradores, 'Obradores');
end;

procedure TfrmMain.btnCentrosZonasClick(Sender: TObject);
var
  LFrm: TfrmCentrosZonas;
begin
  LFrm := TfrmCentrosZonas(OpenFormInTab(TfrmCentrosZonas, 'Zonas y Maquinaria'));
  if Assigned(LFrm) then
    LFrm.pgcDetalles.ActivePage := LFrm.tsEquipos;
end;

procedure TfrmMain.btnProveedorClick(Sender: TObject);
begin
  OpenFormInTab(TfrmProveedoresList, 'Proveedores');
end;

procedure TfrmMain.btnProvAlbaranesClick(Sender: TObject);
begin
  OpenFormInTab(TfrmProvAlbaranesList, 'Albaranes de Proveedores');
end;

procedure TfrmMain.btnProvFacturasClick(Sender: TObject);
begin
  OpenFormInTab(TfrmProvFacturasList, 'Facturas de Proveedores');
end;

procedure TfrmMain.btnProvPresupuestosClick(Sender: TObject);
begin
  OpenFormInTab(TfrmProvPresupuestosList, 'Presupuestos de Proveedores');
end;

procedure TfrmMain.btnArticulosProvClick(Sender: TObject);
begin
  OpenFormInTab(TfrmArticulosProveedor, 'Artículos de Proveedor');
end;

procedure TfrmMain.btnProvPreciosVariacionesClick(Sender: TObject);
begin
  OpenFormInTab(TfrmProvPreciosVariaciones, 'Variaciones de Precios de Compra');
end;

procedure TfrmMain.btnVentasPreciosHistoricoClick(Sender: TObject);
begin
  OpenFormInTab(TfrmVentasPreciosHistorico, 'Histórico de Precios y Tarifas de Venta');
end;

procedure TfrmMain.btnIncidenciasClick(Sender: TObject);
begin
  OpenFormInTab(TfrmIncidencias, 'Control de Incidencias');
end;

procedure TfrmMain.btnFormatosPresentacionClick(Sender: TObject);
begin
  OpenFormInTab(TfrmFormatosPresentacion, 'Formatos de Presentación');
end;

procedure TfrmMain.btnFormatosEnvioClick(Sender: TObject);
begin
  OpenFormInTab(TfrmFormatosEnvio, 'Formatos de Envío');
end;

procedure TfrmMain.btnTransportistasClick(Sender: TObject);
begin
  OpenFormInTab(TfrmTransportistas, 'Catálogo de Transportistas');
end;

procedure TfrmMain.btnConfigEnvioClick(Sender: TObject);
begin
  OpenFormInTab(TfrmConfigEnvio, 'Cuentas de Correo y Envíos');
end;

procedure TfrmMain.btnPresupuestosClick(Sender: TObject);
begin
  OpenFormInTab(TfrmPresupuestos, 'Presupuestos');
end;

procedure TfrmMain.btnEntradasClick(Sender: TObject);
begin
  OpenFormInTab(TfrmEntradasMateriasPrimas, 'Entradas de Materias Primas');
end;

procedure TfrmMain.btnStockEnvasadoClick(Sender: TObject);
begin
  OpenFormInTab(TfrmStockEnvasado, 'Stock y Entradas (Envasado)');
end;

procedure TfrmMain.btnInventarioStockEnvasadoClick(Sender: TObject);
begin
  OpenFormInTab(TfrmInventarioStockEnvasado, 'Inventario Stock');
end;

procedure TfrmMain.btnInventariosClick(Sender: TObject);
begin
  OpenFormInTab(TfrmInventarios, 'Inventarios Físicos');
end;

procedure TfrmMain.btnCambiarEmpresaClick(Sender: TObject);
var
  I: Integer;
begin
  if not Assigned(frmSelectCompany) then
    Application.CreateForm(TfrmSelectCompany, frmSelectCompany);
  try
    if frmSelectCompany.ShowModal = mrOk then
    begin
      // Actualizar visualmente la interfaz
      Self.Caption := 'Gestión - ' + dmgMain.CurrentCompanyName;
      StatusBar1.Panels[2].Text := 'Empresa: ' + dmgMain.CurrentCompanyName;
      
      // Cerrar todas las pestañas abiertas para forzar recarga de datos con la nueva empresa
      for I := pcWorkspace.PageCount - 1 downto 0 do
      begin
        CloseTabByIndex(I);
      end;
      
      ShowMessage('Se ha cambiado a la empresa: ' + dmgMain.CurrentCompanyName);
    end;
    finally
      frmSelectCompany.Free;
      frmSelectCompany := nil;
    end;
end;

procedure TfrmMain.WMResetWorkspace(var Message: TMessage);
begin
  ResetWorkspace;
end;

procedure TfrmMain.ResetWorkspace;
var
  I: Integer;
begin
  for I := pcWorkspace.PageCount - 1 downto 0 do
  begin
    CloseTabByIndex(I);
  end;
end;

procedure TfrmMain.m_CerrarTabClick(Sender: TObject);
begin
  if pcWorkspace.ActivePage <> nil then
    CloseTabByIndex(pcWorkspace.ActivePageIndex);
end;

procedure TfrmMain.btnCerrarTabClick(Sender: TObject);
begin
  m_CerrarTabClick(nil);
end;

procedure TfrmMain.pcWorkspaceMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var
  I: Integer;
  LCloseRect: TRect;
begin
  if Button = mbLeft then
  begin
    for I := 0 to pcWorkspace.PageCount - 1 do
    begin
      LCloseRect := GetCloseButtonRect(I);

      if PtInRect(LCloseRect, Point(X, Y)) then
      begin
        CloseTabByIndex(I);
        Exit;
      end;
    end;
  end;
end;

procedure TfrmMain.pcWorkspaceTabClose(Sender: TObject; var CanClose: Boolean);
begin
  if (Sender is TTabSheet) and (TTabSheet(Sender).ControlCount > 0) then
  begin
    if TTabSheet(Sender).Controls[0] is TForm then
      TForm(TTabSheet(Sender).Controls[0]).Free;
  end;
  CanClose := True;
end;

function TfrmMain.OpenFormInTab(AFormClass: TFormClass; const ACaption: string): TForm;
var
  LPage: TTabSheet;
  LForm: TForm;
  I: Integer;
begin
  Result := nil;
  // Evitar duplicados
  for I := 0 to pcWorkspace.PageCount - 1 do
  begin
    if pcWorkspace.Pages[I].Caption = ACaption then
    begin
      pcWorkspace.ActivePageIndex := I;
      if pcWorkspace.Pages[I].ControlCount > 0 then
        if pcWorkspace.Pages[I].Controls[0] is TForm then
          Result := TForm(pcWorkspace.Pages[I].Controls[0]);
      Exit;
    end;
  end;

  LPage := TTabSheet.Create(pcWorkspace);
  LPage.PageControl := pcWorkspace;
  LPage.Caption := ACaption;

  // Activar la pestaña antes de crear y mostrar el formulario para que VCL tenga el layout/dimensiones correctas
  pcWorkspace.ActivePage := LPage;

  LForm := AFormClass.Create(LPage);
  LForm.Parent := LPage;
  LForm.BorderStyle := bsNone;
  LForm.Align := alClient;
  LForm.Visible := True;
  Result := LForm;
end;

procedure TfrmMain.btnConfigConexionClick(Sender: TObject);
begin
  Application.CreateForm(TfrmDbConfig, frmDbConfig);
  try
    if frmDbConfig.ShowModal = mrOk then
    begin
      StatusBar1.Panels[0].Text := 'Base de Datos: Conectada';
      ShowMessage('Configuración de conexión guardada con éxito.');
    end;
  finally
    frmDbConfig.Free;
  end;
end;

procedure TfrmMain.btnFeatureInDevelopmentClick(Sender: TObject);
var
  LCaption: string;
begin
  LCaption := 'esta opción';
  if Sender is TSpeedButton then
    LCaption := TSpeedButton(Sender).Caption
  else if Sender is TButton then
    LCaption := TButton(Sender).Caption
  else if Sender is TBitBtn then
    LCaption := TBitBtn(Sender).Caption;
  ShowMessage('La funcionalidad de "' + LCaption + '" se encuentra en desarrollo.');
end;

procedure TfrmMain.btnPedidosClick(Sender: TObject);
begin
  // Apertura directa e inmediata de Pedidos de Clientes
  OpenFormInTab(TfrmPedidos, 'Pedidos de Clientes');
end;

procedure TfrmMain.btnReportTemplatesClick(Sender: TObject);
begin
  OpenFormInTab(TfrmReportTemplates, 'Diseñador de Informes');
end;

procedure TfrmMain.btnChatIAClick(Sender: TObject);
begin
  OpenFormInTab(TfrmChatIA, 'Asistente IA');
end;

procedure TfrmMain.btnEnviosClick(Sender: TObject);
begin
  OpenFormInTab(TfrmEnviosList, 'Albaranes de Envío');
end;

procedure TfrmMain.btnPrepararPedidosClick(Sender: TObject);
begin
  OpenFormInTab(TfrmPrepararPedidos, 'Preparación de Pedidos');
end;

procedure TfrmMain.WMCheckWebOrders(var Message: TMessage);
var
  LOrders: TArray<TWebOrderHeader>;
  LMsg, LFechaStr, LEdicomMsg: string;
  i, LCompanyId: Integer;
  LPendingCount, LEdicomCount: Integer;
  LFechaDesde: TDateTime;
begin
  if (dmgMain.CurrentCompanyId = '') or not dmgMain.dbConn.Connected then Exit;
  
  LCompanyId := StrToIntDef(dmgMain.CurrentCompanyId, 1);

  // 1. Comprobación de pedidos web (WooCommerce) si está configurado para la empresa
  if TWebOrderImporter.HasWebConfig(LCompanyId) then
  begin
    if MessageDlg('¿Desea comprobar la existencia de nuevos pedidos web?',
                  mtConfirmation, [mbYes, mbNo], 0) = mrYes then
    begin
      LFechaStr := FormatDateTime('dd/MM/yyyy', Date - 30);
      if InputQuery('Comprobación de Pedidos WooCommerce',
                    'Indique la fecha desde la cual desea consultar pedidos web:',
                    LFechaStr) then
      begin
        if not TryStrToDate(LFechaStr, LFechaDesde) then
          LFechaDesde := Date - 30;

        try
          Screen.Cursor := crHourGlass;
          try
            if TWebOrderImporter.FetchPendingOrders(LCompanyId, LFechaDesde, LOrders, LMsg) then
            begin
              LPendingCount := 0;
              for i := 0 to Length(LOrders) - 1 do
              begin
                if not LOrders[i].Importado then
                  Inc(LPendingCount);
              end;
              
              Screen.Cursor := crDefault;
              if LPendingCount > 0 then
              begin
                if MessageDlg(Format('Atención: Hay %d pedido(s) nuevo(s) en la web desde el %s pendientes de importar.' + #13#10 +
                                    '¿Desea abrir el importador web ahora?', [LPendingCount, FormatDateTime('dd/MM/yyyy', LFechaDesde)]),
                               mtInformation, [mbYes, mbNo], 0) = mrYes then
                begin
                  if not Assigned(frmImportarPedidosWeb) then
                    Application.CreateForm(TfrmImportarPedidosWeb, frmImportarPedidosWeb);
                  frmImportarPedidosWeb.FechaInicialConsultada := LFechaDesde;
                  frmImportarPedidosWeb.ShowModal;
                end;
              end
              else
              begin
                MessageDlg('✅ No se han detectado nuevos pedidos web pendientes de importar desde el ' + FormatDateTime('dd/MM/yyyy', LFechaDesde) + '.', mtInformation, [mbOK], 0);
              end;
            end;
          finally
            Screen.Cursor := crDefault;
          end;
        except
          Screen.Cursor := crDefault;
        end;
      end;
    end;
  end;

  // 2. Comprobación de pedidos EDI (EDICOM iPaaS) si está configurado para la empresa
  if TEdicomWsClient.HasEdicomConfig(IntToStr(LCompanyId), dmgMain.dbConn) then
  begin
    if MessageDlg('¿Desea comprobar la existencia de nuevos pedidos EDI en EDICOM iPaaS?',
                  mtConfirmation, [mbYes, mbNo], 0) = mrYes then
    begin
      try
        Screen.Cursor := crHourGlass;
        try
          if TEdicomWsClient.DownloadAndImportPendingOrders(dmgMain.dbConn, IntToStr(LCompanyId), LEdicomCount, LEdicomMsg) then
          begin
            Screen.Cursor := crDefault;
            if LEdicomCount > 0 then
              MessageDlg(Format('Se han descargado e importado %d pedido(s) EDI desde EDICOM iPaaS correctamente.', [LEdicomCount]),
                         mtInformation, [mbOK], 0)
            else if LEdicomMsg <> '' then
              MessageDlg('Respuesta de EDICOM iPaaS:' + sLineBreak + LEdicomMsg, mtInformation, [mbOK], 0)
            else
              MessageDlg('✅ No se han detectado nuevos pedidos EDI en la suscripción de EDICOM iPaaS.', mtInformation, [mbOK], 0);
          end
          else
          begin
            Screen.Cursor := crDefault;
            if LEdicomMsg <> '' then
              MessageDlg('Error al consultar pedidos EDI en EDICOM: ' + LEdicomMsg, mtError, [mbOK], 0);
          end;
        finally
          Screen.Cursor := crDefault;
        end;
      except
        Screen.Cursor := crDefault;
      end;
    end;
  end;

  // 3. Comprobación de variaciones de precios de compra pendientes de supervisión (OK = 0)
  ComprobarVariacionesPreciosPendientes;
end;

procedure TfrmMain.ComprobarVariacionesPreciosPendientes;
var
  LQry: TFDQuery;
  LCompanyId: Integer;
  LMsg: string;
  LCount: Integer;
  LProv, LCod, LDesc: string;
  LAnt, LNuevo, LPorc: Double;
begin
  if not Assigned(dmgMain) or not Assigned(dmgMain.dbConn) or not dmgMain.dbConn.Connected then Exit;
  LCompanyId := StrToIntDef(dmgMain.CurrentCompanyId, 0);
  if LCompanyId <= 0 then Exit;

  LQry := TFDQuery.Create(nil);
  try
    LQry.Connection := dmgMain.dbConn;
    LQry.SQL.Text :=
      'SELECT v.id, p.nombre AS proveedor_nombre, v.codigo_articulo_proveedor, ' +
      '       v.descripcion, v.precio_anterior, v.precio_nuevo, v.variacion_importe, ' +
      '       v.variacion_porcentaje, v.documento, v.fecha_documento ' +
      'FROM ge_prov_precios_variaciones v ' +
      'LEFT JOIN ge_proveedores p ON v.id_proveedor = p.id ' +
      'WHERE v.id_empresa = :empresa AND (v.ok = 0 OR v.ok IS NULL) ' +
      'ORDER BY v.fecha_documento DESC, v.id DESC';
    LQry.ParamByName('empresa').AsInteger := LCompanyId;
    LQry.Open;

    if not LQry.IsEmpty then
    begin
      LCount := 0;
      LMsg := '⚠️ ATENCIÓN: Se han detectado variaciones en precios de compra pendientes de supervisión (OK = 0):' + #13#10#13#10;

      while not LQry.Eof do
      begin
        Inc(LCount);
        if LCount <= 10 then
        begin
          LProv := LQry.FieldByName('proveedor_nombre').AsString;
          LCod := LQry.FieldByName('codigo_articulo_proveedor').AsString;
          LDesc := LQry.FieldByName('descripcion').AsString;
          LAnt := LQry.FieldByName('precio_anterior').AsFloat;
          LNuevo := LQry.FieldByName('precio_nuevo').AsFloat;
          LPorc := LQry.FieldByName('variacion_porcentaje').AsFloat;

          LMsg := LMsg + Format('• [%s] Cód: %s' + #13#10 +
                                '  Artículo: %s' + #13#10 +
                                '  Precio anterior: %.4f €  ->  Precio nuevo: %.4f € (%+.2f %%)' + #13#10#13#10,
                                [LProv, LCod, LDesc, LAnt, LNuevo, LPorc]);
        end;
        LQry.Next;
      end;

      if LCount > 10 then
        LMsg := LMsg + Format('... y %d variaciones más pendientes de supervisar.' + #13#10#13#10, [LCount - 10]);

      LMsg := LMsg + '¿Desea abrir el listado de Variaciones de Precios para revisarlas ahora?';

      if MessageDlg(LMsg, mtWarning, [mbYes, mbNo], 0) = mrYes then
      begin
        btnProvPreciosVariacionesClick(Self);
      end;
    end;
  finally
    LQry.Free;
  end;
end;

procedure TfrmMain.btnCodigosBarrasCompletoClick(Sender: TObject);
begin
  OpenFormInTab(TfrmCodigosBarrasCompleto, 'Códigos de Barras Completos');
end;

procedure TfrmMain.btnCalidadDocumentosClick(Sender: TObject);
begin
  OpenFormInTab(TfrmCalidadDocumentosList, 'Registro General de Documentos (Calidad e IFS)');
end;

procedure TfrmMain.btnCalidadRegistrosClick(Sender: TObject);
begin
  OpenFormInTab(TfrmCalidadPlannerList, 'Planificador y Registros de Calidad (IFS)');
end;

procedure TfrmMain.btnCalidadPrerrequisitosClick(Sender: TObject);
var
  LEditor: TfrmCalidadPrerrequisitosEditor;
begin
  LEditor := TfrmCalidadPrerrequisitosEditor.Create(Self);
  try
    LEditor.ShowModal;
  finally
    LEditor.Free;
  end;
end;

procedure TfrmMain.btnCalidadIncidenciasClick(Sender: TObject);
begin
  OpenFormInTab(TfrmCalidadIncidenciasList, 'No Conformidades y Acciones Correctoras (RG-11)');
end;

procedure TfrmMain.btnCalidadVerificacionClick(Sender: TObject);
begin
  OpenFormInTab(TfrmCalidadVerificacionDiaria, 'Verificación Diaria Calidad (RG-12)');
end;

procedure TfrmMain.btnCalidadTrazabilidadClick(Sender: TObject);
begin
  OpenFormInTab(TfrmCalidadTrazabilidadMaestra, 'Trazabilidad Maestra (RG-13)');
end;

procedure TfrmMain.btnCalidadGruposControlClick(Sender: TObject);
begin
  OpenFormInTab(TfrmCalidadGrupos, 'Grupos de Informes de Calidad');
end;

procedure TfrmMain.btnCalidadHitosClick(Sender: TObject);
begin
  OpenFormInTab(TfrmCalidadHitos, 'Hitos y Procesos de Calidad');
end;

procedure TfrmMain.btnCalidadPlannerClick(Sender: TObject);
begin
  OpenFormInTab(TfrmCalidadPlannerList, 'Planificador y Cumplimiento de Calidad (IFS)');
end;

procedure TfrmMain.btnTrabajadoresRibbonClick(Sender: TObject);
begin
  OpenFormInTab(TfrmTrabajadores, 'Gestión de Trabajadores');
end;

procedure TfrmMain.btnTrabajadoresGruposRibbonClick(Sender: TObject);
begin
  OpenFormInTab(TfrmTrabajadoresGrupos, 'Grupos de Trabajadores');
end;

procedure TfrmMain.btnFichajesRibbonClick(Sender: TObject);
begin
  OpenFormInTab(TfrmTrabajadoresFichajes, 'Control Horario y Fichajes');
end;

procedure TfrmMain.btnCalendarioLaboralRibbonClick(Sender: TObject);
begin
  OpenFormInTab(TfrmCalendarioLaboral, 'Calendario Laboral Oficial');
end;

procedure TfrmMain.btnTiemposAreasRibbonClick(Sender: TObject);
var
  LFrm: TfrmCentrosZonas;
begin
  LFrm := TfrmCentrosZonas(OpenFormInTab(TfrmCentrosZonas, 'Tiempos Secciones'));
  if Assigned(LFrm) then
    LFrm.pgcDetalles.ActivePage := LFrm.tsTiempos;
end;

procedure TfrmMain.btnCostesManoObraRibbonClick(Sender: TObject);
var
  LFrm: TfrmCentrosZonas;
begin
  LFrm := TfrmCentrosZonas(OpenFormInTab(TfrmCentrosZonas, 'Procesos y Costes'));
  if Assigned(LFrm) then
    LFrm.pgcDetalles.ActivePage := LFrm.tsProcesos;
end;

procedure TfrmMain.btnTipsaConfigClick(Sender: TObject);
begin
  OpenFormInTab(TfrmTipsaConfig, 'Configuración Envíos Tipsa');
end;

procedure TfrmMain.btnTerminalPlantaRibbonClick(Sender: TObject);
begin
  ShellExecute(0, 'open', PChar(ExtractFilePath(Application.ExeName) + 'CONTROL_TRABAJOS\index.html'), nil, nil, SW_SHOWNORMAL);
end;

procedure TfrmMain.btnTermometroBLEClick(Sender: TObject);
begin
  OpenFormInTab(TfrmTermometroMonitor, 'Termómetro BLE');
end;

procedure TfrmMain.btnTiendasClick(Sender: TObject);
begin
  OpenFormInTab(TfrmTiendas, 'Gestión de Tiendas');
end;

procedure TfrmMain.btnMovimientosStockClick(Sender: TObject);
begin
  OpenFormInTab(TfrmMovimientosInternos, 'Movimientos Internos de Stock');
end;

end.
