unit frm_ProvPreciosVariaciones;

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, Vcl.ComCtrls,
  FireDAC.Comp.Client, FireDAC.Stan.Param,
  frm_BaseList, uAppTheme;

type
  TfrmProvPreciosVariaciones = class(TfrmBaseList)
    procedure FormShow(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure btnRefreshClick(Sender: TObject); override;
  private
    FcbbFiltroOk: TComboBox;
    FbtnMarcarOk: TSpeedButton;
    procedure ConfigureColumns;
    procedure FormatNumericFields(DataSet: TDataSet);
    procedure dbGridCustomDrawColumnCell(Sender: TObject; const Rect: TRect;
      DataCol: Integer; Column: TColumn; State: TGridDrawState);
    procedure dbGridMainCellClick(Column: TColumn);
    procedure dbGridMainDblClick(Sender: TObject);
    procedure dbGridMainKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
    procedure cbbFiltroOkChange(Sender: TObject);
    procedure btnMarcarOkClick(Sender: TObject);
    procedure ToggleOk;
  public
    { Public declarations }
  end;

var
  frmProvPreciosVariaciones: TfrmProvPreciosVariaciones;

implementation

uses
  dmg_Main;

{$R *.dfm}

procedure TfrmProvPreciosVariaciones.FormShow(Sender: TObject);
begin
  inherited;
  frmProvPreciosVariaciones := Self;
  OnDestroy := FormDestroy;

  pnlSearch.Visible := True;
  lblSearch.Caption := 'Buscar Variación:';

  // Ocultar botones no aplicables
  btnNuevo.Visible := False;
  btnEditar.Visible := False;
  btnBorrar.Visible := False;

  // Botón para alternar estado de supervisión
  if not Assigned(FbtnMarcarOk) then
  begin
    FbtnMarcarOk := TSpeedButton.Create(Self);
    FbtnMarcarOk.Parent := pnlActions;
    FbtnMarcarOk.Align := alLeft;
    FbtnMarcarOk.Width := 95;
    FbtnMarcarOk.Height := 63;
    FbtnMarcarOk.Caption := 'Supervisar'#13#10'(OK)';
    FbtnMarcarOk.Flat := True;
    FbtnMarcarOk.Font.Charset := DEFAULT_CHARSET;
    FbtnMarcarOk.Font.Color := clWindowText;
    FbtnMarcarOk.Font.Height := -11;
    FbtnMarcarOk.Font.Name := 'Segoe UI';
    FbtnMarcarOk.Font.Style := [fsBold];
    FbtnMarcarOk.Layout := blGlyphTop;
    FbtnMarcarOk.ParentFont := False;
    FbtnMarcarOk.OnClick := btnMarcarOkClick;
  end;

  // Combo de filtrado por estado de verificación (Tag 999 para excluir de change tracking)
  if not Assigned(FcbbFiltroOk) then
  begin
    FcbbFiltroOk := TComboBox.Create(Self);
    FcbbFiltroOk.Tag := 999;
    FcbbFiltroOk.Parent := pnlSearch;
    FcbbFiltroOk.Style := csDropDownList;
    FcbbFiltroOk.Items.Add('Todas las variaciones');
    FcbbFiltroOk.Items.Add('⚠️ Pendientes (OK = 0)');
    FcbbFiltroOk.Items.Add('✅ Supervisadas (OK = 1)');
    FcbbFiltroOk.ItemIndex := 0;
    FcbbFiltroOk.Left := edtSearch.Left + edtSearch.Width + 12;
    FcbbFiltroOk.Top := edtSearch.Top;
    FcbbFiltroOk.Width := 185;
    FcbbFiltroOk.Height := edtSearch.Height;
    FcbbFiltroOk.OnChange := cbbFiltroOkChange;
  end;

  DateFilterField := 'v.fecha_documento';
  dbGridMain.OnDrawColumnCell := dbGridCustomDrawColumnCell;
  dbGridMain.OnCellClick := dbGridMainCellClick;
  dbGridMain.OnDblClick := dbGridMainDblClick;
  dbGridMain.OnKeyDown := dbGridMainKeyDown;

  btnRefreshClick(Self);
end;

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

procedure TfrmProvPreciosVariaciones.cbbFiltroOkChange(Sender: TObject);
begin
  btnRefreshClick(Self);
end;

procedure TfrmProvPreciosVariaciones.btnMarcarOkClick(Sender: TObject);
begin
  ToggleOk;
end;

procedure TfrmProvPreciosVariaciones.dbGridMainCellClick(Column: TColumn);
begin
  if Assigned(Column) and SameText(Column.FieldName, 'ok') then
    ToggleOk;
end;

procedure TfrmProvPreciosVariaciones.dbGridMainDblClick(Sender: TObject);
begin
  ToggleOk;
end;

procedure TfrmProvPreciosVariaciones.dbGridMainKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
  if (Key = VK_SPACE) and Assigned(dbGridMain.SelectedField) and SameText(dbGridMain.SelectedField.FieldName, 'ok') then
  begin
    ToggleOk;
    Key := 0;
  end;
end;

procedure TfrmProvPreciosVariaciones.ToggleOk;
var
  LNewVal, LId: Integer;
  LQryUpd: TFDQuery;
begin
  if not Assigned(FQryMain) or FQryMain.IsEmpty or (FQryMain.FieldByName('id').AsInteger <= 0) then Exit;

  LId := FQryMain.FieldByName('id').AsInteger;
  if FQryMain.FieldByName('ok').AsInteger = 1 then
    LNewVal := 0
  else
    LNewVal := 1;

  LQryUpd := TFDQuery.Create(nil);
  try
    LQryUpd.Connection := dmgMain.dbConn;
    LQryUpd.SQL.Text := 'UPDATE ge_prov_precios_variaciones SET ok = :ok WHERE id = :id';
    LQryUpd.ParamByName('ok').AsInteger := LNewVal;
    LQryUpd.ParamByName('id').AsInteger := LId;
    LQryUpd.ExecSQL;
  finally
    LQryUpd.Free;
  end;

  FQryMain.Edit;
  FQryMain.FieldByName('ok').AsInteger := LNewVal;
  FQryMain.Post;
end;

procedure TfrmProvPreciosVariaciones.btnRefreshClick(Sender: TObject);
var
  LSql: string;
  LSearch: string;
begin
  if dmgMain.CurrentCompanyId = '' then Exit;

  LSearch := Trim(edtSearch.Text);
  FQryMain.Close;

  LSql :=
    'SELECT v.id, v.fecha_documento, v.tipo_documento, v.documento, ' +
    '       p.nombre AS proveedor_nombre, v.codigo_articulo_proveedor, v.descripcion, ' +
    '       COALESCE(mp.descripcion, '''') AS materia_prima_nombre, ' +
    '       v.precio_anterior, v.precio_nuevo, v.variacion_importe, v.variacion_porcentaje, ' +
    '       COALESCE(v.ok, 0) AS ok ' +
    'FROM ge_prov_precios_variaciones v ' +
    'LEFT JOIN ge_proveedores p ON v.id_proveedor = p.id ' +
    'LEFT JOIN ge_materias_primas mp ON v.id_materia_prima = mp.id ' +
    'WHERE v.id_empresa = :empresa ';

  if Assigned(FcbbFiltroOk) then
  begin
    if FcbbFiltroOk.ItemIndex = 1 then
      LSql := LSql + 'AND (v.ok = 0 OR v.ok IS NULL) '
    else if FcbbFiltroOk.ItemIndex = 2 then
      LSql := LSql + 'AND v.ok = 1 ';
  end;

  if LSearch <> '' then
  begin
    LSql := LSql +
      'AND (p.nombre LIKE :search ' +
      '     OR v.descripcion LIKE :search ' +
      '     OR v.codigo_articulo_proveedor LIKE :search ' +
      '     OR v.documento LIKE :search ' +
      '     OR mp.descripcion LIKE :search) ';
  end;

  LSql := LSql + 'ORDER BY v.fecha_documento DESC, v.id DESC';

  FQryMain.SQL.Text := LSql;
  FQryMain.ParamByName('empresa').AsString := dmgMain.CurrentCompanyId;
  if LSearch <> '' then
    FQryMain.ParamByName('search').AsString := '%' + LSearch + '%';

  FQryMain.Open;
  FormatNumericFields(FQryMain);
  ConfigureColumns;
end;

procedure TfrmProvPreciosVariaciones.ConfigureColumns;
begin
  dbGridMain.Columns.Clear;

  with dbGridMain.Columns.Add do
  begin
    FieldName := 'ok';
    Title.Caption := 'OK';
    Title.Alignment := taCenter;
    Width := 40;
    Alignment := taCenter;
  end;

  with dbGridMain.Columns.Add do
  begin
    FieldName := 'fecha_documento';
    Title.Caption := 'Fecha';
    Width := 85;
  end;

  with dbGridMain.Columns.Add do
  begin
    FieldName := 'tipo_documento';
    Title.Caption := 'Tipo';
    Width := 75;
  end;

  with dbGridMain.Columns.Add do
  begin
    FieldName := 'documento';
    Title.Caption := 'Nº Doc.';
    Width := 105;
  end;

  with dbGridMain.Columns.Add do
  begin
    FieldName := 'proveedor_nombre';
    Title.Caption := 'Proveedor';
    Width := 180;
  end;

  with dbGridMain.Columns.Add do
  begin
    FieldName := 'codigo_articulo_proveedor';
    Title.Caption := 'Cód. Proveedor';
    Width := 95;
  end;

  with dbGridMain.Columns.Add do
  begin
    FieldName := 'descripcion';
    Title.Caption := 'Artículo / Producto';
    Width := 210;
  end;

  with dbGridMain.Columns.Add do
  begin
    FieldName := 'materia_prima_nombre';
    Title.Caption := 'Materia Prima Asignada';
    Width := 170;
  end;

  with dbGridMain.Columns.Add do
  begin
    FieldName := 'precio_anterior';
    Title.Caption := 'Precio Ant. (€)';
    Width := 95;
  end;

  with dbGridMain.Columns.Add do
  begin
    FieldName := 'precio_nuevo';
    Title.Caption := 'Precio Nuevo (€)';
    Width := 95;
  end;

  with dbGridMain.Columns.Add do
  begin
    FieldName := 'variacion_importe';
    Title.Caption := 'Diferencia (€)';
    Width := 95;
  end;

  with dbGridMain.Columns.Add do
  begin
    FieldName := 'variacion_porcentaje';
    Title.Caption := 'Variación (%)';
    Width := 90;
  end;
end;

procedure TfrmProvPreciosVariaciones.FormatNumericFields(DataSet: TDataSet);
var
  i: Integer;
  Fld: TField;
begin
  for i := 0 to DataSet.FieldCount - 1 do
  begin
    Fld := DataSet.Fields[i];
    if Fld is TNumericField then
    begin
      if SameText(Fld.FieldName, 'precio_anterior') or SameText(Fld.FieldName, 'precio_nuevo') then
        TNumericField(Fld).DisplayFormat := '#,##0.0000 €'
      else if SameText(Fld.FieldName, 'variacion_importe') then
        TNumericField(Fld).DisplayFormat := '+#,##0.0000 €;-#,##0.0000 €;0.0000 €'
      else if SameText(Fld.FieldName, 'variacion_porcentaje') then
        TNumericField(Fld).DisplayFormat := '+0.00 %;-0.00 %;0.00 %';
    end;
  end;
end;

procedure TfrmProvPreciosVariaciones.dbGridCustomDrawColumnCell(Sender: TObject; const Rect: TRect;
  DataCol: Integer; Column: TColumn; State: TGridDrawState);
var
  Grid: TDBGrid;
  LVarImp: Double;
  IsSelected: Boolean;
  LBoxRect: TRect;
  LChecked: Boolean;
begin
  Grid := TDBGrid(Sender);
  IsSelected := gdSelected in State;

  if Assigned(Column.Field) then
  begin
    // Dibujado automático de casilla de verificación para el campo OK
    if SameText(Column.FieldName, 'ok') then
    begin
      Grid.Canvas.FillRect(Rect);
      LChecked := (Column.Field.AsInteger = 1);
      LBoxRect.Left := Rect.Left + (Rect.Width - 14) div 2;
      LBoxRect.Top := Rect.Top + (Rect.Height - 14) div 2;
      LBoxRect.Right := LBoxRect.Left + 14;
      LBoxRect.Bottom := LBoxRect.Top + 14;
      if LChecked then
        DrawFrameControl(Grid.Canvas.Handle, LBoxRect, DFC_BUTTON, DFCS_BUTTONCHECK or DFCS_CHECKED)
      else
        DrawFrameControl(Grid.Canvas.Handle, LBoxRect, DFC_BUTTON, DFCS_BUTTONCHECK);
      Exit;
    end;

    if not IsSelected then
    begin
      LVarImp := 0.0;
      if Assigned(Grid.DataSource) and Assigned(Grid.DataSource.DataSet) and Grid.DataSource.DataSet.Active then
        LVarImp := Grid.DataSource.DataSet.FieldByName('variacion_importe').AsFloat;

      if SameText(Column.FieldName, 'variacion_importe') or SameText(Column.FieldName, 'variacion_porcentaje') then
      begin
        if LVarImp > 0.0001 then
        begin
          // Subida de coste: fondo rosado suave, texto rojo oscuro
          Grid.Canvas.Brush.Color := $E8E8FF;
          Grid.Canvas.Font.Color := $0000B3;
          Grid.Canvas.Font.Style := [fsBold];
        end
        else if LVarImp < -0.0001 then
        begin
          // Bajada de coste: fondo verde suave, texto verde oscuro
          Grid.Canvas.Brush.Color := $E2F5E2;
          Grid.Canvas.Font.Color := $006622;
          Grid.Canvas.Font.Style := [fsBold];
        end;
      end
      else
      begin
        // Filas alternas
        if Assigned(Grid.DataSource.DataSet) and Odd(Grid.DataSource.DataSet.RecNo) then
          Grid.Canvas.Brush.Color := TAppTheme.COLOR_GRID_ROW_ODD
        else
          Grid.Canvas.Brush.Color := TAppTheme.COLOR_GRID_ROW_EVEN;
      end;
    end;
  end;

  Grid.DefaultDrawColumnCell(Rect, DataCol, Column, State);
end;

end.
