import { v4 as uuidv4 } from 'uuid';
import { db } from '../application/database';
import {
  MitraPackageOptionResponse,
  toMitraPackageOptionResponse,
  BulkUpdateMitraPackageOptionRequest,
} from '../model/mitra-package-option-model';
import { MitraPackageOptionValidation } from '../validation/mitra-package-option-validation';
import { Validation } from '../validation/validation';

async function bulkUpdate(table: string, request: BulkUpdateMitraPackageOptionRequest): Promise<void> {
  // Validate the bulk update request
  const { created, modified, deleted } = Validation.validate(MitraPackageOptionValidation.BULK_UPDATE, request);

  // Start a transaction for batch processing
  await db.transaction(async (conn) => {
    // Inserting created items
    if (created && created.length > 0) {
      const values = created.map((option) => [uuidv4(), option.name, option.price_idr, option.order_number]);
      const placeholders = values.map(() => '(?, ?, ?, ?)').join(', ');
      const query = `INSERT INTO ${table} (id, name, price_idr, order_number) VALUES ${placeholders}`;
      const flatValues = values.flat();
      
      await conn.query(query, flatValues); // Use flat values
    }

    // Updating modified items
    if (modified && modified.length > 0) {
      await Promise.all(
        modified.map(async (option) => {
          const query = `UPDATE ${table} SET name = ?, price_idr = ?, order_number = ? WHERE id = ?`;
          await conn.query(query, [option.name, option.price_idr, option.order_number, option.id]);
        })
      );
    }

    // Deleting items
    if (deleted && deleted.length > 0) {
      const query = `DELETE FROM ${table} WHERE id IN (?)`;
      await conn.query(query, [deleted]);
    }
  });
}

async function getAll(table: string): Promise<MitraPackageOptionResponse[]> {
  // Retrieve all items from the table
  const items = await db.query<MitraPackageOptionResponse>(`SELECT * FROM ${table} ORDER BY order_number, created_at ASC`);

  // Map each item to the response format
  return items.map(toMitraPackageOptionResponse);
}

export class MitraPackageOptionService {
  // Airline methods
  static async bulkUpdateAirlines(request: BulkUpdateMitraPackageOptionRequest): Promise<void> {
    await bulkUpdate('airline', request);
  }

  static async getAllAirlines(): Promise<MitraPackageOptionResponse[]> {
    return await getAll('airline');
  }

  // Visa methods
  static async bulkUpdateVisas(request: BulkUpdateMitraPackageOptionRequest): Promise<void> {
    await bulkUpdate('visa', request);
  }

  static async getAllVisas(): Promise<MitraPackageOptionResponse[]> {
    return await getAll('visa');
  }

  // Transportation methods
  static async bulkUpdateTransportations(request: BulkUpdateMitraPackageOptionRequest): Promise<void> {
    await bulkUpdate('transportation', request);
  }

  static async getAllTransportations(): Promise<MitraPackageOptionResponse[]> {
    return await getAll('transportation');
  }

  // Muthawif methods
  static async bulkUpdateMuthawifs(request: BulkUpdateMitraPackageOptionRequest): Promise<void> {
    await bulkUpdate('muthawif', request);
  }

  static async getAllMuthawifs(): Promise<MitraPackageOptionResponse[]> {
    return await getAll('muthawif');
  }

  // Handling saudi methods
  static async bulkUpdateHandlingSaudis(request: BulkUpdateMitraPackageOptionRequest): Promise<void> {
    await bulkUpdate('handling_saudi', request);
  }

  static async getAllHandlingSaudis(): Promise<MitraPackageOptionResponse[]> {
    return await getAll('handling_saudi');
  }

  // Hanlding domestic methods
  static async bulkUpdateHandlingDomestics(request: BulkUpdateMitraPackageOptionRequest): Promise<void> {
    await bulkUpdate('handling_domestic', request);
  }

  static async getAllHandlingDomestics(): Promise<MitraPackageOptionResponse[]> {
    return await getAll('handling_domestic');
  }

  // Siskopatuh methods
  static async bulkUpdateSiskopatuhs(request: BulkUpdateMitraPackageOptionRequest): Promise<void> {
    await bulkUpdate('siskopatuh', request);
  }

  static async getAllSiskopatuhs(): Promise<MitraPackageOptionResponse[]> {
    return await getAll('siskopatuh');
  }

  // Equipment methods
  static async bulkUpdateEquipments(request: BulkUpdateMitraPackageOptionRequest): Promise<void> {
    await bulkUpdate('equipment', request);
  }

  static async getAllEquipments(): Promise<MitraPackageOptionResponse[]> {
    return await getAll('equipment');
  }

  // Tour plus methods
  static async bulkUpdateTourPluses(request: BulkUpdateMitraPackageOptionRequest): Promise<void> {
    await bulkUpdate('tour_plus', request);
  }

  static async getAllTourPluses(): Promise<MitraPackageOptionResponse[]> {
    return await getAll('tour_plus');
  }

  // Manasik methods
  static async bulkUpdateManasiks(request: BulkUpdateMitraPackageOptionRequest): Promise<void> {
    await bulkUpdate('manasik', request);
  }

  static async getAllManasiks(): Promise<MitraPackageOptionResponse[]> {
    return await getAll('manasik');
  }
}
