import React, { useEffect, useRef, useState } from "react";
import { Card } from "../../tremor/Card";
import { Label } from "../../tremor/Text";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "../../tremor/Select";
import { Input } from "../../tremor/Input";
import { Button } from "../../tremor/Button";
import { Switch } from "../../tremor/Switch";
import { Tabs, TabsList, TabsTrigger } from "../../tremor/Tabs";
import { Bars3BottomLeftIcon, Bars3BottomRightIcon, Bars3Icon } from "@heroicons/react/24/outline";
import { Divider } from "../../tremor/Divider";

const chartTypes = [
  "line",
  "bar",
  "area",
  "metric",
  "table",
  "pie",
  "doughnut",
  "bubble",
  "polarArea",
  "radar",
  "scatter",
  "funnel",
].map((a) => ({ label: a, value: a }));

const PositionPicker: React.FC<{
  value: string;
  onValueChange: (str: string) => void;
}> = ({ value, onValueChange }) => {
  return (
    <Tabs
      defaultValue="top"
      value={value || "top"}
      onValueChange={onValueChange}
    >
      <TabsList variant="solid">
        <TabsTrigger value="top">Top</TabsTrigger>
        <TabsTrigger value="left">Left</TabsTrigger>
        <TabsTrigger value="bottom">Bottom</TabsTrigger>
        <TabsTrigger value="right">Right</TabsTrigger>
      </TabsList>
    </Tabs>
  );
};

const AlignmentPicker: React.FC<{
  value: string;
  onValueChange: (str: string) => void;
}> = ({ value, onValueChange }) => {
  return (
    <Tabs
      defaultValue="start"
      value={value || "start"}
      onValueChange={onValueChange}
    >
      <TabsList variant="solid">
        <TabsTrigger value="start"><Bars3BottomLeftIcon className="onvo-size-4" /></TabsTrigger>
        <TabsTrigger value="center"><Bars3Icon className="onvo-size-4" /></TabsTrigger>
        <TabsTrigger value="end"><Bars3BottomRightIcon className="onvo-size-4" /></TabsTrigger>
      </TabsList>
    </Tabs>
  );
};

