import IntlCourierRate from '#models/intl_courier_rate'
import IntlCourierRateGroup from '#models/intl_courier_rate_group'
import {
  calculateIntlShippingRateValidator,
  createIntlCourierRateValidator,
  createIntlRateGroupValidator,
  deleteIntlCourierRateValidator,
  deleteIntlRateGroupValidator,
  intlCourierRateIndividualDetailsValidator,
  intlRateGroupDetailsValidator,
  listAllIntlRateGroupsValidator,
  listIntlCourierRateValidator,
  listIntlRateGroupValidator,
  statusUpdateIntlRateGroupValidator,
  updateIntlCourierRateValidator,
  updateIntlRateGroupValidator,
} from '#validators/international_rate'
import type { HttpContext } from '@adonisjs/core/http'
import { IntlCouriers, IntlCouriersRateType } from '../../types/enum.js'
import Customer from '#models/customer'

export default class InternationalRatesController {
  async calculateIntlShippingRate({ request, response }: HttpContext) {
    const { rate, courier, customer_id, weight } = await request.validateUsing(
      calculateIntlShippingRateValidator
    )

    const customerDetails = await Customer.query()
      .where('id', customer_id)
      .preload('intl_courier_rate_group_details', (groupQuery) => {
        groupQuery.where('is_active', true)
        groupQuery.preload('intl_courier_rate_details', (rateQuery) => {
          rateQuery
            .where('weight_from', '<=', weight)
            .andWhere('weight_to', '>', weight)
            .where('courier', courier as IntlCouriers)
        })
      })
      .first()

    let intlCourierRate =
      customerDetails?.intl_courier_rate_group_details?.intl_courier_rate_details?.[0]

    if (!intlCourierRate) {
      const data = await IntlCourierRateGroup.query()
        .where('is_default', true)
        .andWhere('is_active', true)
        .whereHas('intl_courier_rate_details', (rateQuery) => {
          rateQuery
            .where('weight_from', '<=', weight)
            .andWhere('weight_to', '>', weight)
            .where('courier', courier as IntlCouriers)
        })
        .preload('intl_courier_rate_details', (rateQuery) => {
          rateQuery
            .where('weight_from', '<=', weight)
            .andWhere('weight_to', '>', weight)
            .where('courier', courier as IntlCouriers)
            .first()
        })
        .first()

      intlCourierRate = data?.intl_courier_rate_details?.[0]
    }

    if (!intlCourierRate) {
      return response.status(404).json({ message: 'Rate not found' })
    }

    // const defaultRateGroup = await IntlCourierRateGroup.query()
    //   .where('is_default', true)
    //   .andWhere('is_active', true)
    //   .first()

    // if (!defaultRateGroup) {
    //   return response.status(404).json({ message: 'Default rate group not found' })
    // }

    // const rateRecord = await IntlCourierRate.query()
    //   .where('intl_courier_rate_group_id', defaultRateGroup.id)
    //   .where('weight_from', '<=', weight)
    //   .andWhere('weight_to', '>', weight)
    //   .where('courier', courier as IntlCouriers)
    //   .first()

    // if (!rateRecord) {
    //   return response.status(404).json({ message: 'Rate not found' })
    // }

    let calculatedRate: { courierRate: number; margin: number; finalRate: number } = {
      courierRate: rate,
      margin: 0,
      finalRate: rate,
    }

    switch (intlCourierRate.rate_type) {
      case IntlCouriersRateType.Addition:
        const additionMargin = Number(intlCourierRate.value)
        calculatedRate.margin = additionMargin
        calculatedRate.finalRate = rate + additionMargin

        break

      case IntlCouriersRateType.Percentage:
        const percentageMargin = (rate * Number(intlCourierRate.value)) / 100
        calculatedRate.margin = percentageMargin
        calculatedRate.finalRate = rate + percentageMargin

        break

      case IntlCouriersRateType.Multiplication:
        const multiplicationValue = Number(intlCourierRate.value)
        calculatedRate.margin = 0
        calculatedRate.finalRate = weight * multiplicationValue

        break
    }

    return response.json({
      status: true,
      data: calculatedRate,
    })
  }

  async listIntlRateGroup({ request, response }: HttpContext) {
    const {
      page = 1,
      limit = 10,
      filter_by_is_active,
      search,
      sort_by_is_active,
      sort_by_name,
      sort_by_created_at,
      sort_by_updated_at,
      sort_by_id,
      sort_by_price_id,
    } = await request.validateUsing(listIntlRateGroupValidator)

    const intlRateGroup = await IntlCourierRateGroup.query()
      .if(filter_by_is_active?.length, (query) => {
        query.whereIn('is_active', filter_by_is_active as number[])
      })
      .if(search, (query) => {
        query.where('name', 'like', `%${search}%`).orWhere('price_id', 'like', `%${search}%`)
      })
      .if(sort_by_is_active, (query) => {
        query.orderBy('is_active', sort_by_is_active)
      })
      .if(sort_by_name, (query) => {
        query.orderBy('name', sort_by_name)
      })
      .if(sort_by_created_at, (query) => {
        query.orderBy('created_at', sort_by_created_at)
      })
      .if(sort_by_updated_at, (query) => {
        query.orderBy('updated_at', sort_by_updated_at)
      })
      .if(sort_by_id, (query) => {
        query.orderBy('id', sort_by_id)
      })
      .if(sort_by_price_id, (query) => {
        query.orderBy('price_id', sort_by_price_id)
      })
      .if(
        !sort_by_is_active &&
          !sort_by_name &&
          !sort_by_created_at &&
          !sort_by_updated_at &&
          !sort_by_id &&
          !sort_by_price_id,
        (query) => {
          query.orderBy('id', 'asc')
        }
      )
      .paginate(page, limit)

    return response.ok({
      status: true,
      message: 'International Rate Groups fetched successfully',
      data: intlRateGroup,
    })
  }

