import { defineStore } from 'pinia';
import { api } from 'src/boot/axios';

import axios from 'axios';

import { Pagination } from 'stores/types';

import {
  ProductGroup,
  ProductGroupCreate,
  ProductGroupUpdate,
  ProductList,
  ProductCreate,
  ProductUpdate,
  Service,
  ServiceCreate,
  ServiceById,
  Work,
  ProductOnWork,
  WorkCreate,
} from './types';
import { ref } from 'vue';
import useFlowStore from '../flow';

const useProductServiceStore = defineStore('api-product-service', () => {
  const flowStore = useFlowStore();

  const workNameItems = ref<
    {
      id: string;
      name: string;
      isEdit: boolean;
    }[]
  >([]);

  // Product Group

  async function fetchStatsProductGroup() {
    const res = await api.get('/product-group/stats');

    if (!res) return false;

    if (res.status === 200) {
      return res.data;
    }
  }

  async function fetchListProductServiceById(groupId: string) {
    const res = await api.get<ProductGroup>(`/product-group/${groupId}`);

    if (!res) return false;

    if (res.status === 200) {
      return res.data;
    }
  }

  async function fetchListProductService(opts?: {
    page?: number;
    pageSize?: number;
    query?: string;
    status?: 'CREATED' | 'ACTIVE' | 'INACTIVE';
  }) {
    const params = new URLSearchParams();

    for (const [k, v] of Object.entries(opts || {})) {
      v !== undefined && params.append(k, v.toString());
    }

    const query = params.toString();

    const res = await api.get<Pagination<ProductGroup[]>>(
      `/product-group${(params && '?'.concat(query)) || ''}`,
      {
        headers: {
          'X-Rtid': flowStore.rtid,
        },
      },
    );

    if (!res) return false;
    if (res.status === 200) {
      return res.data;
    }

    return false;
  }

  async function createProductService(data: ProductGroupCreate) {
    const { code, ...payload } = data;

    const res = await api.post<ProductGroupCreate>('/product-group', {
      ...payload,
    });

    if (!res) return false;

    if (res.status === 201) {
      return res.data;
    }

    return false;
  }

  async function editProductService(
    groupId: string,
    data: Partial<ProductGroupUpdate>,
  ) {
    const { code, ...payload } = data;

    const res = await api.put<ProductGroupUpdate>(`/product-group/${groupId}`, {
      ...payload,
    });

    if (!res) return false;

    if (res.status === 200) {
      return res.data;
    }

    return false;
  }

  async function deleteProductService(groupId: string) {
    const res = await api.delete(`/product-group/${groupId}`);

    if (!res) return false;

    if (res.status === 200) {
      return res.data;
    }

    return false;
  }

  // Product

  async function fetchStatsProduct(opts?: { productGroupId?: string }) {
    const params = new URLSearchParams();

    for (const [k, v] of Object.entries(opts || {})) {
      v !== undefined && params.append(k, v.toString());
    }

    const query = params.toString();

    const res = await api.get(
      `/product/stats${(params && '?'.concat(query)) || ''}`,
    );

    if (!res) return false;

    if (res.status === 200) {
      return res.data;
    }
  }

  async function fetchListProduct(opts?: {
    query?: string;
    page?: number;
    pageSize?: number;
    productGroupId?: string;
    status?: string;
  }) {
    const params = new URLSearchParams();

    for (const [k, v] of Object.entries(opts || {})) {
      v !== undefined && params.append(k, v.toString());
    }

    const query = params.toString();

    const res = await api.get<Pagination<ProductList[]>>(
      `/product${(params && '?'.concat(query)) || ''}`,
      {
        headers: { 'X-Rtid': flowStore.rtid },
      },
    );

    if (!res) return false;
    if (res.status === 200) {
      return res.data;
    }

    return false;
  }

  async function createProduct(
    data: ProductCreate,
    imgList: {
      selectedImage: string;
      list: { url: string; imgFile: File | null; name: string }[];
    },
  ) {
    const { image, status, ...payload } = data;

    const res = await api.post<ProductCreate>('/product', {
      ...payload,
      selectedImage: imgList.selectedImage || '',
    });

    if (imgList.list.length > 0 && res.data.id) {
      for (let index = 0; index < imgList.list.length; index++) {
        const imgFile = imgList.list[index].imgFile;
        if (imgFile)
          await addImageList(
            imgFile,
            res.data.id,
            imgList.list[index].name,
            'product',
          );
      }
    }

    if (!res) return false;

    if (res.status === 201) {
      return res.data;
    }

    return false;
  }

  async function fetchListProductById(productId: string) {
    const res = await api.get<ProductList>(`/product/${productId}`);

    if (!res) return false;

    if (res.status === 200) {
      return res.data;
    }
  }

  async function editProduct(
    productId: string,
    data: Partial<ProductCreate & { status: string }>,
  ) {
    const { image, code, ...payload } = data;

    const res = await api.put<ProductCreate & { imageUploadUrl: string }>(
      `/product/${productId}`,
      {
        ...payload,
      },
    );

    if (res.status === 200) {
      return res.data;
    }

    return false;
  }

  async function deleteProduct(productId: string) {
    const res = await api.delete(`/product/${productId}`);

    if (!res) return false;

    if (res.status === 200) {
      return res.data;
    }

    return false;
  }

  // Service
  async function fetchStatsService(opts?: { productGroupId?: string }) {
    const params = new URLSearchParams();

    for (const [k, v] of Object.entries(opts || {})) {
      v !== undefined && params.append(k, v.toString());
    }

    const query = params.toString();

    const res = await api.get(
      `/service/stats${(params && '?'.concat(query)) || ''}`,
    );

    if (!res) return false;

    if (res.status === 200) {
      return res.data;
    }
  }

  async function fetchListService(opts?: {
    query?: string;
    page?: number;
    pageSize?: number;
    productGroupId?: string;
    status?: string;
    fullDetail?: boolean;
  }) {
    const params = new URLSearchParams();

    for (const [k, v] of Object.entries(opts || {})) {
      v !== undefined && params.append(k, v.toString());
    }

    const query = params.toString();

    const res = await api.get<Pagination<Service[]>>(
      `/service${(params && '?'.concat(query)) || ''}`,
      {
        headers: {
          'X-Rtid': flowStore.rtid,
        },
      },
    );

    if (!res) return false;
    if (res.status === 200) {
      return res.data;
    }

    return false;
  }

  async function createService(
    data: ServiceCreate,
    imgList: {
      selectedImage: string;
      list: { url: string; imgFile: File | null; name: string }[];
    },
  ) {
    const { image, status, ...payload } = data;

    const res = await api.post<ServiceCreate & { imageUploadUrl: string }>(
      '/service',
      {
        ...payload,
        selectedImage: imgList.selectedImage || '',
      },
    );

    if (imgList.list.length > 0 && res.data.id) {
      for (let index = 0; index < imgList.list.length; index++) {
        const imgFile = imgList.list[index].imgFile;
        if (imgFile)
          await addImageList(
            imgFile,
            res.data.id,
            imgList.list[index].name,
            'service',
          );
      }
    }

    if (!res) return false;

    if (res.status === 201) {
      return res.data;
    }

    return false;
  }

  async function fetchListServiceByIdWork(
    serviceId: string,
    opts?: { query?: string; page?: number; pageSize?: number },
  ) {
    const params = new URLSearchParams();

    for (const [k, v] of Object.entries(opts || {})) {
      v !== undefined && params.append(k, v.toString());
    }

    const query = params.toString();

    const res = await api.get<Pagination<ServiceById[]>>(
      `/service/${serviceId}/work${(params && '?'.concat(query)) || ''}`,
      {
        headers: {
          'X-Rtid': flowStore.rtid,
        },
      },
    );

    if (!res) return false;
    if (res.status === 200) {
      return res.data;
    }

    return false;
  }

  async function fetchListServiceById(serviceId: string) {
    const res = await api.get<ServiceById>(`/service/${serviceId}`);

    if (!res) return false;

    if (res.status === 200) {
      return res.data;
    }
  }

  async function editService(
    serviceId: string,
    data: Partial<ServiceCreate & { status: string }>,
  ) {
    const { image, code, productGroupId, ...payload } = data;

    if (payload.status === 'CREATED') {
      delete payload.status;
    }

    const res = await api.put<ServiceCreate & { imageUploadUrl: string }>(
      `/service/${serviceId}`,
      {
        ...payload,
      },
    );

    if (!res) return false;

    if (res.status === 200) {
      return res.data;
    }

    return false;
  }

  async function deleteService(serviceId: string) {
    const res = await api.delete(`/service/${serviceId}`);

    if (!res) return false;

    if (res.status === 200) {
      return res.data;
    }

    return false;
  }

  // work
  async function fetchListWork(opts?: {
    query?: string;
    page?: number;
    pageSize?: number;
    baseOnly?: boolean;
  }) {
    const params = new URLSearchParams();

    for (const [k, v] of Object.entries(opts || {})) {
      v !== undefined && params.append(k, v.toString());
    }

    const query = params.toString();

    const res = await api.get<
      Pagination<(Work & { productOnWork: ProductOnWork[] })[]>
    >(`/work${(params && '?'.concat(query)) || ''}`, {
      headers: {
        'X-Rtid': flowStore.rtid,
      },
    });

    if (!res) return false;
    if (res.status === 200) {
      return res.data;
    }

    return false;
  }

  async function createWork(data: Partial<WorkCreate>) {
    const { ...payload } = data;

    const res = await api.post<WorkCreate>('/work', {
      ...payload,
    });

    if (!res) return false;

    if (res.status === 201) {
      await fetchListOfWork();
      return res.data;
    }

    return false;
  }

  async function fetchListWorkById(workId: string) {
    const res = await api.get<Work>(`/work/${workId}`);

    if (!res) return false;

    if (res.status === 200) {
      return res.data;
    }
  }

  async function editWork(
    workId: string,
    data: Partial<WorkCreate & { status: string }>,
  ) {
    const { ...payload } = data;

    const res = await api.put<WorkCreate>(`/work/${workId}`, {
      ...payload,
    });

    if (res.status === 200) {
      await fetchListOfWork();
      return res.data;
    }

    return false;
  }

  async function deleteWork(workId: string) {
    const res = await api.delete(`/work/${workId}`);

    if (!res) return false;

    if (res.status === 200) {
      await fetchListOfWork();
      return res.data;
    }

    return false;
  }

  async function fetchListProductByIdWork(
    workId: string,
    opts?: { query?: string; page?: number; pageSize?: number },
  ) {
    const params = new URLSearchParams();

    for (const [k, v] of Object.entries(opts || {})) {
      v !== undefined && params.append(k, v.toString());
    }

    const query = params.toString();

    const res = await api.get<Pagination<ProductList[]>>(
      `/work/${workId}/product${(params && '?'.concat(query)) || ''}`,
      {
        headers: {
          'X-Rtid': flowStore.rtid,
        },
      },
    );

    if (!res) return false;
    if (res.status === 200) {
      return res.data;
    }

    return false;
  }

  async function fetchListOfWork() {
    const res = await fetchListWork({ baseOnly: true });

    if (res) {
      workNameItems.value = res.result.map((item) => {
        return { id: item.id, name: item.name, isEdit: false };
      });
    }
  }

  async function fetchImageListById(
    id: string,
    type: 'product' | 'service',
    flow?: {
      sessionId?: string;
      refTransactionId?: string;
      transactionId?: string;
    },
  ) {
    const res = await api.get(`/${type}/${id}/image`, {
      headers: {
        'X-Session-Id': flow?.sessionId,
        'X-Rtid': flow?.refTransactionId || flowStore.rtid,
        'X-Tid': flow?.transactionId,
      },
    });

    if (!res) return false;
    if (res.status === 200) return res.data;
    if (res.status === 204) return null;

    return false;
  }

  async function addImageList(
    file: File,
    id: string,
    name: string,
    type: 'product' | 'service',
  ) {
    await api
      .put(`/${type}/${id}/image/${name}`, file, {
        headers: { 'Content-Type': file.type },
        onUploadProgress: (e) => console.log(e),
      })
      .catch((e) => console.error(e));

    return name;
  }

  async function deleteImageByName(
    id: string,
    name: string,
    type: 'product' | 'service',
    flow?: {
      sessionId?: string;
      refTransactionId?: string;
      transactionId?: string;
    },
  ) {
    const res = await api.delete(`/${type}/${id}/image/${name}`, {
      headers: {
        'X-Session-Id': flow?.sessionId,
        'X-Rtid': flow?.refTransactionId || flowStore.rtid,
        'X-Tid': flow?.transactionId,
      },
    });

    if (!res) return false;
  }

  return {
    workNameItems,

    fetchStatsProductGroup,
    fetchListProductServiceById,
    fetchListProductService,
    createProductService,
    editProductService,
    deleteProductService,

    fetchStatsProduct,
    fetchListProduct,
    createProduct,
    fetchListProductById,
    editProduct,
    deleteProduct,

    fetchStatsService,
    fetchListService,
    createService,
    fetchListServiceByIdWork,
    fetchListServiceById,
    editService,
    deleteService,

    fetchListWork,
    createWork,
    fetchListWorkById,
    editWork,
    deleteWork,
    fetchListProductByIdWork,

    fetchListOfWork,

    fetchImageListById,
    addImageList,
    deleteImageByName,
  };
});

export default useProductServiceStore;
