<script setup>
import { ref, onMounted} from 'vue';
import { createProduct,getProducts,modifyProduct,deleteProduct,getWarehouses } from '../api.js';
import { useToast } from 'primevue/usetoast';
import { DateTime } from 'luxon';

import InputText from 'primevue/inputtext';
import Button from 'primevue/button';
import PMessage from 'primevue/message';
import InputNumber from 'primevue/inputnumber';
import InputGroup from 'primevue/inputgroup';
import InputGroupAddon from 'primevue/inputgroupaddon';
import Checkbox from 'primevue/checkbox';
import DataTable from 'primevue/datatable';
import Column from 'primevue/column';
import Tag from 'primevue/tag';
import Badge from 'primevue/badge';
import FileUpload from 'primevue/fileupload';
import MultiSelect from 'primevue/multiselect';

const toast = useToast();
const formatDate = (date) => DateTime.fromISO(date).toLocaleString(DateTime.DATETIME_MED);

const products = ref([]);

const productName = ref('');
const productReference = ref('');
const productDescription = ref('');
const productQuantity = ref(0);
const productAlert = ref(false);
const productStockLimit = ref(null);
const base64Image = ref(null);
const selectedWarehouses = ref([]);

const registerErrors = ref({});
const modifyErrors =  ref({});
const editingRows = ref([]);
const warehouses = ref([]);

async function create_product() {
  if (productAlert.value && !productStockLimit.value) {
    registerErrors.value.stock_limit = 'Veuillez renseigner une limite de stock.';
    return;
  }
  registerErrors.value = {};
  try {
    await createProduct({
      name: productName.value,
      reference: productReference.value,
      description: productDescription.value,
      quantity: productQuantity.value,
      alert_enabled: productAlert.value,
      stock_limit: productStockLimit.value,
      image: base64Image.value,
      warehouses: selectedWarehouses.value.map((warehouse) => warehouse.id),
    });
    warehouses.value = await getWarehouses();
    products.value = await getProducts();
    products.value = enrichProducts();
    resetForms();
    toast.add({ severity: 'success', life: 2500, summary:`${productName.value} crée`});
} catch (error){
    if (error.response && error.response.data) {
      const data = error.response.data;
      if (data.detail) {
        toast.add({ severity: 'error',life: 2500, summary: 'Erreur', detail: data.detail });
      }
      registerErrors.value = {
        name: data.name ? data.name[0] : "",
        description: data.description ? data.description[0]: "",
        reference: data.reference ? data.reference[0]: "",
        quantity: data.quantity ? data.quantity[0] : "",
        alert_enabled: data.alert_enabled ? data.alert_enabled[0] : "",
        stock_limit: data.stock_limit ? data.stock_limit[0] : "",
        image: data.image ? data.image[0] : "",
        warehouses: data.warehouses ? data.warehouses[0] : "",
      }
    } else {
      toast.add({ severity: 'error',life: 2500, summary: 'Erreur', detail: 'Une erreur est survenue.' });
    }
  }
}

function resetForms() {
  productName.value = '';
  productDescription.value = '';
  productReference.value = '';
  productQuantity.value = 0;
  productAlert.value = false;
  productStockLimit.value = null;
  base64Image.value = null;
  selectedWarehouses.value = [];
};

