<template>
  <div>
    <label v-if="caption">{{ caption }}</label>
    <div class="report-definition">
      <!-- Form for Report Name -->
      <div class="report-form-group">
        <input-text v-model="report.name" :caption="labels.name" :placeholder="labels.namePlaceholder"></input-text>
      </div>
      <!-- Form for Report Description -->
      <div class="report-form-group">
        <input-textarea v-model="report.description" :caption="labels.description" :placeholder="labels.descriptionPlaceholder"></input-textarea>
      </div>
      <!-- Form for Report Filter -->
      <div class="report-form-group" v-if="filters.length">
        <input-select extra_class="form-select" :caption="labels.filter" :options="transformToSelectOptions(filters)" v-model="report.filter.id"></input-select>
      </div>
      <!-- Form for Report Type -->
      <div class="report-form-group">
        <input-select extra_class="form-select" :caption="labels.type" :options="transformToSelectOptions(reportTypes)" v-model="report.type.id"></input-select>
      </div>
      <!-- Form for Axis X Selection -->
      <div class="report-form-group">
        <input-select extra_class="form-select" :caption="labels.axisX" :options="axisOptionsX" v-model="report.x.axis.id"></input-select>
      </div>
      <!-- Form for Axis Y Selection -->
      <div class="report-form-group" v-for="(yAxis, index) in report.y" :key="index">
        <div class="flex-container">
          <!-- Axis Y Select -->
          <input-select extra_class="form-select" :caption="`${labels.axisY} ${index + 1}`" :options="axisOptionsY(index)" v-model="yAxis.axis.id"></input-select>
          
          <!-- Aggregate Function Select -->
          <input-select extra_class="form-select" class="aggregate-select" :caption="labels.aggregate" :options="aggregates" v-model="yAxis.aggregate"></input-select>
          
          <!-- Remove Y Axis Button -->
          <div v-if="report.y.length > 1" @click="removeYAxis(index)" class="icon-button"><span class="mdi mdi-delete-variant"></span></div>
        </div>
      </div>
      <!-- Add Y Axis Button -->
      <div :class="showDateRange ? 'report-form-group': ''">
        <button @click="addYAxis" class="btn btn-secondary custom-add-button">{{ labels.addYAxisButton }}</button>
      </div>
      
      <!-- Date Range Selection -->
      <div class="report-form-group mb-0" v-if="showDateRange && report.dateRange">
        <div class="date-range-container">
          <div class="date-input">
            <input-date v-model="report.dateRange.start" :caption="labels.dateRangeStart" placeholder="YYYY-MM-DD" :use-timestamp="true" :maxDate="report.dateRange.end ? formatTimestampToDate(report.dateRange.end) : ''" />
          </div>
          <div class="date-input">
            <input-date v-model="report.dateRange.end" :caption="labels.dateRangeEnd" placeholder="YYYY-MM-DD" :use-timestamp="true" :minDate="report.dateRange.start ? formatTimestampToDate(report.dateRange.start) : ''" />
          </div>
        </div>
      </div>
      
      <!-- Save Button -->
      <button type="button" class="btn btn-primary custom-save-button" @click="saveReport">{{ labels.saveButton }}</button>
    </div>
    <small class="form-text text-muted" v-if="description">
      {{ description }}
    </small>
  </div>
</template>

<script lang="ts">
import { defineComponent } from 'vue'
import { ReportDefinition, AxisDefinition, ReportType, AxisAggregate, AxisY, ReportFilter, DateRange } from './types';
import { inputSelect, inputText, inputTextarea } from '@/index';
import inputDate from '../../basic/Date.vue'
import { formatTimestampToDate } from '../../../tools/util'

