import { Color, Model, UID } from "../../../src";
import { GaugeChartRuntime } from "../../../src/types/chart/gauge_chart";
import { ScorecardChartRuntime } from "../../../src/types/chart/scorecard_chart";
import {
  activateSheet,
  addEqualCf,
  createChart,
  createGaugeChart,
  createScorecardChart,
  createSheet,
  duplicateSheet,
  setCellContent,
  setFormatting,
  updateFigure,
} from "../../test_helpers/commands_helpers";

describe("Single cell chart background color", () => {
  let model: Model;
  let sheetId: UID;
  const chartId = "thisIsAnId";

  function getGaugeOrScorecardRuntime(
    model: Model,
    chartId: UID
  ): GaugeChartRuntime | ScorecardChartRuntime {
    return model.getters.getChartRuntime(chartId) as GaugeChartRuntime | ScorecardChartRuntime;
  }

  beforeEach(() => {
    model = new Model();
    sheetId = model.getters.getActiveSheetId();
    setCellContent(model, "A1", "1");
  });

  function addCfToA1(fillColor: Color) {
    addEqualCf(model, "A1", { fillColor }, "1");
  }

  function addFillToA1(color: Color) {
    setFormatting(model, "A1", { fillColor: color });
  }

  function createTestChart(chartType: string, mainCell: string, background?: Color) {
    if (chartType === "scorecard") {
      createScorecardChart(model, { background, keyValue: `=${mainCell}` }, chartId);
    } else if (chartType === "gauge") {
      createGaugeChart(model, { background, dataRange: mainCell }, chartId);
    }
  }

  test.each(["scorecard", "gauge"])(
    "chart %s background color change with main cell CF background color",
    (chartType: string) => {
      createTestChart(chartType, "A1");
      expect(getGaugeOrScorecardRuntime(model, chartId).background).toEqual("#FFFFFF");
      addCfToA1("#FF0000");
      expect(getGaugeOrScorecardRuntime(model, chartId).background).toEqual("#FF0000");
      setCellContent(model, "A1", "random value not in CF");
      expect(getGaugeOrScorecardRuntime(model, chartId).background).toEqual("#FFFFFF");
    }
  );

  test.each(["scorecard", "gauge"])(
    "chart %s background color change with main cell background color",
    (chartType: string) => {
      createTestChart(chartType, "A1");
      expect(getGaugeOrScorecardRuntime(model, chartId).background).toEqual("#FFFFFF");
      addFillToA1("#00FF00");
      expect(getGaugeOrScorecardRuntime(model, chartId).background).toEqual("#00FF00");
    }
  );

  test.each(["scorecard", "gauge"])(
    "CF color have priority over cell background color",
    (chartType: string) => {
      addCfToA1("#FF0000");
      addFillToA1("#00FF00");
      createTestChart(chartType, "A1");
      expect(getGaugeOrScorecardRuntime(model, chartId).background).toEqual("#FF0000");
    }
  );

  test.each(["scorecard", "gauge"])(
    "chart background color have priority over CF color",
    (chartType: string) => {
      addCfToA1("#FF0000");
      createTestChart(chartType, "A1", "#0000FF");
      expect(getGaugeOrScorecardRuntime(model, chartId).background).toEqual("#0000FF");
    }
  );

  test.each(["scorecard", "gauge"])(
    "Chart style change based on CF of another sheet",
    (chartType: string) => {
      createSheet(model, { sheetId: "sheet2" });
      activateSheet(model, "sheet2");
      setCellContent(model, "A1", "1", sheetId);
      addEqualCf(model, "A1", { fillColor: "#000FFF" }, "1", "cfId", sheetId);
      const sheet1Name = model.getters.getSheetName(sheetId);
      createTestChart(chartType, `${sheet1Name}!A1`);
      expect(getGaugeOrScorecardRuntime(model, chartId).background).toEqual("#000FFF");
    }
  );

  test("Duplicating a sheet preserves the figure dimensions", () => {
    const firstSheetId = model.getters.getActiveSheetId();
    const secondSheetId = "42";
    createChart(model, { type: "bar" });
    const firstSheetFigures = model.getters.getFigures(firstSheetId);
    expect(firstSheetFigures.length).toBe(1);
    updateFigure(model, {
      sheetId,
      figureId: firstSheetFigures[0].id,
      offset: {
        x: 0,
        y: 0,
      },
      width: 123,
      height: 321,
      col: 0,
      row: 0,
    });
    duplicateSheet(model, firstSheetId, secondSheetId);
    const secondSheetFigures = model.getters.getFigures(secondSheetId);
    expect(secondSheetFigures.length).toBe(1);
    expect(firstSheetFigures[0]).toMatchObject({
      ...secondSheetFigures[0],
      id: expect.any(String),
    });
  });
});
