import Order from '#models/order'
import {
  bulkPickupOrDeliveryAgentChangeByAdminValidator,
  bulkPickupOrDeliveryDateChangeByAdminValidator,
} from '#validators/bulk_order_edit'
import type { HttpContext } from '@adonisjs/core/http'
import {
  OrderHistoryActions,
  OrderStatus,
  OrderStatusForCustomer,
  PackageStatus,
  Roles,
  UserType,
} from '../../types/enum.js'
import { createComprehensiveOrderHistory, UserNameById } from '../Helper/Helper.js'
import User from '#models/user'
import OrderPackage from '#models/order_package'

export default class BulkOrderEditsController {
  async bulkPickupOrDeliveryDateChangeByAdmin({ auth, request, response }: HttpContext) {
    const { type, date, order_ids } = await request.validateUsing(
      bulkPickupOrDeliveryDateChangeByAdminValidator
    )

    if (type === 'pickup') {
      const orders = await Order.query().whereIn('id', order_ids)

      const openAndPendingOrders = orders.filter((order) =>
        [OrderStatus.Open, OrderStatus.PendingPickup, OrderStatus.PickupException].includes(
          order.status
        )
      )

      if (openAndPendingOrders.length !== order_ids.length) {
        return response.status(400).send({
          status: false,
          message:
            'Some orders are not in Open or Pending Pickup status, cannot update pickup date',
        })
      }

      await Order.query().whereIn('id', order_ids).update({ pickup_preference_date: date })

      for (const order of orders) {
        await createComprehensiveOrderHistory(
          order.id,
          auth?.user?.id as number,
          OrderHistoryActions.PickupDateChanged,
          {},
          `✏️ Pickup date changed to ${date.toISOString().split('T')[0]} by admin`
        )
      }

      return response.status(200).send({
        status: true,
        message: 'Pickup dates updated successfully',
      })
    } else if (type === 'delivery') {
      const orders = await Order.query().whereIn('id', order_ids)

      const pickedOrWarehouseOrders = orders.filter((order) =>
        [OrderStatus.PartialAtWarehouse, OrderStatus.AtWarehouse].includes(order.status)
      )

      if (pickedOrWarehouseOrders.length !== order_ids.length) {
        return response.status(400).send({
          status: false,
          message: 'Some orders are not in At Warehouse status, cannot update delivery date',
        })
      }

      await Order.query().whereIn('id', order_ids).update({ delivery_preference_date: date })

      for (const order of orders) {
        await createComprehensiveOrderHistory(
          order.id,
          auth?.user?.id as number,
          OrderHistoryActions.DeliveryDateChanged,
          {},
          `✏️ Delivery date changed to ${date.toISOString().split('T')[0]} by admin`
        )
      }

      return response.status(200).send({
        status: true,
        message: 'Delivery dates updated successfully',
      })
    }
  }

  async bulkPickupOrDeliveryAgentChangeByAdmin({ auth, request, response }: HttpContext) {
    const { type, driver_id, order_ids } = await request.validateUsing(
      bulkPickupOrDeliveryAgentChangeByAdminValidator
    )

    const driverDetails = await User.findOrFail(driver_id)

    if (driverDetails.is_active === false) {
      return response.status(400).send({
        status: false,
        message: 'The selected driver is inactive. Please select an active driver.',
      })
    }

    if (driverDetails.is_blocked === true) {
      return response.status(400).send({
        status: false,
        message: 'The selected driver is blocked. Please select a different driver.',
      })
    }

    if (
      !driverDetails ||
      driverDetails.role !== Roles.Staff ||
      driverDetails.user_type !== UserType.DriverCumDeliveryBoy
    ) {
      return response.status(400).send({
        status: false,
        message: 'The selected driver does not exist. Please select a valid driver.',
      })
    }

    if (type === 'pickup') {
      const orders = await Order.query().whereIn('id', order_ids)

      const openAndPendingOrders = orders.filter((order) =>
        [OrderStatus.Open, OrderStatus.PendingPickup, OrderStatus.PickupException].includes(
          order.status
        )
      )

      if (openAndPendingOrders.length !== order_ids.length) {
        return response.status(400).send({
          status: false,
          message:
            'Some orders are not in Open or Pending Pickup status, cannot update pickup agent',
        })
      }

      await Order.query().whereIn('id', order_ids).update({
        status: OrderStatus.PendingPickup,
        status_for_customer: OrderStatusForCustomer.PendingPickup,
        is_pickup_driver_assigned: true,
        assigned_pickup_driver_id: driver_id,
        is_manuel_pickup_assign: true,
        is_pickup_exception_marked: false,
        initiate_pickup_after_exception: true,
      })

      await OrderPackage.query()
        .whereIn('order_id', order_ids)
        .where('is_picked_up', false)
        .update({
          status: PackageStatus.PendingPickup,
          is_pickup_driver_assigned: true,
          assigned_pickup_driver_id: driver_id,
        })

      for (const order of orders) {
        await createComprehensiveOrderHistory(
          order.id,
          auth?.user?.id as number,
          OrderHistoryActions.PickupAgentChanged,
          {},
          `🚚 Pickup driver (👨‍🦱: ${await UserNameById(driver_id)}) assigned manually by ${auth.user?.first_name} ${auth.user?.last_name}`
        )
      }

      return response.status(200).send({
        status: true,
        message: 'Pickup agents updated successfully',
      })
    } else if (type === 'delivery') {
      const orders = await Order.query().whereIn('id', order_ids)

      const pickedOrWarehouseOrders = orders.filter((order) =>
        [OrderStatus.PartialAtWarehouse, OrderStatus.AtWarehouse].includes(order.status)
      )

      if (pickedOrWarehouseOrders.length !== order_ids.length) {
        return response.status(400).send({
          status: false,
          message: 'Some orders are not in At Warehouse status, cannot update delivery agent',
        })
      }

      await Order.query().whereIn('id', order_ids).update({
        is_delivery_driver_assigned: true,
        assigned_delivery_driver_id: driver_id,
      })

      await OrderPackage.query()
        .whereIn('order_id', order_ids)
        .where('is_delivery_driver_assigned', false)
        .update({
          is_delivery_agent_assigned: true,
          assigned_delivery_agent_id: driver_id,
        })

      for (const order of orders) {
        await createComprehensiveOrderHistory(
          order.id,
          auth?.user?.id as number,
          OrderHistoryActions.DeliveryAgentChanged,
          {},
          `🚚 Delivery driver (👨‍🦱: ${await UserNameById(driver_id)}) assigned manually by ${auth.user?.first_name} ${auth.user?.last_name}`
        )
      }

      return response.status(200).send({
        status: true,
        message: 'Delivery agents updated successfully',
      })
    }
  }
}