  async listAllIntlRateGroups({ request, response }: HttpContext) {
    const { search } = await request.validateUsing(listAllIntlRateGroupsValidator)

    const intlRateGroups = await IntlCourierRateGroup.query()
      .if(search, (query) => {
        query.where('name', 'like', `%${search}%`).orWhere('price_id', 'like', `%${search}%`)
      })
      .select('id', 'price_id', 'name')
      .orderBy('name', 'asc')

    return response.ok({
      status: true,
      message: 'International Rate Groups fetched successfully',
      data: intlRateGroups,
    })
  }

  async intlRateGroupDetails({ request, response }: HttpContext) {
    const { id } = await request.validateUsing(intlRateGroupDetailsValidator)

    const intlRateGroup = await IntlCourierRateGroup.query()
      .where('id', id)
      .preload('intl_courier_rate_details')
      .first()

    return response.ok({
      status: true,
      message: 'International Rate Group details fetched successfully',
      data: intlRateGroup,
    })
  }

  async createIntlRateGroup({ request, response }: HttpContext) {
    const payload = await request.validateUsing(createIntlRateGroupValidator)

    await IntlCourierRateGroup.create(payload)

    return response.created({
      status: true,
      message: 'International Rate Group created successfully',
    })
  }

  async updateIntlRateGroup({ request, response }: HttpContext) {
    const payload = await request.validateUsing(updateIntlRateGroupValidator)
    console.log(payload)

    await IntlCourierRateGroup.query().where('id', payload.id).update(payload)

    return response.ok({
      status: true,
      message: 'International Rate Group updated successfully',
    })
  }

  async deleteIntlRateGroup({ request, response }: HttpContext) {
    const { id } = await request.validateUsing(deleteIntlRateGroupValidator)

    const intlCourierRateGroup = await IntlCourierRateGroup.query().where('id', id).firstOrFail()

    if (intlCourierRateGroup.is_default) {
      return response.status(400).json({
        status: false,
        message: 'Default International Rate Group cannot be deleted',
      })
    }

    await intlCourierRateGroup.related('intl_courier_rate_details').query().delete()

    await IntlCourierRateGroup.query().where('id', id).delete()

    return response.ok({
      status: true,
      message: 'International Rate Group deleted successfully',
    })
  }

  async statusUpdateIntlRateGroup({ request, response }: HttpContext) {
    const { id, is_active } = await request.validateUsing(statusUpdateIntlRateGroupValidator)

    await IntlCourierRateGroup.query().where('id', id).update({ is_active })

    return response.ok({
      status: true,
      message: 'International Rate Group status updated successfully',
    })
  }

  async listIntlCourierRate({ request, response }: HttpContext) {
    const {
      page = 1,
      limit = 10,
      filter_by_intl_courier_rate_group_id,
      filter_by_courier,
      filter_by_rate_type,
    } = await request.validateUsing(listIntlCourierRateValidator)

    const intlCourierRate = await IntlCourierRate.query()
      .where('intl_courier_rate_group_id', filter_by_intl_courier_rate_group_id)
      .if(filter_by_courier !== undefined, (query) => {
        query.whereIn('courier', filter_by_courier as IntlCouriers[])
      })
      .if(filter_by_rate_type !== undefined, (query) => {
        query.whereIn('rate_type', filter_by_rate_type as IntlCouriersRateType[])
      })
      .paginate(page, limit)

    return response.ok({
      status: true,
      message: 'International Courier Rates fetched successfully',
      data: intlCourierRate,
    })
  }

  async intlCourierRateIndividualDetails({ request, response }: HttpContext) {
    const { courier_id, intl_courier_rate_group_id } = await request.validateUsing(
      intlCourierRateIndividualDetailsValidator
    )

    const intlCourierRate = await IntlCourierRate.query()
      .where('courier', courier_id as IntlCouriers)
      .andWhere('intl_courier_rate_group_id', intl_courier_rate_group_id)
      .orderBy('weight_from', 'asc')

    return response.ok({
      status: true,
      message: 'International Courier Rate details fetched successfully',
      data: intlCourierRate,
    })
  }

  async createIntlCourierRate({ request, response }: HttpContext) {
    const { intl_courier_rate_group_id, courier, weight_from, weight_to, rate_type, value } =
      await request.validateUsing(createIntlCourierRateValidator)

    const isExistingRate = await IntlCourierRate.query()
      .where('intl_courier_rate_group_id', intl_courier_rate_group_id)
      .andWhere('courier', courier)
      .where((query) => {
        query.where('weight_from', '<', weight_to).andWhere('weight_to', '>', weight_from)
      })
      .first()

    if (isExistingRate) {
      return response.status(400).json({
        status: false,
        message:
          'An international courier rate with the same group, courier, and weight range already exists.',
      })
    }

    await IntlCourierRate.create({
      intl_courier_rate_group_id,
      courier,
      weight_from,
      weight_to,
      rate_type,
      value,
    })

    return response.created({
      status: true,
      message: 'International Courier Rate created successfully',
    })
  }

  async updateIntlCourierRate({ request, response }: HttpContext) {
    const { id, ...payload } = await request.validateUsing(updateIntlCourierRateValidator)

    await IntlCourierRate.query().where('id', id).update(payload)

    return response.ok({
      status: true,
      message: 'International Courier Rate updated successfully',
    })
  }

  async deleteIntlCourierRate({ request, response }: HttpContext) {
    const { id } = await request.validateUsing(deleteIntlCourierRateValidator)

    await IntlCourierRate.query().where('id', id).delete()

    return response.ok({
      status: true,
      message: 'International Courier Rate deleted successfully',
    })
  }
}