async function onRowEditSave(event) {
  if (event && event.data) {
    let {newData, index} = event;
    products.value[index] = newData;

    if (!newData.id) {
      console.error("No id found in edited row.");
      toast.add({ severity: 'error', life: 2500, summary: 'Error', detail: 'Aucune donnée n\'a été modifiée.' });
      return;
    }
    modifyErrors.value[newData.id] = {};
    try {
      await modifyProduct({
        id: newData.id,
        name: newData.name,
        reference: newData.reference,
        description: newData.description,
        quantity: newData.quantity,
        image: base64Image.value,
        warehouses: newData.warehouse.map((warehouse) => warehouse.id),
      },
      newData.id);
      warehouses.value = await getWarehouses();
      products.value = await getProducts();
      products.value = enrichProducts();
      resetForms();
      toast.add({ severity: 'success', life: 2500, summary: 'Succès', detail: 'Produit modifié.' });
  } catch (error) {
      if (error.response && error.response.data) {
        const data = error.response.data;
        if (data.detail) {
          toast.add({ severity: 'error',life: 2500, summary: 'Erreur', detail: data.detail });
        }
        modifyErrors.value[newData.id] = {
          name: data.name ? data.name[0] : "",
          description: data.description ? data.description[0]: "",
          reference: data.reference ? data.reference[0]: "",
          quantity: data.quantity ? data.quantity[0] : "",
          alert_enabled: data.alert_enabled ? data.alert_enabled[0] : "",
          stock_limit: data.stock_limit ? data.stock_limit[0] : "",
          image: data.image ? data.image[0] : "",
          warehouses: data.warehouses ? data.warehouses[0] : "",
        };
      } else {
        toast.add({ severity: 'error', life: 2500, summary: 'Erreur', detail: 'Une erreur est survenue.' });
      }
    }
  }
}
function onRowEditInit(event) {
  const { data } = event;
  data.warehouse = data.warehouses.map(warehouse => ({ ...warehouse }));
}

async function removeProduct(id) {
  try {
    await deleteProduct(id);
    editingRows.value = [];
    warehouses.value = await getWarehouses();
    products.value = await getProducts();
    products.value = enrichProducts();
    toast.add({ severity: 'success', life: 2500, summary: 'Succès', detail: 'Produit supprimé.' });
  } catch (error) {
    if (error.response && error.response.data) {
      const data = error.response.data;
      if (data.detail) {
        toast.add({ severity: 'error', life: 2500, summary: 'Erreur', detail: data.detail });
      }
    } else {
      toast.add({ severity: 'error', life: 2500, summary: 'Erreur', detail: 'Une erreur est survenue.' });
    }
  }
};
const enrichProducts = () => {
   return products.value.map((product) => {
    const attachedWarehouses = warehouses.value.filter((warehouse) =>
      product.warehouses.includes(warehouse.id)
    );

    return {
      ...product,
      warehouses: attachedWarehouses
    };
  });
};


const stockSeverity = (data) => {
  if (!data) return 'info';
  
  const quantity = data.quantity;
  
  if (quantity <= 5) {
    return 'danger';
  } else if (quantity > 5 && quantity <= 20) {
    return 'success';
  } else {
    return 'warning';
  }
};

const truncate = (text, length) => {
  if (text.length > length) {
    return text.substring(0, length) + '...';
  }
  return text;
};
const handleFileUpload = (event) => {
  const file = event.files[0];
  if (!file) return;
  const reader = new FileReader();
  reader.onload = () => {
    base64Image.value = reader.result;
    toast.add({ severity: 'success', life: 2500, summary: 'Image ajouté avec succès.' });
  };
  reader.onerror = () => {
    toast.add({ severity: 'error', life: 2500, summary: 'Erreur', detail: 'Impossible de lire le fichier.' });
  };
  reader.readAsDataURL(file);
};

onMounted(async () => {
try {
  warehouses.value = await getWarehouses();
  products.value = await getProducts();
  products.value = enrichProducts();
  products.value.forEach((product) => {
  product.creation_date = formatDate(product.creation_date);
  product.modification_date = formatDate(product.modification_date);
  });
} catch (error){
  if (error.response && error.response.data) {
    const data = error.response.data;
    if (data.detail) {
      toast.add({ severity: 'error',life: 2500, summary: 'Erreur', detail: data.detail });
    }
  } else {
    toast.add({ severity: 'error',life: 2500, summary: 'Erreur', detail: 'Une erreur est survenue.' });
  }
}
});
</script>

