# frozen_string_literal: true

class ChannelsCdrSignalController < ApplicationController
  prepend_before_action -> { authentication_check && authorize! }, except: [:webhook]
  skip_before_action :verify_csrf_token, only: [:webhook]

  include CreatesTicketArticles

  def index
    assets = {}
    channel_ids = []
    Channel.where(area: 'Signal::Number').order(:id).each do |channel|
      assets = channel.assets(assets)
      channel_ids.push channel.id
    end
    render json: {
      assets: assets,
      channel_ids: channel_ids
    }
  end

  def add
    begin
      errors = {}
      errors['group_id'] = 'required' unless params[:group_id].present?

      if errors.present?
        render json: {
          errors: errors
        }, status: :bad_request
        return
      end
      channel = Channel.create(
        area: 'Signal::Number',
        options: {
          adapter: 'cdr_signal',
          phone_number: params[:phone_number],
          bot_token: params[:bot_token],
          bot_endpoint: params[:bot_endpoint],
          token: SecureRandom.urlsafe_base64(48),
          organization_id: params[:organization_id]
        },
        group_id: params[:group_id],
        active: true
      )
    rescue StandardError => e
      raise Exceptions::UnprocessableEntity, e.message
    end
    render json: channel
  end

  def update
    errors = {}
    errors['group_id'] = 'required' unless params[:group_id].present?

    if errors.present?
      render json: {
        errors: errors
      }, status: :bad_request
      return
    end
    channel = Channel.find_by(id: params[:id], area: 'Signal::Number')
    begin
      channel.options[:phone_number] = params[:phone_number]
      channel.options[:bot_token] = params[:bot_token]
      channel.options[:bot_endpoint] = params[:bot_endpoint]
      channel.options[:organization_id] = params[:organization_id]
      channel.group_id = params[:group_id]
      channel.save!
    rescue StandardError => e
      raise Exceptions::UnprocessableEntity, e.message
    end
    render json: channel
  end

  def rotate_token
    channel = Channel.find_by(id: params[:id], area: 'Signal::Number')
    channel.options[:token] = SecureRandom.urlsafe_base64(48)
    channel.save!
    render json: {}
  end

  def enable
    channel = Channel.find_by(id: params[:id], area: 'Signal::Number')
    channel.active = true
    channel.save!
    render json: {}
  end

  def disable
    channel = Channel.find_by(id: params[:id], area: 'Signal::Number')
    channel.active = false
    channel.save!
    render json: {}
  end

  def destroy
    channel = Channel.find_by(id: params[:id], area: 'Signal::Number')
    channel.destroy
    render json: {}
  end

  def channel_for_token(token)
    return false unless token

    Channel.where(area: 'Signal::Number').each do |channel|
      return channel if channel.options[:token] == token
    end
    false
  end

  def webhook
    token = params['token']
    return render json: {}, status: 401 unless token

    channel = channel_for_token(token)
    return render json: {}, status: 401 if !channel || !channel.active
    return render json: {}, status: 401 if channel.options[:token] != token

    channel_id = channel.id

    # validate input
    errors = {}

    #    %i[to
    #       from
    #       message_id
    #       sent_at].each | field |
    #      (errors[field] = 'required' if params[field].blank?)

    if errors.present?
      render json: {
        errors: errors
      }, status: :bad_request
      return
    end

    message_id = params[:message_id]

    return if Ticket::Article.exists?(message_id: "cdr_signal.#{message_id}")

    receiver_phone_number = params[:to].strip
    sender_phone_number = params[:from].strip
    customer = User.find_by(phone: sender_phone_number)
    customer ||= User.find_by(mobile: sender_phone_number)
    unless customer
      role_ids = Role.signup_role_ids
      customer = User.create(
        firstname: '',
        lastname: '',
        email: '',
        password: '',
        phone: sender_phone_number,
        note: 'CDR Signal',
        active: true,
        role_ids: role_ids,
        updated_by_id: 1,
        created_by_id: 1
      )
    end

    # set current user
    UserInfo.current_user_id = customer.id
    current_user_set(customer, 'token_auth')

    group = Group.find_by(id: channel.group_id)
    if group.blank?
      Rails.logger.error "Signal channel #{channel_id} paired with Group #{channel.group_id}, but group does not exist!"
      return render json: { error: 'There was an error during Signal submission' }, status: 500
    end

    organization_id = channel.options['organization_id']
    if organization_id.present?
      organization = Organization.find_by(id: organization_id)
      unless organization.present?
        Rails.logger.error "Signal channel #{channel_id} paired with Organization #{organization_id}, but organization does not exist!"
        return render json: { error: 'There was an error during Signal submission' }, status: 500
      end
      unless customer.organization_id.present?
        customer.organization_id = organization.id
        customer.save!
      end
    end

    message = params[:message] ||= 'No text content'
    sent_at = params[:sent_at]
    attachment_data_base64 = params[:attachment]
    attachment_filename = params[:filename]
    attachment_mimetype = params[:mime_type]
    title = "Message from #{sender_phone_number} at #{sent_at}"
    body = message

    # find ticket or create one
    state_ids = Ticket::State.where(name: %w[closed merged removed]).pluck(:id)
    ticket = Ticket.where(customer_id: customer.id).where.not(state_id: state_ids).order(:updated_at).first
    if ticket
      # check if title need to be updated
      ticket.title = title if ticket.title == '-'
      new_state = Ticket::State.find_by(default_create: true)
      ticket.state = Ticket::State.find_by(default_follow_up: true) if ticket.state_id != new_state.id
    else
      ticket = Ticket.new(
        group_id: channel.group_id,
        title: title,
        customer_id: customer.id,
        preferences: {
          channel_id: channel.id,
          cdr_signal: {
            bot_token: channel.options[:bot_token], # change to bot id
            chat_id: sender_phone_number
          }
        }
      )
    end

    ticket.save!

    article_params = {
      from: sender_phone_number,
      to: receiver_phone_number,
      sender_id: Ticket::Article::Sender.find_by(name: 'Customer').id,
      subject: title,
      body: body,
      content_type: 'text/plain',
      message_id: "cdr_signal.#{message_id}",
      ticket_id: ticket.id,
      internal: false,
      preferences: {
        cdr_signal: {
          timestamp: sent_at,
          message_id: message_id,
          from: sender_phone_number
        }
      }
    }

    if attachment_data_base64.present?
      article_params[:attachments] = [
        # i don't even...
        # this is necessary because of what's going on in controllers/concerns/creates_ticket_articles.rb
        # we need help from the ruby gods
        {
          'filename' => attachment_filename,
          :filename => attachment_filename,
          :data => attachment_data_base64,
          'data' => attachment_data_base64,
          'mime-type' => attachment_mimetype
        }
      ]
    end

    ticket.with_lock do
      ta = article_create(ticket, article_params)
      ta.update!(type_id: Ticket::Article::Type.find_by(name: 'cdr_signal').id)
    end

    ticket.update!(create_article_type_id: Ticket::Article::Type.find_by(name: 'cdr_signal').id)

    result = {
      ticket: {
        id: ticket.id,
        number: ticket.number
      }
    }

    render json: result, status: :ok
  end
end
