import { ref } from 'vue';
import { defineStore } from 'pinia';
import { Pagination } from '../types';
import { api } from 'src/boot/axios';
import {
  Customer,
  CustomerCreate,
  CustomerUpdate,
  CustomerStats,
  CustomerBranch,
  CustomerBranchCreate,
  CustomerType,
  CitizenPayload,
} from './types';
import { Employee } from '../employee/types';
import { baseUrl, manageFile, manageMeta } from '../utils';

const useCustomerStore = defineStore('api-customer', () => {
  const data = ref<Pagination<Customer[]>>();

  const fileManager = manageFile<
    | 'citizen'
    | 'house-registration'
    | 'commercial-registration'
    | 'vat-registration'
    | 'power-of-attorney'
  >(api, 'customer-branch');

  const metaManager = manageMeta<
    | 'citizen'
    | 'house-registration'
    | 'commercial-registration'
    | 'vat-registration'
    | 'power-of-attorney'
  >(api, 'customer-branch');

  async function setImage(id: string, image: File) {
    await api.put(`/customer/${id}/image`, image, {
      headers: { 'Content-Type': image?.type },
      onUploadProgress: (e) => console.log(e),
    });
  }

  async function fetchById(customerId: string) {
    const res = await api.get<
      Customer & { branch: CustomerBranch[]; registeredBranchId: string }
    >(`/customer/${customerId}`);

    if (res && res.status === 200) return res.data;

    return false;
  }

  async function fetchBranchEmployee(
    idBranch: string,
    opts?: {
      zipCode?: string;
      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<Employee[]>>(
      `/customer-branch/${idBranch}/employee${(params && '?'.concat(query)) || ''}`,
    );

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

  async function fetchListCustomeBranch<
    Options extends {
      zipCode?: string;
      customerId?: string;
      includeCustomer?: boolean;
      status?: 'CREATED' | 'ACTIVE' | 'INACTIVE';
      query?: string;
      page?: number;
      pageSize?: number;
    },
    Data extends Pagination<
      (CustomerBranch &
        (Options['includeCustomer'] extends true
          ? { customer: Customer }
          : unknown))[]
    >,
  >(opts?: Options): Promise<Data | false> {
    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<Data>(
      `/customer-branch${(params && '?'.concat(query)) || ''}`,
    );

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

    return false;
  }

  async function fetchList<
    Options extends {
      page?: number;
      pageSize?: number;
      query?: string;
      includeBranch?: boolean;
      status?: 'CREATED' | 'ACTIVE' | 'INACTIVE';
      customerType?: CustomerType;
    },
    Data extends Pagination<
      (Customer &
        (Options['includeBranch'] extends true
          ? { branch: CustomerBranch[] }
          : unknown))[]
    >,
  >(opts?: Options): Promise<Data | false> {
    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<Data>(
      `/customer${(params && '?'.concat(query)) || ''}`,
    );

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

    return false;
  }

  async function getStatsCustomer() {
    const res = await api.get<CustomerStats>('/customer/type-stats');

    if (!res) return false;

    return res.data;
  }

  async function putAttachment(opts: {
    branchId: string;
    file: File;
    filename?: string;
  }) {
    const res = await api.put(
      `/customer-branch/${opts.branchId}/attachment/${opts.filename || opts.file.name}`,
      opts.file,
      {
        headers: { 'Content-Type': opts.file.type },
        onUploadProgress: (e) => console.log(e),
      },
    );

    if (res.status >= 400) return false;

    return true;
  }

  async function deleteAttachment(id: string, filename: string) {
    const res = await api.delete(
      `/customer-branch/${id}/attachment/${filename}`,
    );

    if (res.status >= 400) return false;
    return true;
  }

  async function listAttachment(id: string) {
    const res = await api.get<string[]>(`/customer-branch/${id}/attachment`);

    if (res.status >= 400) return false;

    return res.data;
  }
  async function getAttachment(id: string, filename: string, download = false) {
    const url = `${baseUrl}/customer-branch/${id}/attachment/${filename}`;
    const res = await api.get<string>(url);

    if (download) {
      fetch(res.data)
        .then(async (res) => await res.blob())
        .then((blob) => {
          const a = document.createElement('a');
          a.download = filename;
          a.href = window.URL.createObjectURL(blob);
          a.click();
          a.remove();
        });
    }

    return res.data;
  }

  async function fetchImageListById(id: string) {
    const res = await api.get(`/customer/${id}/image`);

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

    return false;
  }

  async function addImageList(file: File, customerId: string, name: string) {
    await api
      .put(`/customer/${customerId}/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) {
    const res = await api.delete(`/customer/${id}/image/${name}`);

    if (!res) return false;
  }

  async function create(
    data: CustomerCreate,
    imgList: {
      selectedImage: string;
      list: { url: string; imgFile: File | null; name: string }[];
    },
  ) {
    if (data.customerBranch) {
      if (data.customerBranch[0].citizenId) {
        delete data.customerBranch[0]['authorizedNameEN'];
        delete data.customerBranch[0]['authorizedName'];
        delete data.customerBranch[0]['authorizedCapital'];
        delete data.customerBranch[0]['registerDate'];
        delete data.customerBranch[0]['registerNameEN'];
        delete data.customerBranch[0]['registerName'];
        delete data.customerBranch[0]['legalPersonNo'];
      } else {
        delete data.customerBranch[0]['citizenId'];
      }
      if (!data.customerBranch[0].birthDate)
        delete data.customerBranch[0]['birthDate'];
      if (!data.customerBranch[0].registerDate)
        delete data.customerBranch[0]['registerDate'];
    }

    const { customerBranch, image, ...payload } = data;

    const res = await api.post<Customer & { branch: CustomerBranch[] }>(
      '/customer',
      {
        ...payload,
        branch: data.customerBranch?.map((v) => ({
          ...v,
          file: undefined,
          branchCode: undefined,
          id: undefined,
          customerId: undefined,
          codeCustomer: undefined,
        })),
        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);
      }
    }

    if (!res) return false;

    await Promise.all(
      res.data.branch.map(async (v, i) => {
        const tempValue = customerBranch?.at(i);

        if (tempValue) {
          tempValue.file?.forEach(async ({ group, _meta, file }) => {
            if (file !== undefined) {
              await metaManager.postMeta({
                parentId: v.id,
                group: group as
                  | 'citizen'
                  | 'house-registration'
                  | 'commercial-registration'
                  | 'vat-registration'
                  | 'power-of-attorney',
                meta: _meta,
                file,
              });
            }
          });
        }
      }),
    );

    return res.data;
  }

  async function editById(id: string, data: Partial<CustomerUpdate>) {
    const { customerBranch, image, ...payload } = data;

    const res = await api.put<
      Customer & {
        branch: CustomerBranch[];
      }
    >(`/customer/${id}`, {
      ...payload,
      branch: data.customerBranch?.map((v) => ({
        ...v,
        file: undefined,
        branchCode: undefined,
        id: undefined,
        customerId: undefined,
        codeCustomer: undefined,
        createAt: undefined,
        createdByUserId: undefined,
        statusOrder: undefined,
        updatedAt: undefined,
        updatedByUserId: undefined,
      })),
    });

    if (!res) return false;

    return res.data;
  }

  async function deleteById(id: string) {
    const res = await api.delete<Customer>(`/customer/${id}`);

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

    return false;
  }

  async function getBranchById(id: string) {
    const res = await api.get<CustomerBranch>(`/customer-branch/${id}`);
    if (!res) return false;

    return res.data;
  }

  async function createBranch(
    data: CustomerBranchCreate & {
      id?: string;
      customerId: string;
      codeCustomer: string;
    },
  ) {
    if (data.citizenId) {
      delete data['authorizedNameEN'];
      delete data['authorizedName'];
      delete data['registerDate'];
      delete data['authorizedCapital'];
      delete data['registerNameEN'];
      delete data['registerName'];
      delete data['legalPersonNo'];
    } else {
      delete data['citizenId'];
    }
    if (!data.birthDate) delete data['birthDate'];
    if (!data.registerDate) delete data['registerDate'];

    const {
      codeCustomer,
      statusSave,
      code,
      file,
      birthDate,
      citizen,
      ...payload
    } = data;

    const res = await api.post<CustomerBranch>('/customer-branch', payload);
    if (!res) return false;

    if (citizen) {
      for (let i = 0; i < citizen.length; i++) {
        const _res = await api.post<{ id: string }>(
          `/customer-branch/${res.data.id}/citizen`,
          citizen[i],
        );
        if (_res.data.id) {
          await fileManager.putFile({
            group: 'citizen',
            parentId: res.data.id,
            file: citizen[i].file,
            fileId: _res.data.id,
          });
        }
      }
    }

    return res.data;
  }

  async function editBranchById(
    id: string,
    data: Partial<
      CustomerBranch & {
        id?: string;
        customerId: string;
        codeCustomer: string;
      }
    >,
  ) {
    if (data.citizenId) {
      delete data['authorizedNameEN'];
      delete data['authorizedName'];
      delete data['registerDate'];
      delete data['authorizedCapital'];
      delete data['registerNameEN'];
      delete data['registerName'];
      delete data['legalPersonNo'];
    } else {
      delete data['citizenId'];
    }
    if (!data.birthDate) delete data['birthDate'];
    if (!data.registerDate) delete data['registerDate'];

    const {
      code,
      status,
      codeCustomer,
      createdAt,
      createdByUserId,
      statusOrder,
      updatedAt,
      updatedByUserId,
      customerCode,
      file,
      registerCompanyName,
      statusSave,
      ...payload
    } = data;

    if (!!payload.citizenId) {
      delete payload['registerDate'];
      delete payload['registerName'];
      delete payload['registerNameEN'];
      delete payload['authorizedCapital'];
      delete payload['legalPersonNo'];
    } else {
      delete payload['citizenId'];
    }

    const res = await api.put<CustomerBranch>(
      `/customer-branch/${id}`,
      payload,
    );

    if (!res) return false;

    return res.data;
  }

  async function deleteBranchById(id: string) {
    const res = await api.delete<Customer>(`/customer-branch/${id}`);

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

    return false;
  }

  async function fetchListCustomeBranchById(branchId: string) {
    const res = await api.get(`/customer-branch/${branchId}`);

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

    return false;
  }

  return {
    data,

    getStatsCustomer,

    setImage,
    fetchListCustomeBranch,
    fetchById,
    fetchList,

    fetchImageListById,
    addImageList,
    deleteImageByName,

    create,
    editById,
    deleteById,
    createBranch,
    getBranchById,
    editBranchById,
    deleteBranchById,
    fetchListCustomeBranchById,

    fetchBranchEmployee,

    listAttachment,
    getAttachment,
    putAttachment,
    deleteAttachment,

    ...fileManager,
    ...metaManager,
  };
});

export default useCustomerStore;