<template>
  <div>
    <h2>Tableau de bord</h2>
    <div class="register form-container">
      <h2>Créer un produit</h2>
      <form @submit.prevent="create_product">
        <div class="form">
          <InputGroup>
            <InputGroupAddon>Nom :</InputGroupAddon>
            <InputText
              type="text"
              id="register-product"
              v-model="productName"
              required
            />
          </InputGroup>
          <p-message
            v-if="registerErrors.name"
            severity="error"
          >
            {{ registerErrors.name }}
          </p-message>
        </div>
        
        <div class="form">
          <InputGroup>
            <InputGroupAddon>Reference :</InputGroupAddon>
            <InputText
              type="text"
              id="register-reference"
              v-model="productReference"
            />
          </InputGroup>
          <p-message
            v-if="registerErrors.description"
            severity="error"
          >
            {{ registerErrors.description }}
          </p-message>
        </div>

        <div class="form">
          <InputGroup>
            <InputGroupAddon>Description :</InputGroupAddon>
            <InputText
              type="text"
              id="register-description"
              v-model="productDescription"
            />
          </InputGroup>
          <p-message
            v-if="registerErrors.description"
            severity="error"
          >
            {{ registerErrors.description }}
          </p-message>
        </div>

        <div class="form">
          <InputGroup>
            <InputGroupAddon>Quantité :</InputGroupAddon>
            <InputNumber
              id="register-quantity"
              inputId="integeronly"
              v-model="productQuantity"
              fluid
              required
            />
          </InputGroup>
        </div>

        <div class="form">
          <InputGroup>
            <InputGroupAddon>
              Activer une alerte ?
              <Checkbox
                :binary="true"
                id="register-alert"
                v-model="productAlert"
              />
            </InputGroupAddon>
            <InputNumber
              v-if="productAlert"
              id="register-stock-limit"
              inputId="integeronly"
              v-model="productStockLimit"
              fluid
            />
          </InputGroup>
        </div>
          <div class="form">
            <InputGroup >
              <InputGroupAddon>Image :</InputGroupAddon>
              <FileUpload
              name="productImage"
              accept="image/*" 
              mode="basic"
              customUpload
              :auto="true"
              :multiple="false"
              :maxFileSize="1000000"
              :chooseLabel="'Choisir une image'"
              @uploader="handleFileUpload" 
              />
            </InputGroup>
        </div>
        <div class="form">
          <InputGroup>
              <InputGroupAddon>Entrepôt :</InputGroupAddon>
              <MultiSelect
                v-model="selectedWarehouses"
                :options="warehouses"
                optionLabel="name"
                placeholder="Sélectionner un entrepôt"
                display="chip"
                :invalid="!!registerErrors.warehouses"
                ></MultiSelect>
          </InputGroup>
        </div>
        <div class="alert">
          <p-message
            v-if="registerErrors.alert_enabled"
            severity="error">
            {{ registerErrors.alert_enabled }}
          </p-message>
          <p-message
            v-if="registerErrors.stock_limit"
            severity="error">
            {{ registerErrors.stock_limit }}
          </p-message>
          <p-message
            v-if="registerErrors.image"
            severity="error">
            {{ registerErrors.image }}
          </p-message>
          <p-message
            v-if="registerErrors.warehouses"
            severity="error">
            {{ registerErrors.warehouses }}
          </p-message>
          <p-message
            v-if="registerErrors.quantity"
            severity="error"
          >
            {{ registerErrors.quantity }}
          </p-message>
          <p-message
            v-if="registerErrors.reference"
            severity="error"
          >
            {{ registerErrors.reference }}
          </p-message>
        </div>
        <Button
          label="Créer"
          type="submit"
          class="p-button-primary"
        />
      </form>
    </div>

    <DataTable
      v-model:editingRows="editingRows"
      editMode="row"
      dataKey="id"
      @row-edit-save="onRowEditSave"
      @row-edit-init="onRowEditInit"
      :value="products"
      tableStyle="min-width: 50rem"
      removableSort
    >
      <template #header>
        <div class="text-end pb-4">
          <Button
            icon="pi pi-external-link"
            label="Export"
            @click="exportCSV($event)"
          />
        </div>
      </template>

      <Column field="image"editor="true">
        <template #body="slotProps">
          <img
            :src="slotProps.data.image"
            style="width: 6rem"
          />
        </template>
        <template #editor>
          <FileUpload
          name="editProductImage"
          accept="image/*"
          mode="basic"
          customUpload
          :auto="true"
          :multiple="false"
          :maxFileSize="1000000"
          :chooseLabel='"modifier image"'
          @uploader="handleFileUpload"
          >
        </FileUpload>
        </template>
      </Column>

      <Column field="is_stock_low" header="Stock" sortable>
        <template #body="slotProps">
          <Tag
            :severity="slotProps.data.is_stock_low
              ? 'danger'
              : 'success'"
            :value="slotProps.data.is_stock_low
              ? 'LOWSTOCK'
              : 'INSTOCK'"
          />
        </template>
      </Column>

      <Column field="name" header="Name" editor="true" sortable>
        <template #body="slotProps">
          <span v-if="!modifyErrors[slotProps.data.id]?.name">{{ slotProps.data.name }}</span>
          <p-message v-if="modifyErrors[slotProps.data.id]?.name" severity="error">{{ modifyErrors[slotProps.data.id].name }}</p-message>
        </template>
        <template #editor="slotProps">
          <InputText v-model="slotProps.data.name" fluid />
        </template>
      </Column>

      <Column field="reference" header="reference" editor="true" sortable>
        <template #body="slotProps">
          <span v-if="!modifyErrors[slotProps.data.id]?.reference">{{ slotProps.data.reference }}</span>
          <p-message v-if="modifyErrors[slotProps.data.id]?.reference" severity="error">{{ modifyErrors[slotProps.data.id].reference }}</p-message>
        </template>
        <template #editor="slotProps">
          <InputText v-model="slotProps.data.reference" fluid />
        </template>
      </Column>


      <Column field="description" header="Description" editor="true">
        <template #body="slotProps">
          <span v-if="!modifyErrors[slotProps.data.id]?.description" :title="slotProps.data.description">
            {{ truncate(slotProps.data.description, 50) }}
          </span>
          <p-message v-if="modifyErrors[slotProps.data.id]?.description" severity="error">{{ modifyErrors[slotProps.data.id].description }}</p-message>
        </template>
        <template #editor="slotProps">
          <InputText v-model="slotProps.data.description" fluid />
        </template>
      </Column>

      <Column field="quantity" header="Quantity" editor="true" sortable>
        <template #body="slotProps">
          <Badge v-if="!modifyErrors[slotProps.data.id]?.quantity"
            :value="slotProps.data.quantity"
            :severity="stockSeverity(slotProps.data)"
          />
          <p-message v-if="modifyErrors[slotProps.data.id]?.quantity" severity="error">{{ modifyErrors[slotProps.data.id].quantity }}</p-message>
        </template>
        <template #editor="slotProps">
          <InputNumber v-model="slotProps.data.quantity" fluid />
        </template>
      </Column>
      <Column header="Entrepôt" editor="true" sortable> 
        <template #body="slotProps">
          <span v-if="!modifyErrors[slotProps.data.id]?.warehouses" v-for="warehouse in slotProps.data.warehouses" :key="warehouse.id">
            {{ warehouse.name }}({{ warehouse.actual_capacity }}/{{ warehouse.max_capacity }}),
          </span>
          <p-message v-if="modifyErrors[slotProps.data.id]?.warehouses" severity="error">{{ modifyErrors[slotProps.data.id].warehouses }}</p-message>
        </template>
        <template #editor="slotProps">
          <MultiSelect
            v-model="slotProps.data.warehouse"
            :options="warehouses"
            optionLabel="name"
            placeholder="Sélectionner un entrepôt"
            :invalid="!!modifyErrors[slotProps.data.id]?.warehouses"
          ></MultiSelect>
        </template>
      </Column>

      <Column editor="true">
        <template #editor="slotProps">
          <Button
            icon="pi pi-times"
            class="p-button-rounded p-button-danger"
            @click="removeProduct(slotProps.data.id)"
          />
        </template>
      </Column>
      <Column
        :rowEditor="true"
        style="width: 10%; min-width: 8rem"
        bodyStyle="text-align:center"
      />
    </DataTable>
  </div>
</template>