export default defineComponent({
  name: 'ReportDefinition',
  props: {
    caption: {
      type: String,
    },
    description: {
      type: String,
    },
    axisOptions: {
      type: Array as () => AxisDefinition[],
      required: true,
      default: [],
    },
    reportTypes: {
      type: Array as () => ReportType[],
      required: true,
      default: [],
    },
    filters: {
      type: Array as () => ReportFilter[],
      required: false,
      default: [],
    },
    labels: {
      type: Object,
      default: () => ({
        name: 'Report Name',
        namePlaceholder: 'Enter report name',
        description: 'Report Description',
        filter: 'Report Filter',
        descriptionPlaceholder: 'Enter report description',
        type: 'Report Type',
        axisX: 'Axis - X',
        axisY: 'Axis - Y',
        aggregate: 'Aggregate Data',
        select: 'Select',
        saveButton: 'Save',
        addYAxisButton: 'Add Y Axis',
        dateRangeStart: 'Reporting Period Start Date',
        dateRangeEnd: 'Reporting Period End Date',
      }),
    },
    reportInitialData: {
      type: Object as () => ReportDefinition,
      required: false,
    },
    aggregateOptions:  {
      type: Array as () => AxisAggregate[],
      required: false,
    },
    showDateRange: {
      type: Boolean,
      default: true,
    },
  },
  components: {
    inputSelect,
    inputText,
    inputTextarea,
    inputDate
  },
  data() {
    return {
      report: {
        name: '',
        description: '',
        type: { id: '', name: '' },
        filter: { id: '', name: '' },
        x: { axis: { id: '', name: '', path: '', type: '' } },
        y: [{ axis: { id: '', name: '', path: '', type: 'number' }, aggregate: AxisAggregate.Select }],
        dateRange: { start: null, end: null },
      } as ReportDefinition,
    };
  },
  created() {
    if (this.reportInitialData) {
      Object.assign(this.report, this.reportInitialData);
    }
  },
  methods: {
    formatTimestampToDate(timestamp: number | null) {
      return formatTimestampToDate(timestamp);
    },
    saveReport() {
      if (!this.showDateRange && this.report.dateRange) {
        delete this.report.dateRange;
      }
      this.$emit('change', this.report);
      this.$emit('input', this.report);
    },
    transformToSelectOptions(optionsArray: any[]) {
      return optionsArray.map((option: { name: any; id: any; }) => ({
        name: option.name,
        value: option.id,
      }));
    },
    addYAxis() {
      this.report.y.push({ axis: { id: '-1', name: '', path: '', type: 'number' }, aggregate: AxisAggregate.Select });
    },
    removeYAxis(index: number) {
      this.report.y.splice(index, 1);
    },
  },
  watch: {
    'report.name'() {
      this.$emit('change', this.report);
    },
    'report.description'() {
      this.$emit('change', this.report);
    },
    'report.type.id'(newTypeId) {
      const selectedType = this.reportTypes.find(type => type.id === newTypeId);
      if (selectedType) {
        this.report.type.name = selectedType.name;
      }
      this.$emit('change', this.report);
    },
    'report.filter.id'(newFilterId) {
      const selectedFilter = this.filters.find(filter => filter.id === newFilterId);
      if (selectedFilter) {
        this.report.filter.name = selectedFilter.name;
      }
      this.$emit('change', this.report);
    },
    'report.x.axis.id'(newAxisId) {
      const selectedAxis = this.axisOptions.find(axis => axis.id === newAxisId);
      if (selectedAxis) {
        this.report.x.axis.name = selectedAxis.name;
        this.report.x.axis.path = selectedAxis.path;
        this.report.x.axis.type = selectedAxis.type;
      }
      this.$emit('change', this.report);
    },
    'report.y': {
      deep: true,
      handler(newYAxes) {
        newYAxes.forEach((yAxis: AxisY, index: number) => {
          const selectedAxis = this.axisOptions.find(axis => axis.id === yAxis.axis.id);
          if (selectedAxis) {
            this.report.y[index].axis.name = selectedAxis.name;
            this.report.y[index].axis.path = selectedAxis.path;
            this.report.y[index].axis.type = selectedAxis.type;
          }
        });
        this.$emit('change', this.report);
      },
    },
    'report.dateRange': {
      deep: true,
      handler() {
        this.$emit('change', this.report);
      },
    },
  },

  computed: {
    axisOptionsX() {
      return this.axisOptions.map(option => ({
        name: option.name,
        value: option.id,
        // Disable option if it's selected in any Y axis or as the current X axis
        disabled: this.report.y.some(yAxis => yAxis.axis.id === option.id) || option.id === this.report.x.axis.id,
      }));
    },
    axisOptionsY() {
      return (index: number) => {
        return this.axisOptions
          .filter(option => option.type === 'number') // doar cele de tip number!
          .map(option => ({
            name: option.name,
            value: option.id,
            disabled: this.report.y.some((yAxis, yAxisIndex) => yAxisIndex !== index && yAxis.axis.id === option.id) || option.id === this.report.x.axis.id,
          }));
      };
    },
    aggregates() {
      return this.aggregateOptions ? this.aggregateOptions :  Object.entries(AxisAggregate).map(([key, value]) => ({
        id: value,
        value: key,
      }));
    }
  },
});
</script>

<style scoped>
.report-form-group {
  margin-bottom: 1rem;
}
.report-form-check {
  padding-left: 0;
}
.report-form-check-input {
  margin: 0;
  margin-top: 0.2rem;
}
.report-form-check-label {
  margin: 0;
  margin-left: 1rem;
}
.custom-save-button {
  width: 100%;
  margin-top: 2rem;
}
.custom-add-button {
  width: 100%;
  margin-top: 0.2rem;
}
.flex-container {
  display: flex;
  align-items: end;
  justify-content: space-between;
}
.flex-container > *:first-child {
  flex-grow: 1;
}
.form-group {
  margin-bottom: 0;
}
.icon-button {
  cursor: pointer;
  font-size: 24px; 
  margin-left: 1rem;
  opacity: 0.8;
}
.icon-button:hover {
  opacity: 1;
}

.full-width {
  width: 100%;
}
.aggregate-select {
  margin-left: 1rem;
}
.date-range-container {
  display: flex;
  gap: 1rem;
}
.date-input {
  flex: 1;
}
</style>