import axios from 'axios';
import { BaseApiService } from '@/services/api/base';
import { BaseApiResponse } from '@/types/api/api-general';
import { httpClient, httpClientFetcher } from '@/services/http/client';
import { formatDate } from '@/lib/helper';
import {
  CreateFinancePayment,
  CreateInitialBalance,
  CreateInjection,
  Finance,
  UpdateFinancePayment,
  UpdateInitialBalance,
  UpdateInjection,
} from '@/types/api/finance/finance';

export class FinanceApiService extends BaseApiService<
  Finance,
  unknown,
  unknown
> {
  constructor(basePath: string) {
    super(basePath);
  }

  async getSingle(id: number): Promise<BaseApiResponse<Finance>> {
    return await httpClientFetcher<BaseApiResponse<Finance>>(
      `${this.basePath}/transactions/${id}`
    );
  }

  async create(payload: CreateFinancePayment) {
    const isFormData =
      typeof FormData !== 'undefined' && payload instanceof FormData;
    try {
      const headers = isFormData
        ? { ...(this.header ?? {}) }
        : { 'Content-Type': 'application/json', ...(this.header ?? {}) };

      const createRes = await httpClient<BaseApiResponse<Finance>>(
        `${this.basePath}/payments`,
        {
          method: 'POST',
          body: payload,
          headers,
        }
      );
      return createRes;
    } catch (error: unknown) {
      if (axios.isAxiosError<BaseApiResponse<Finance>>(error)) {
        return error.response?.data;
      }
      return undefined;
    }
  }

  async createInitialBalances(payload: CreateInitialBalance) {
    const isFormData =
      typeof FormData !== 'undefined' && payload instanceof FormData;
    try {
      const headers = isFormData
        ? { ...(this.header ?? {}) }
        : { 'Content-Type': 'application/json', ...(this.header ?? {}) };

      const createRes = await httpClient<BaseApiResponse<Finance>>(
        `${this.basePath}/initial-balances`,
        {
          method: 'POST',
          body: payload,
          headers,
        }
      );
      return createRes;
    } catch (error: unknown) {
      if (axios.isAxiosError<BaseApiResponse<Finance>>(error)) {
        return error.response?.data;
      }
      return undefined;
    }
  }

  async createInjections(payload: CreateInjection) {
    const isFormData =
      typeof FormData !== 'undefined' && payload instanceof FormData;
    try {
      const headers = isFormData
        ? { ...(this.header ?? {}) }
        : { 'Content-Type': 'application/json', ...(this.header ?? {}) };

      const createRes = await httpClient<BaseApiResponse<Finance>>(
        `${this.basePath}/injections`,
        {
          method: 'POST',
          body: payload,
          headers,
        }
      );
      return createRes;
    } catch (error: unknown) {
      if (axios.isAxiosError<BaseApiResponse<Finance>>(error)) {
        return error.response?.data;
      }
      return undefined;
    }
  }

  async update(id: number, payload: UpdateFinancePayment) {
    const isFormData =
      typeof FormData !== 'undefined' && payload instanceof FormData;
    try {
      const updatePath = `${this.basePath}/payments/${id}`;

      const headers = isFormData
        ? { ...(this.header ?? {}) }
        : { 'Content-Type': 'application/json', ...(this.header ?? {}) };

      const updateRes = await httpClient<BaseApiResponse<Finance>>(updatePath, {
        method: 'PATCH',
        body: payload,
        headers,
      });
      return updateRes;
    } catch (error: unknown) {
      if (axios.isAxiosError<BaseApiResponse<Finance>>(error)) {
        return error.response?.data;
      }
      return undefined;
    }
  }

  async updateInitialBalances(id: number, payload: UpdateInitialBalance) {
    const isFormData =
      typeof FormData !== 'undefined' && payload instanceof FormData;
    try {
      const updatePath = `${this.basePath}/initial-balances/${id}`;

      const headers = isFormData
        ? { ...(this.header ?? {}) }
        : { 'Content-Type': 'application/json', ...(this.header ?? {}) };

      const updateRes = await httpClient<BaseApiResponse<Finance>>(updatePath, {
        method: 'PATCH',
        body: payload,
        headers,
      });
      return updateRes;
    } catch (error: unknown) {
      if (axios.isAxiosError<BaseApiResponse<Finance>>(error)) {
        return error.response?.data;
      }
      return undefined;
    }
  }

  async updateInjections(id: number, payload: UpdateInjection) {
    const isFormData =
      typeof FormData !== 'undefined' && payload instanceof FormData;
    try {
      const updatePath = `${this.basePath}/injections/${id}`;

      const headers = isFormData
        ? { ...(this.header ?? {}) }
        : { 'Content-Type': 'application/json', ...(this.header ?? {}) };

      const updateRes = await httpClient<BaseApiResponse<Finance>>(updatePath, {
        method: 'PATCH',
        body: payload,
        headers,
      });
      return updateRes;
    } catch (error: unknown) {
      if (axios.isAxiosError<BaseApiResponse<Finance>>(error)) {
        return error.response?.data;
      }
      return undefined;
    }
  }

  async exportToExcel(initialQueryString: string) {
    const params = new URLSearchParams(initialQueryString);

    params.set('export', 'excel');
    params.set('page', '1');
    params.set('limit', '99999999999');

    const res = await httpClient<Blob>(
      `${this.basePath}/transactions?${params.toString()}`,
      { method: 'GET', responseType: 'blob' }
    );

    const url = window.URL.createObjectURL(new Blob([res]));
    const link = document.createElement('a');
    link.href = url;
    link.setAttribute(
      'download',
      `finance-${formatDate(Date.now(), 'DD-MM-YYYY')}.xlsx`
    );
    document.body.appendChild(link);
    link.click();
    link.remove();
  }

  async delete(id: number) {
    try {
      const deletePath = `${this.basePath}/transactions/${id}`;
      const deleteRes = await httpClient<BaseApiResponse>(deletePath, {
        method: 'DELETE',
      });
      return deleteRes;
    } catch (error) {
      if (axios.isAxiosError<BaseApiResponse>(error)) {
        return error.response?.data;
      }
      return undefined;
    }
  }
}

export const FinanceApi = new FinanceApiService('/finance');
