import {
  CreateProjectFlockPayload,
  ProjectFlock,
  UpdateProjectFlockPayload,
} from '@/types/api/production/project-flock';
import { BaseApiService } from '@/services/api/base';
import {
  Approvals,
  BaseApiResponse,
  BaseGroupedApproval,
  ErrorApiResponse,
  SuccessApiResponse,
} from '@/types/api/api-general';
import { httpClient } from '@/services/http/client';
import axios from 'axios';
import { Kandang } from '@/types/api/master-data/kandang';
import { RequestOptions } from '@/services/http/base';

export class ProjectFlockService extends BaseApiService<
  ProjectFlock,
  CreateProjectFlockPayload,
  UpdateProjectFlockPayload
> {
  constructor(basePath: string = '') {
    super(basePath);
  }
  /**
   * Get Approval Lines
   */
  async getApprovalLines(
    id: number
  ): Promise<
    | BaseApiResponse<BaseGroupedApproval[]>
    | ErrorApiResponse
    | SuccessApiResponse<BaseGroupedApproval[]>
    | undefined
  > {
    const path = `/approvals`;
    try {
      return await httpClient<SuccessApiResponse<BaseGroupedApproval[]>>(path, {
        method: 'GET',
        query: {
          module_id: id,
          module_name: 'PROJECT_FLOCKS',
          group_step_number: true,
        },
      } as RequestOptions);
    } catch (error) {
      if (axios.isAxiosError<BaseApiResponse>(error)) {
        return error.response?.data as ErrorApiResponse;
      } else {
        return undefined;
      }
    }
  }

  async getApprovalLineHistory(
    id: number,
    page: number = 1,
    limit: number = 100
  ) {
    try {
      const approvalHistoryRes = await httpClient<Approvals>('/approvals', {
        query: {
          module_name: 'PROJECT_FLOCKS',
          module_id: id,
          group_step_number: 'false',
          page,
          limit,
          order_by_date: 'ASC',
        },
      });

      return approvalHistoryRes;
    } catch (error) {
      if (axios.isAxiosError<Approvals>(error)) {
        return error.response?.data;
      }

      return undefined;
    }
  }

  /**
   * Lookup for Project Flock Kandang
   */
  async lookupProjectFlockKandang(
    projectFlockId: number,
    kandangId: number
  ): Promise<
    | BaseApiResponse<
        | ErrorApiResponse
        | SuccessApiResponse<{
            id: number;
            kandang_id: Kandang;
            project_flock: ProjectFlock;
            available_quantity: number;
          }>
      >
    | undefined
  > {
    try {
      const path = `${this.basePath}/kandangs/lookup`;
      return await httpClient<
        BaseApiResponse<
          SuccessApiResponse<{
            id: number;
            kandang_id: Kandang;
            project_flock: ProjectFlock;
            available_quantity: number;
          }>
        >
      >(path, {
        method: 'GET',
        body: {
          project_flock_id: projectFlockId,
          kandang_id: kandangId,
        },
      });
    } catch (error) {
      if (axios.isAxiosError<BaseApiResponse<ErrorApiResponse>>(error)) {
        return error.response?.data;
      } else {
        return undefined;
      }
    }
  }

  /**
   * Get Next Period of Project Flock
   */
  async getNextPeriod(locationId: number): Promise<
    | BaseApiResponse<
        {
          id: number;
          name: string;
          period: number;
        }[]
      >
    | ErrorApiResponse
    | SuccessApiResponse<
        {
          id: number;
          name: string;
          period: number;
        }[]
      >
    | undefined
  > {
    try {
      const path = `${this.basePath}/locations/${locationId.toString()}/periods`;
      return await httpClient<
        SuccessApiResponse<
          {
            id: number;
            name: string;
            period: number;
          }[]
        >
      >(path, {
        method: 'GET',
      });
    } catch (error) {
      if (axios.isAxiosError<BaseApiResponse<ErrorApiResponse>>(error)) {
        return error.response?.data as ErrorApiResponse;
      } else {
        return undefined;
      }
    }
  }

  /**
   * Resubmit Project Flock
   */
  async resubmit(
    id: number,
    payload: UpdateProjectFlockPayload
  ): Promise<BaseApiResponse<ProjectFlock> | undefined> {
    try {
      const updatePath = `${this.basePath}/${id}/resubmit`;

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

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

  /**
   * Approve single Project Flock
   */
  async approve(
    id: number,
    notes?: string
  ): Promise<BaseApiResponse<{ message: string }> | undefined> {
    return await this.bulkApprovalAction([id], 'APPROVED', notes);
  }

  /**
   * Reject single Project Flock
   */
  async reject(
    id: number,
    notes?: string
  ): Promise<BaseApiResponse<{ message: string }> | undefined> {
    return await this.bulkApprovalAction([id], 'REJECTED', notes);
  }

  /**
   * Approve Bulk Project Flock
   */
  async bulkApprove(
    ids: number[],
    notes?: string
  ): Promise<BaseApiResponse<{ message: string }> | undefined> {
    return await this.bulkApprovalAction(ids, 'APPROVED', notes);
  }

  /**
   * Reject Bulk Project Flock
   */
  async bulkReject(
    ids: number[],
    notes?: string
  ): Promise<BaseApiResponse<{ message: string }> | undefined> {
    return await this.bulkApprovalAction(ids, 'REJECTED', notes);
  }

  /**
   * Approve Bulk Project Flock
   */
  async bulkApprovalAction(
    ids: number[],
    action: 'APPROVED' | 'REJECTED',
    notes?: string
  ): Promise<BaseApiResponse<{ message: string }> | undefined> {
    try {
      const path = `${this.basePath}/approvals`;
      return await httpClient<BaseApiResponse<{ message: string }>>(path, {
        method: 'POST',
        body: {
          action: action,
          approvable_ids: ids,
          notes: notes ?? `Bulk ${action} Project Flock ${ids.join(', ')}`,
        },
      });
    } catch (error) {
      if (axios.isAxiosError<BaseApiResponse<{ message: string }>>(error)) {
        return error.response?.data;
      } else {
        return undefined;
      }
    }
  }
}

export const ProjectFlockApi = new ProjectFlockService(
  '/production/project-flocks'
);
