import * as XLSX from 'xlsx';
import toast from 'react-hot-toast';
import { formatDate, safeRound } from '@/lib/helper';
import { isResponseSuccess } from '@/lib/api-helper';
import { BaseApiService } from '@/services/api/base';
import { httpClient, httpClientFetcher } from '@/services/http/client';
import { BaseApiResponse } from '@/types/api/api-general';
import { ProductionResult } from '@/types/api/report/production-result';
import { BaseProjectFlockKandang } from '@/types/api/production/project-flock-kandang';

export class ProductionResultReportApiService extends BaseApiService<
  ProductionResult,
  unknown,
  unknown
> {
  constructor(basePath: string = '/reports/production-result') {
    super(basePath);
  }

  async getAllProductionResultFetcher(
    endpoint: string
  ): Promise<BaseApiResponse<ProductionResult[]>> {
    return await httpClientFetcher<BaseApiResponse<ProductionResult[]>>(
      endpoint
    );
  }

  async exportProductionResultToExcel(
    projectFlockKandangs: BaseProjectFlockKandang[] | null
  ) {
    try {
      const mappedProductionResults: {
        projectFlockKandang: BaseProjectFlockKandang;
        productionResult: ProductionResult[] | null;
      }[] = await Promise.all(
        (projectFlockKandangs || []).map(async (projectFlockKandang) => {
          const getProductionResultPath = `${this.basePath}/${projectFlockKandang.id}?page=1&limit=99999999`;
          const getProductionResultRes = await httpClient<
            BaseApiResponse<ProductionResult[]>
          >(getProductionResultPath);

          return {
            projectFlockKandang,
            productionResult: isResponseSuccess(getProductionResultRes)
              ? getProductionResultRes.data
              : null,
          };
        })
      );

      const rows = mappedProductionResults;
      if (!rows || rows.length === 0) {
        toast.error('Tidak ada data untuk diexport.');
        return;
      }

      // Group by Project Flock Kandang Name
      const groupedData: Record<
        string,
        Record<string, string | number | undefined>[]
      > = {};

      rows.forEach((row) => {
        const kandangName = row.projectFlockKandang.kandang.name || 'Unknown';
        if (!groupedData[kandangName]) {
          groupedData[kandangName] = [];
        }

        row.productionResult?.forEach((productionResult) => {
          groupedData[kandangName].push({
            woa: safeRound(productionResult.woa, 2),
            bw: safeRound(productionResult.bw, 2),
            std_bw: safeRound(productionResult.std_bw, 2),
            uniformity: safeRound(productionResult.uniformity, 2),
            std_uniformity: productionResult.std_uniformity,
            dep_kum: safeRound(productionResult.dep_kum, 2),
            dep_std: safeRound(productionResult.dep_std, 2),
            butiran_utuh: safeRound(productionResult.butiran_utuh, 2),
            butiran_putih: safeRound(productionResult.butiran_putih, 2),
            butiran_retak: safeRound(productionResult.butiran_retak, 2),
            butiran_pecah: safeRound(productionResult.butiran_pecah, 2),
            butiran_jumlah: safeRound(productionResult.butiran_jumlah, 2),
            total_butir: safeRound(productionResult.total_butir, 2),
            kg_utuh: safeRound(productionResult.kg_utuh, 2),
            kg_putih: safeRound(productionResult.kg_putih, 2),
            kg_retak: safeRound(productionResult.kg_retak, 2),
            kg_pecah: safeRound(productionResult.kg_pecah, 2),
            kg_jumlah: safeRound(productionResult.kg_jumlah, 2),
            total_kg: safeRound(productionResult.total_kg, 2),
            persen_utuh: safeRound(productionResult.persen_utuh, 2),
            persen_putih: safeRound(productionResult.persen_putih, 2),
            persen_retak: safeRound(productionResult.persen_retak, 2),
            persen_pecah: safeRound(productionResult.persen_pecah, 2),
            hd: safeRound(productionResult.hd, 2),
            hd_std: safeRound(productionResult.hd_std, 2),
            fi: safeRound(productionResult.fi, 2),
            fi_std: safeRound(productionResult.fi_std, 2),
            em: safeRound(productionResult.em, 2),
            em_std: safeRound(productionResult.em_std, 2),
            ew: safeRound(productionResult.ew, 2),
            ew_std: safeRound(productionResult.ew_std, 2),
            fcr: safeRound(productionResult.fcr, 2),
            fcr_std: safeRound(productionResult.fcr_std, 2),
            hh: safeRound(productionResult.hh, 2),
            hh_std: safeRound(productionResult.hh_std, 2),
            project_flock_name:
              row.projectFlockKandang.project_flock.flock_name,
            project_flock_category:
              row.projectFlockKandang.project_flock.category,
            kandang_name: row.projectFlockKandang.kandang.name,
            created_at: formatDate(productionResult.created_at, 'YYYY-MM-DD'),
            updated_at: formatDate(productionResult.updated_at, 'YYYY-MM-DD'),
          });
        });
      });

      const wb = XLSX.utils.book_new();

      Object.keys(groupedData).forEach((sheetName) => {
        const ws = XLSX.utils.json_to_sheet(groupedData[sheetName]);
        // Sheet names cannot exceed 31 chars
        const safeSheetName = sheetName.substring(0, 31);
        XLSX.utils.book_append_sheet(wb, ws, safeSheetName);
      });

      const productionResultExcelFileName = `laporan-hasil-produksi-${formatDate(Date.now(), 'YYYY-MM-DD')}-${rows[0].projectFlockKandang.project_flock.flock_name}.xlsx`;

      XLSX.writeFile(wb, productionResultExcelFileName);
    } catch (error) {
      console.error(error);
      toast.error('Gagal melakukan export laporan hasil produksi! Coba lagi.');
    }
  }
}

export const ProductionResultReportApi = new ProductionResultReportApiService(
  '/reports/production-result'
);
