import { ref } from 'vue';
import { defineStore } from 'pinia';
import { Pagination } from '../types';
import { api } from 'src/boot/axios';
import { Status } from 'stores/types';
import {
  Employee,
  EmployeeCheckup,
  EmployeeCreate,
  EmployeeOther,
  EmployeeWork,
  EmployeeCheckupCreate,
  EmployeeOtherCreate,
  EmployeeWorkCreate,
} from './types';
import { CustomerBranch } from '../customer/types';
import axios from 'axios';
import useFlowStore from '../flow';

const useEmployeeStore = defineStore('api-employee', () => {
  const flowStore = useFlowStore();
  const data = ref<Pagination<Employee[]>>();
  const globalOption = ref();
  const ownerOption = ref<CustomerBranch[]>();

  async function fetchById(id: string) {
    const res = await api.get<Employee>(`/employee/${id}`);
    if (res && res.status === 200) {
      return res.data;
    }
    return false;
  }

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

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

  async function create(
    data: EmployeeCreate,
    flow?: {
      sessionId?: string;
      refTransactionId?: string;
      transactionId?: string;
    },
  ) {
    const { id, code, image, ...payload } = data;
    const res = await api.post<
      Employee & { profileImageUrl: string; profileImageUploadUrl: string }
    >('/employee', payload, {
      headers: {
        'X-Session-Id': flow?.sessionId,
        'X-Rtid': flow?.refTransactionId || flowStore.rtid,
        'X-Tid': flow?.transactionId,
      },
    });

    image &&
      (await axios
        .put(res.data.profileImageUploadUrl, 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 createEmployeeCheckup(
    employeeId: string,
    data: EmployeeCheckupCreate,
    flow?: {
      sessionId?: string;
      refTransactionId?: string;
      transactionId?: string;
    },
  ) {
    const { id, statusSave, ...payload } = data;
    const res = await api.post<EmployeeCheckupCreate>(
      `/employee/${employeeId}/checkup`,
      { ...payload },
      {
        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 createEmployeeWork(
    employeeId: string,
    data: EmployeeWorkCreate,
    flow?: {
      sessionId?: string;
      refTransactionId?: string;
      transactionId?: string;
    },
  ) {
    const { id, ...payload } = data;
    const res = await api.post<EmployeeWorkCreate>(
      `/employee/${employeeId}/work`,
      { ...payload },
      {
        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 createEmployeeOtherInfo(
    employeeId: string,
    data: EmployeeOtherCreate,
    flow?: {
      sessionId?: string;
      refTransactionId?: string;
      transactionId?: string;
    },
  ) {
    const { id, statusSave, ...payload } = data;
    const res = await api.post<EmployeeOtherCreate>(
      `/employee/${employeeId}/other-info`,
      { ...payload },
      {
        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 editByIdEmployeeCheckup(
    employeeOfId: string,
    data: Partial<EmployeeCheckupCreate>,
    flow?: {
      sessionId?: string;
      refTransactionId?: string;
      transactionId?: string;
    },
  ) {
    const {
      id,
      createdAt,
      createdByUserId,
      employeeId,
      statusSave,
      updatedAt,
      updatedByUserId,
      ...payload
    } = data;
    const res = await api.put<EmployeeCheckupCreate>(
      `/employee/${employeeOfId}/checkup/${id}`,
      { ...payload },
      {
        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 editByIdEmployeeWork(
    employeeOfId: string,
    data: Partial<EmployeeWorkCreate>,
    flow?: {
      sessionId?: string;
      refTransactionId?: string;
      transactionId?: string;
    },
  ) {
    const {
      id,
      createdAt,
      createdByUserId,
      employeeId,
      statusSave,
      updatedAt,
      updatedByUserId,
      ...payload
    } = data;
    const res = await api.put<EmployeeWorkCreate>(
      `/employee/${employeeOfId}/work/${id}`,
      { ...payload },
      {
        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 editByIdEmployeeOtherInfo(
    employeeOfId: string,
    data: Partial<EmployeeOtherCreate>,
    flow?: {
      sessionId?: string;
      refTransactionId?: string;
      transactionId?: string;
    },
  ) {
    const {
      id,
      statusSave,
      updatedByUserId,
      updatedAt,
      createdByUserId,
      createdAt,
      employeeId,
      ...payload
    } = data;
    const res = await api.put<EmployeeOtherCreate>(
      `/employee/${employeeOfId}/other-info/${id}`,
      { ...payload },
      {
        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 editById(
    employeeId: string,
    data: Partial<EmployeeCreate>,
    flow?: {
      sessionId?: string;
      refTransactionId?: string;
      transactionId?: string;
    },
  ) {
    const { id, code, image, ...payload } = data;
    const res = await api.put<
      Employee & { imageUrl: string; profileImageUploadUrl: string }
    >(`/employee/${employeeId}`, payload, {
      headers: {
        'X-Session-Id': flow?.sessionId,
        'X-Rtid': flow?.refTransactionId || flowStore.rtid,
        'X-Tid': flow?.transactionId,
      },
    });

    image &&
      (await axios
        .put(res.data.profileImageUploadUrl, 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 deleteByIdCheckUp(
    opts: {
      employeeId: string;
      checkUpId?: string;
    },
    flow?: {
      sessionId?: string;
      refTransactionId?: string;
      transactionId?: string;
    },
  ) {
    const res = await api.delete<Employee>(
      `/employee/${opts.employeeId}/checkup/${opts.checkUpId}`,
      {
        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 deleteByIdWork(
    opts: {
      employeeId: string;
      workId?: string;
    },
    flow?: {
      sessionId?: string;
      refTransactionId?: string;
      transactionId?: string;
    },
  ) {
    const res = await api.delete<Employee>(
      `/employee/${opts.employeeId}/work/${opts.workId}`,
      {
        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 deleteById(
    id: string,
    flow?: {
      sessionId?: string;
      refTransactionId?: string;
      transactionId?: string;
    },
  ) {
    const res = await api.delete<Employee>(`/employee/${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 fetchCheckup(
    id: string,
    flow?: {
      sessionId?: string;
      refTransactionId?: string;
      transactionId?: string;
    },
  ) {
    const res = await api.get<EmployeeCheckup[]>(`/employee/${id}/checkup`, {
      headers: {
        'X-Session-Id': flow?.sessionId,
        'X-Rtid': flow?.refTransactionId || flowStore.rtid,
        'X-Tid': flow?.transactionId,
      },
    });
    if (res && res.status === 200) {
      return res.data;
    }
  }

  async function fetchWork(
    id: string,
    flow?: {
      sessionId?: string;
      refTransactionId?: string;
      transactionId?: string;
    },
  ) {
    const res = await api.get<EmployeeWork[]>(`/employee/${id}/work`, {
      headers: {
        'X-Session-Id': flow?.sessionId,
        'X-Rtid': flow?.refTransactionId || flowStore.rtid,
        'X-Tid': flow?.transactionId,
      },
    });
    if (res && res.status === 200) {
      return res.data;
    }
  }

  async function fetchOther(
    id: string,
    flow?: {
      sessionId?: string;
      refTransactionId?: string;
      transactionId?: string;
    },
  ) {
    const res = await api.get<EmployeeOther>(`/employee/${id}/other-info`, {
      headers: {
        'X-Session-Id': flow?.sessionId,
        'X-Rtid': flow?.refTransactionId || flowStore.rtid,
        'X-Tid': flow?.transactionId,
      },
    });
    if (res && res.status === 200) {
      return res.data;
    }
  }

  async function getStatsEmployee(
    customerBranchId?: string,
    flow?: {
      sessionId?: string;
      refTransactionId?: string;
      transactionId?: string;
    },
  ) {
    const res = await api.get(
      `/employee/stats${customerBranchId ? '?customerBranchId=' + customerBranchId : ''}/`,
      {
        headers: {
          'X-Session-Id': flow?.sessionId,
          'X-Rtid': flow?.refTransactionId || flowStore.rtid,
          'X-Tid': flow?.transactionId,
        },
      },
    );
    if (res && res.status === 200) {
      return res.data;
    }
  }

  async function getStatsEmployeeGender(
    opts?: {
      customerBranchId?: string;
      status?: 'CREATED' | 'ACTIVE' | 'INACTIVE';
      query?: string;
    },

    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(
      `/employee/stats/gender${(params && '?'.concat(query)) || ''}`,
      {
        headers: {
          'X-Session-Id': flow?.sessionId,
          'X-Rtid': flow?.refTransactionId || flowStore.rtid,
          'X-Tid': flow?.transactionId,
        },
      },
    );
    if (res && res.status === 200) {
      return res.data;
    }
  }

  async function getEditHistory(
    employeeId: string,
    flow?: {
      sessionId?: string;
      refTransactionId?: string;
      transactionId?: string;
    },
  ) {
    const res = await api.get(`/employee/${employeeId}/edit-history`, {
      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 {
    data,
    globalOption,
    ownerOption,

    fetchById,
    fetchList,
    create,
    editById,
    deleteById,
    fetchCheckup,
    fetchWork,
    fetchOther,
    getStatsEmployee,
    getStatsEmployeeGender,
    getEditHistory,

    createEmployeeCheckup,
    editByIdEmployeeCheckup,
    deleteByIdCheckUp,

    createEmployeeWork,
    editByIdEmployeeWork,
    deleteByIdWork,

    createEmployeeOtherInfo,
    editByIdEmployeeOtherInfo,
  };
});

export default useEmployeeStore;
