import { ref } from 'vue';
import { defineStore } from 'pinia';
import { Pagination } from '../types';
import { api } from 'src/boot/axios';
import {
  Customer,
  CustomerCreate,
  CustomerUpdate,
  BranchAttachmentCreate,
  BranchAttachment,
  CustomerStats,
  CustomerBranch,
  CustomerBranchCreate,
  CustomerType,
} from './types';
import axios from 'axios';
import useFlowStore from '../flow';
import { Employee } from '../employee/types';

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

  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,
    flow?: {
      sessionId?: string;
      refTransactionId?: string;
      transactionId?: string;
    },
  ) {
    const res = await api.get<
      Customer & { branch: CustomerBranch[]; registeredBranchId: string }
    >(`/customer/${customerId}`, {
      headers: {
        'X-Session-Id': flow?.sessionId,
        'X-Rtid': flow?.refTransactionId || flowStore.rtid,
        'X-Tid': flow?.transactionId,
      },
    });

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

    return false;
  }

  async function fetchBranchEmployee(
    idBranch: string,
    opts?: {
      zipCode?: string;
      query?: string;
      page?: number;
      pageSize?: number;
    },
    flow?: {
      sessionId?: string;
      refTransactionId?: string;
      transactionId?: 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<Employee[]>>(
      `/customer-branch/${idBranch}/employee${(params && '?'.concat(query)) || ''}`,
      {
        headers: {
          'X-Session-Id': flow?.sessionId,
          'X-Rtid': flow?.refTransactionId || flowStore.rtid,
          'X-Tid': flow?.transactionId,
        },
      },
    );

    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,
    flow?: {
      sessionId?: string;
      refTransactionId?: string;
      transactionId?: string;
    },
  ): 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)) || ''}`,
      {
        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;
    }

    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,
    flow?: {
      sessionId?: string;
      refTransactionId?: string;
      transactionId?: string;
    },
  ): 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)) || ''}`,
      {
        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;
    }

    return false;
  }

  async function getStatsCustomer(flow?: {
    sessionId?: string;
    refTransactionId?: string;
    transactionId?: string;
  }) {
    const res = await api.get<CustomerStats>('/customer/type-stats', {
      headers: {
        'X-Session-Id': flow?.sessionId,
        'X-Rtid': flow?.refTransactionId || flowStore.rtid,
        'X-Tid': flow?.transactionId,
      },
    });

    if (!res) return false;

    return res.data;
  }
  async function create(
    data: CustomerCreate,
    flow?: {
      sessionId?: string;
      refTransactionId?: string;
      transactionId?: string;
    },
  ) {
    const { code, customerBranch, image, ...payload } = data;

    // const attachment = payload.customerBranch?.map((v) => v.file);

    // if (payload.customerBranch?.length) {
    //   for (let i = 0; i < payload.customerBranch?.length; i++) {
    //     delete payload.customerBranch[i].file;
    //   }
    // }

    const res = await api.post<
      Customer & {
        branch: CustomerBranch[];
        imageUrl: string;
        imageUploadUrl: string;
      }
    >('/customer', payload, {
      headers: {
        'X-Session-Id': flow?.sessionId,
        'X-Rtid': flow?.refTransactionId || flowStore.rtid,
        'X-Tid': flow?.transactionId,
      },
    });

    // await Promise.allSettled([
    //   ...res.data.branch.map(async (v, i) => {
    //     const fileList = attachment?.[i];
    //     if (fileList)
    //       return await addBranchAttachment(v.id, { file: fileList });
    //   }),
    image &&
      (await api
        .put(`/customer/${res.data.id}/image`, image, {
          headers: { 'Content-Type': image?.type },
          onUploadProgress: (e) => console.log(e),
        })
        .catch((e) => console.error(e)));
    // ]);

    if (!res) return false;

    return res.data;
  }

  async function editById(
    id: string,
    data: Partial<CustomerUpdate>,
    flow?: {
      sessionId?: string;
      refTransactionId?: string;
      transactionId?: string;
    },
  ) {
    const { customerBranch, image, ...payload } = data;
    // const attachment = payload.customerBranch?.map((v) => v.file);

    // payload.customerBranch = payload.customerBranch?.map((v) => {
    //   const { code: _code, ...rest } = v;
    //   return { ...rest };
    // });

    // if (payload.customerBranch?.length) {
    //   for (let i = 0; i < payload.customerBranch?.length; i++) {
    //     delete payload.customerBranch[i].file;
    //   }
    // }

    const res = await api.put<
      Customer & {
        branch: CustomerBranch[];
        imageUrl: string;
        imageUploadUrl: string;
      }
    >(`/customer/${id}`, payload, {
      headers: {
        'X-Session-Id': flow?.sessionId,
        'X-Rtid': flow?.refTransactionId || flowStore.rtid,
        'X-Tid': flow?.transactionId,
      },
    });

    // await Promise.allSettled([
    //   ...res.data.branch.map(async (v, i) => {
    //     const fileList = attachment?.[i];
    //     if (fileList)
    //       return await addBranchAttachment(v.id, { file: fileList });
    //   }),
    image &&
      (await axios
        .put(res.data.imageUploadUrl, image, {
          headers: { 'Content-Type': image.type },
          onUploadProgress: (e) => console.log(e),
        })
        .catch((e) => console.error(e)));
    // ]);

    if (!res) return false;

    return res.data;
  }

  async function deleteById(
    id: string,
    flow?: {
      sessionId?: string;
      refTransactionId?: string;
      transactionId?: string;
    },
  ) {
    const res = await api.delete<Customer>(`/customer/${id}`, {
      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;

    return false;
  }

  async function getBranchById(
    id: string,
    flow?: {
      sessionId?: string;
      refTransactionId?: string;
      transactionId?: string;
    },
  ) {
    const res = await api.get<CustomerBranch>(`/customer-branch/${id}`, {
      headers: {
        'X-Session-Id': flow?.sessionId,
        'X-Rtid': flow?.refTransactionId || flowStore.rtid,
        'X-Tid': flow?.transactionId,
      },
    });
    if (!res) return false;

    return res.data;
  }

  async function createBranch(
    data: CustomerBranchCreate & { id?: string; customerId: string },
    flow?: {
      sessionId?: string;
      refTransactionId?: string;
      transactionId?: string;
    },
  ) {
    const {
      customerCode,
      registerCompanyName,
      statusSave,
      code,
      file,
      ...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.post<CustomerBranch>('/customer-branch', payload, {
      headers: {
        'X-Session-Id': flow?.sessionId,
        'X-Rtid': flow?.refTransactionId || flowStore.rtid,
        'X-Tid': flow?.transactionId,
      },
    });
    if (!res) return false;

    if (file) await addBranchAttachment(res.data.id, { file });

    return res.data;
  }

  async function editBranchById(
    id: string,
    data: Partial<CustomerBranchCreate & { id?: string; customerId: string }>,
    flow?: {
      sessionId?: string;
      refTransactionId?: string;
      transactionId?: string;
    },
  ) {
    const {
      customerCode,
      registerCompanyName,
      statusSave,
      code,
      status,
      file,
      ...payload
    } = data;

    console.log(payload);

    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,
      {
        headers: {
          'X-Session-Id': flow?.sessionId,
          'X-Rtid': flow?.refTransactionId || flowStore.rtid,
          'X-Tid': flow?.transactionId,
        },
      },
    );

    if (file) await addBranchAttachment(id, { file });

    if (!res) return false;

    return res.data;
  }

  async function deleteBranchById(
    id: string,
    flow?: {
      sessionId?: string;
      refTransactionId?: string;
      transactionId?: string;
    },
  ) {
    const res = await api.delete<Customer>(`/customer-branch/${id}`, {
      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;

    return false;
  }

  async function addBranchAttachment(
    branchId: string,
    payload: BranchAttachmentCreate,
    flow?: {
      sessionId?: string;
      refTransactionId?: string;
      transactionId?: string;
    },
  ) {
    const list: { name: string; file: File }[] = [];

    payload.file.forEach((v) => {
      let filename = v.name;

      if (list.some((v) => v.name === filename)) {
        const dotIndex = filename.lastIndexOf('.');
        const originalName =
          dotIndex !== -1 && !filename.startsWith('.')
            ? filename.slice(0, dotIndex)
            : filename;
        const extension =
          dotIndex !== -1 && !filename.startsWith('.')
            ? filename.slice(dotIndex)
            : '';

        let i = 0;

        while (list.some((v) => v.name === filename)) {
          filename = `${originalName} (${++i})`;
          if (dotIndex !== -1) filename += extension;
        }
      }

      list.push({ name: filename, file: v });
    });

    const res = await api.post<(BranchAttachment & { uploadUrl: string })[]>(
      `/customer-branch/${branchId}/attachment`,
      { file: list.map((v) => v.name) },
      {
        headers: {
          'X-Session-Id': flow?.sessionId,
          'X-Rtid': flow?.refTransactionId || flowStore.rtid,
          'X-Tid': flow?.transactionId,
        },
      },
    );

    await Promise.all(
      res.data.map(async (a) => {
        const found = list.find((b) => b.name === a.name)!;

        await axios
          .put(a.uploadUrl, found.file, {
            headers: { 'Content-Type': found.file.type },
            onUploadProgress: (e) => console.log(e),
          })
          .catch((e) => console.error(e));
      }),
    );
  }

  async function fetchListCustomeBranchById(
    branchId: string,
    flow?: {
      sessionId?: string;
      refTransactionId?: string;
      transactionId?: string;
    },
  ) {
    const res = await api.get(`/customer-branch/${branchId}`, {
      headers: {
        'X-Session-Id': flow?.sessionId,
        'X-Rtid': flow?.refTransactionId || flowStore.rtid,
        'X-Tid': flow?.transactionId,
      },
    });

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

    return false;
  }

  return {
    data,

    getStatsCustomer,

    setImage,
    fetchListCustomeBranch,
    fetchById,
    fetchList,
    create,
    editById,
    deleteById,
    createBranch,
    getBranchById,
    editBranchById,
    deleteBranchById,
    fetchListCustomeBranchById,

    fetchBranchEmployee,
  };
});

export default useCustomerStore;
