import type { HttpContext } from '@adonisjs/core/http'
import Webhook from '#models/webhook'
import {
  createWebhookValidator,
  updateWebhookValidator,
  listWebhooksValidator,
  updateWebhookStatusValidator,
  createByCustomerWebhookValidator,
  updateByCustomerWebhookValidator,
  updateByCustomerWebhookStatusValidator,
} from '#validators/webhook'

export default class WebhooksController {
  async listByCustomer({ auth, response }: HttpContext) {
    const customer = auth.use('customer').user
    if (!customer) return response.unauthorized({ status: false, message: 'Unauthorized' })

    const webhooks = await Webhook.query().where('customer_id', customer.id)
    return response.ok({
      status: true,
      message: 'Webhook listed successfully',
      data: webhooks.map((w) => w.toJSON()),
    })
  }

  async createByCustomer({ auth, request, response }: HttpContext) {
    const customer = auth.use('customer').user
    if (!customer) return response.unauthorized({ status: false, message: 'Unauthorized' })

    const payload = await request.validateUsing(createByCustomerWebhookValidator)

    let webhook = await Webhook.query().where('customer_id', customer.id).first()

    if (webhook) {
      webhook.merge(payload)
      await webhook.save()

      return response.ok({
        status: true,
        message: 'Webhook updated successfully',
        data: webhook.toJSON(),
      })
    } else {
      webhook = await Webhook.create({
        ...payload,
        customer_id: customer.id,
        user_id: null,
      })

      return response.created({
        status: true,
        message: 'Webhook created successfully',
        data: webhook.toJSON(),
      })
    }
  }

  async updateByCustomer({ auth, request, response, params }: HttpContext) {
    const customer = auth.use('customer').user
    if (!customer) return response.unauthorized({ status: false, message: 'Unauthorized' })

    const webhook = await Webhook.query()
      .where('id', params.id)
      .where('customer_id', customer.id)
      .firstOrFail()

    const payload = await request.validateUsing(updateByCustomerWebhookValidator)
    webhook.merge(payload)
    await webhook.save()

    return response.ok({
      status: true,
      message: 'Webhook updated successfully',
      data: webhook.toJSON(),
    })
  }

  async updateStatusByCustomer({ auth, request, response, params }: HttpContext) {
    const customer = auth.use('customer').user
    if (!customer) return response.unauthorized({ status: false, message: 'Unauthorized' })

    const webhook = await Webhook.query()
      .where('id', params.id)
      .where('customer_id', customer.id)
      .firstOrFail()

    const { is_active: isActive } = await request.validateUsing(
      updateByCustomerWebhookStatusValidator
    )
    webhook.is_active = isActive
    await webhook.save()

    return response.ok({
      status: true,
      message: 'Webhook status updated successfully',
      data: webhook.toJSON(),
    })
  }

  async deleteByCustomer({ auth, response, params }: HttpContext) {
    const customer = auth.use('customer').user
    if (!customer) return response.unauthorized({ status: false, message: 'Unauthorized' })

    const webhook = await Webhook.query()
      .where('id', params.id)
      .where('customer_id', customer.id)
      .firstOrFail()

    await webhook.delete()
    return response.ok({ status: true, message: 'Webhook deleted successfully' })
  }

  async listByAdmin({ request, response }: HttpContext) {
    const {
      customer_id: customerId,
      user_id: userId,
      page = 1,
      limit = 10,
    } = await request.validateUsing(listWebhooksValidator)

    const query = Webhook.query()
    if (customerId) query.where('customer_id', customerId)
    if (userId) query.where('user_id', userId)

    const webhooks = await query
      .preload('customer_details')
      .preload('user_details')
      .paginate(page, limit)
    return response.ok({
      status: true,
      message: 'Webhook listed successfully',
      data: webhooks.toJSON(),
    })
  }

  async detailsByAdmin({ response, params }: HttpContext) {
    try {
      const webhook = await Webhook.query()
        .where('id', params.id)
        .preload('customer_details')
        .preload('user_details')
        .firstOrFail()

      return response.ok({
        status: true,
        message: 'Webhook details retrieved successfully',
        data: webhook.toJSON(),
      })
    } catch (error) {
      if (error.code === 'E_ROW_NOT_FOUND') {
        return response.notFound({ status: false, message: 'Webhook not found' })
      }
      return response.internalServerError({
        status: false,
        message: 'Failed to retrieve webhook details',
        error: error.message,
        code: error.code,
      })
    }
  }

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

    let webhook: Webhook | null = null

    if (payload.customer_id) {
      webhook = await Webhook.query().where('customer_id', payload.customer_id).first()
    } else if (payload.user_id) {
      webhook = await Webhook.query().where('user_id', payload.user_id).first()
    }

    if (webhook) {
      webhook.merge(payload)
      await webhook.save()

      return response.ok({
        status: true,
        message: 'Webhook updated successfully',
        data: webhook.toJSON(),
      })
    } else {
      webhook = await Webhook.create(payload)
      return response.created({
        status: true,
        message: 'Webhook created successfully',
        data: webhook.toJSON(),
      })
    }
  }

  async updateByAdmin({ request, response, params }: HttpContext) {
    const webhook = await Webhook.findOrFail(params.id)
    const payload = await request.validateUsing(updateWebhookValidator)
    webhook.merge(payload)
    await webhook.save()
    return response.ok({
      status: true,
      message: 'Webhook updated successfully',
      data: webhook.toJSON(),
    })
  }

  async updateStatusByAdmin({ request, response, params }: HttpContext) {
    const webhook = await Webhook.findOrFail(params.id)
    const { is_active: isActive } = await request.validateUsing(updateWebhookStatusValidator)
    webhook.is_active = isActive
    await webhook.save()
    return response.ok({
      status: true,
      message: 'Webhook status updated successfully',
      data: webhook.toJSON(),
    })
  }

  async deleteByAdmin({ response, params }: HttpContext) {
    const webhook = await Webhook.findOrFail(params.id)
    await webhook.delete()
    return response.ok({ status: true, message: 'Webhook deleted successfully' })
  }
}