export const WidgetWizard: React.FC<{
  columns: string[],
  onChange: (config: any) => void;
  config: any;
}> = ({ columns, onChange, config }) => {

  const [type, setType] = useState(chartTypes[0].value);
  const [labels, setLabels] = useState("");
  const [title, setTitle] = useState<{
    'text': string,
    'display'?: boolean,
    'position'?: string,
    'align'?: string,
  }>({
    'text': ""
  });

  const [subtitle, setSubtitle] = useState<{
    'text': string,
    'display'?: boolean,
    'position'?: string,
    'align'?: string,
  }>({
    'text': ""
  });

  const [xAxis, setXAxis] = useState<{
    'text'?: string,
    'display'?: boolean
  }>({
    'display': false
  });

  const [yAxis, setYAxis] = useState<{
    'text'?: string,
    'display'?: boolean
  }>({
    'display': false
  });


  const [legend, setLegend] = useState<{
    'display'?: boolean,
    'position'?: string,
    'align'?: string,
  }>({
    'display': false
  });

  const [datasets, setDatasets] = useState<
    {
      title: string;
      data: string;
      type: string;
      backgroundColor?: string;
      borderColor?: string;
      borderWidth?: number;
    }[]
  >([]);



  const prevConfig = useRef(null);

  const constructCode = () => {
    let newConfig = {
      'type': type,
      'data': {
        'labels': labels,
        'datasets': datasets.map(
          (d) => ({
            'label': d.title,
            'type': d.type,
            'data': d.data,
            'backgroundColor': d.backgroundColor,
            'borderColor': d.borderColor,
            'borderWidth': d.borderWidth,
          })
        )
      },
      'options': {
        'responsive': true,
        'maintainAspectRatio': false,
        'plugins': {
          'title': title,
          'subtitle': subtitle,
          'legend': legend
        },
        'scales': {
          'x': xAxis,
          'y': yAxis
        }
      }
    };

    if (JSON.stringify(prevConfig.current) !== JSON.stringify(newConfig)) {
      // @ts-ignore
      prevConfig.current = newConfig;
      onChange(newConfig);
    }
  };

  useEffect(() => {
    if (config && JSON.stringify(prevConfig.current) !== JSON.stringify(config)) {
      prevConfig.current = config;
      setType(config.type);
      setLabels(config.data.labels);
      setTitle(config.options.plugins.title);
      setSubtitle(config.options.plugins.subtitle);
      setXAxis(config.options.scales.x);
      setYAxis(config.options.scales.y);
      setLegend(config.options.plugins.legend);
      setDatasets(config.data.datasets);
    }
  }, [config]);

  useEffect(() => {
    constructCode();
  }, [
    type,
    datasets,
    title,
    subtitle,
    xAxis,
    yAxis,
    labels
  ]);

  return (
    <div className="onvo-w-full onvo-flex onvo-flex-col onvo-gap-2">

      <div className="onvo-flex onvo-flex-row onvo-items-center onvo-justify-between">
        <Label className="onvo-w-24 onvo-flex-shrink-0">Chart type</Label>
        <Select value={type} onValueChange={setType}>
          <SelectTrigger>
            <SelectValue placeholder="Select" />
          </SelectTrigger>
          <SelectContent>
            {chartTypes.map((item) => (
              <SelectItem key={item.value} value={item.value}>
                {item.label}
              </SelectItem>
            ))}
          </SelectContent>
        </Select>
      </div>
      <div className="onvo-w-full onvo-flex onvo-flex-col onvo-flex-grow onvo-gap-2">
        <div className="onvo-flex onvo-flex-row onvo-items-center onvo-justify-between">
          <Label className="onvo-w-24 onvo-flex-shrink-0">Datasets</Label>

          <Button
            variant="secondary"
            onClick={() =>
              setDatasets([
                ...datasets,
                {
                  title: "Dataset " + (datasets.length + 1),
                  data: "",
                  type: type || "line"
                },
              ])
            }
          >
            Add dataset
          </Button>
        </div>

        {datasets.map((a, idx) => (
          <Card key={"dataset-" + (idx + 1)} className="onvo-flex onvo-flex-col onvo-gap-2">
            <div className="onvo-flex onvo-flex-row onvo-items-center onvo-gap-3">
              <Label className="onvo-flex-shrink-0">
                Column
              </Label>
              <Select value={a.data} onValueChange={val => {
                setDatasets(
                  datasets.map((a, i) => {
                    if (i === idx) {
                      return {
                        ...a,
                        data: val,
                      };
                    }
                    return a;
                  })
                );
              }}>
                <SelectTrigger>
                  <SelectValue placeholder="Select" />
                </SelectTrigger>
                <SelectContent>
                  {columns.map((item) => (
                    <SelectItem key={item} value={`{{data['${item}']}}`}>
                      {item}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>
            <div className="onvo-flex onvo-flex-row onvo-items-center onvo-gap-3">

              <Label className="onvo-flex-grow onvo-flex-shrink-0">
                Title
              </Label>

              <Input
                placeholder="Title"
                value={a.title}
                onChange={(e) => {
                  setDatasets(
                    datasets.map((a, i) => {
                      if (i === idx) {
                        return {
                          ...a,
                          title: e.target.value,
                        };
                      }
                      return a;
                    })
                  );
                }}
              />

              <Label className="onvo-w-24 onvo-flex-shrink-0">Type</Label>
              <Select value={a.type} onValueChange={val => {
                setDatasets(
                  datasets.map((a, i) => {
                    if (i === idx) {
                      return {
                        ...a,
                        type: val,
                      };
                    }
                    return a;
                  })
                );
              }}>
                <SelectTrigger>
                  <SelectValue placeholder="Select" />
                </SelectTrigger>
                <SelectContent>
                  {chartTypes.map((item) => (
                    <SelectItem key={item.value} value={item.value}>
                      {item.label}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>

            </div>
            <div className="onvo-flex onvo-flex-row onvo-items-center onvo-gap-3">
              <Label className="onvo-flex-shrink-0">
                Background
              </Label>
              <Input
                placeholder="#ff1245"
                value={a.backgroundColor}
                onChange={(e) => {
                  setDatasets(
                    datasets.map((a, i) => {
                      if (i === idx) {
                        return {
                          ...a,
                          backgroundColor: e.target.value,
                        };
                      }
                      return a;
                    })
                  );
                }}
              />

              <Label className="onvo-flex-shrink-0">
                Border
              </Label>
              <Input
                placeholder="#ff0000"
                value={a.borderColor}
                onChange={(e) => {
                  setDatasets(
                    datasets.map((a, i) => {
                      if (i === idx) {
                        return {
                          ...a,
                          borderColor: e.target.value,
                        };
                      }
                      return a;
                    })
                  );
                }}
              />
              <Label className="onvo-flex-shrink-0">
                Border width
              </Label>
              <Input
                type="number"
                placeholder="2"
                value={a.borderWidth}
                onChange={(e) => {
                  setDatasets(
                    datasets.map((a, i) => {
                      if (i === idx) {
                        return {
                          ...a,
                          borderWidth: Number(e.target.value),
                        };
                      }
                      return a;
                    })
                  );
                }}
              />
            </div>

            <div className="onvo-flex onvo-flex-row onvo-items-center onvo-justify-end onvo-gap-2">
              <Button
                variant="destructive"
                onClick={() => {
                  setDatasets(datasets.filter((a, i) => i !== idx));
                }}
              >
                Remove datasource
              </Button>
            </div>
          </Card>
        ))}

      </div>

      <div className="onvo-flex onvo-flex-row onvo-items-center onvo-gap-2">
        <Label className="onvo-w-24 onvo-flex-shrink-0">Labels</Label>
        <Select value={labels} onValueChange={val => {
          setLabels(val);
        }}>
          <SelectTrigger>
            <SelectValue placeholder="Select" />
          </SelectTrigger>
          <SelectContent>
            {columns.map((item) => (
              <SelectItem key={item} value={`{{data['${item}']}}`}>
                {item}
              </SelectItem>
            ))}
          </SelectContent>
        </Select>
      </div>
      <Divider />
      <div className="onvo-flex onvo-flex-row onvo-items-center onvo-justify-between">
        <Label>Title</Label>
        <Tabs
          defaultValue="false"
          value={title.display ? "true" : "false"}
          onValueChange={(val) => {
            setTitle(t => ({ ...t, display: val === "true" }))
          }}
        >
          <TabsList variant="solid">
            <TabsTrigger value="true">Visible</TabsTrigger>
            <TabsTrigger value="false">Hidden</TabsTrigger>
          </TabsList>
        </Tabs>
      </div>

      {title.display && (
        <div className="onvo-flex onvo-flex-col onvo-gap-2">
          <div className="onvo-flex onvo-flex-row onvo-items-center onvo-gap-2">
            <Label className="onvo-w-24 onvo-flex-shrink-0">
              Chart title
            </Label>
            <Input
              value={title.text}
              placeholder="Chart title"
              onChange={(e) => setTitle(t => ({ ...t, text: e.target.value }))}
            />
          </div>

          <div className="onvo-flex onvo-flex-row onvo-items-center onvo-gap-2">
            <Label className="onvo-w-24 onvo-flex-shrink-0">
              Position
            </Label>
            <PositionPicker
              value={title.position || "start"}
              onValueChange={val => setTitle(t => ({ ...t, position: val }))}
            />
            <Label className="onvo-w-24 onvo-flex-shrink-0 onvo-text-right">
              Align
            </Label>
            <AlignmentPicker
              value={title.align || "center"}
              onValueChange={val => setTitle(t => ({ ...t, align: val }))}
            />
          </div>
        </div>
      )}

      <Divider />
      <div className="onvo-flex onvo-flex-row onvo-items-center onvo-justify-between">
        <Label>Subtitle</Label>
        <Tabs
          defaultValue="false"
          value={subtitle.display ? "true" : "false"}
          onValueChange={(val) => {
            setSubtitle(t => ({ ...t, display: val === "true" }))
          }}
        >
          <TabsList variant="solid">
            <TabsTrigger value="true">Visible</TabsTrigger>
            <TabsTrigger value="false">Hidden</TabsTrigger>
          </TabsList>
        </Tabs>
      </div>

      {subtitle.display && (
        <div className="onvo-flex onvo-flex-col onvo-gap-2">
          <div className="onvo-flex onvo-flex-row onvo-items-center onvo-gap-2">
            <Label className="onvo-w-24 onvo-flex-shrink-0">
              Chart subtitle
            </Label>
            <Input
              placeholder="Chart subtitle"
              value={subtitle.text}
              onChange={(e) => setSubtitle(t => ({ ...t, text: e.target.value }))}
            />
          </div>

          <div className="onvo-flex onvo-flex-row onvo-items-center onvo-gap-2">
            <Label className="onvo-w-24 onvo-flex-shrink-0">
              Position
            </Label>
            <PositionPicker
              value={subtitle.position || "start"}
              onValueChange={val => setSubtitle(t => ({ ...t, position: val }))}
            />
            <Label className="onvo-w-24 onvo-flex-shrink-0 onvo-text-right">
              Align
            </Label>
            <AlignmentPicker
              value={subtitle.align || "center"}
              onValueChange={val => setSubtitle(t => ({ ...t, align: val }))}
            />
          </div>
        </div>
      )}

      <Divider />

      <div className="onvo-flex onvo-flex-row onvo-items-center onvo-justify-between">
        <Label>Legend</Label>
        <Tabs
          defaultValue="false"
          value={legend.display ? "true" : "false"}
          onValueChange={(val) => {
            setLegend(t => ({ ...t, display: val === "true" }))
          }}
        >
          <TabsList variant="solid">
            <TabsTrigger value="true">Visible</TabsTrigger>
            <TabsTrigger value="false">Hidden</TabsTrigger>
          </TabsList>
        </Tabs>
      </div>

      {legend.display && (
        <div className="onvo-flex onvo-flex-col onvo-gap-2">

          <div className="onvo-flex onvo-flex-row onvo-items-center onvo-gap-2">
            <Label className="onvo-w-24 onvo-flex-shrink-0">
              Position
            </Label>
            <PositionPicker
              value={legend.position || "start"}
              onValueChange={val => setLegend(t => ({ ...t, position: val }))}
            />
            <Label className="onvo-w-24 onvo-flex-shrink-0 onvo-text-right">
              Align
            </Label>
            <AlignmentPicker
              value={legend.align || "center"}
              onValueChange={val => setLegend(t => ({ ...t, align: val }))}
            />
          </div>
        </div>
      )}

      <Divider />
      <div className="onvo-flex onvo-flex-col onvo-gap-2 onvo-mt-2">
        <div className="onvo-flex onvo-flex-row onvo-items-center onvo-gap-2">
          <Label className="onvo-flex-grow onvo-flex-shrink-0">
            Show x axis
          </Label>
          <Switch
            checked={xAxis.display}
            onCheckedChange={(val) => setXAxis(t => ({ ...t, display: val }))}
          />
          {xAxis.display && (
            <div className="onvo-flex onvo-flex-row onvo-items-center onvo-gap-2">
              <Label className="onvo-w-24 onvo-flex-shrink-0">
                X axis title
              </Label>
              <Input
                value={xAxis.text || ""}
                onChange={(e) => setXAxis(t => ({ ...t, text: e.target.value }))}
                placeholder="Date in DD/MM/YYYY format"
              />
            </div>
          )}
        </div>
        <div className="onvo-flex onvo-flex-row onvo-items-center onvo-gap-2">
          <Label className="onvo-flex-grow onvo-flex-shrink-0">
            Show y axis
          </Label>
          <Switch
            checked={yAxis.display}
            onCheckedChange={(val) => setYAxis(t => ({ ...t, display: val }))}
          />
          {yAxis.display && (
            <div className="onvo-flex onvo-flex-row onvo-items-center onvo-gap-2">
              <Label className="onvo-w-24 onvo-flex-shrink-0">
                Y axis title
              </Label>
              <Input
                value={yAxis.text}
                onChange={(e) => setYAxis(t => ({ ...t, text: e.target.value }))}
                placeholder="No of users"
              />
            </div>
          )}
        </div>

      </div>
    </div>
  );
};
