# Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/

class ChannelsCdrVoiceController < 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: 'Voice::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: 'Voice::Number',
        options: {
          phone_number: params[:phone_number],
          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: 'Voice::Number')
    begin
      channel.options[:phone_number] = params[:phone_number]
      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: 'Voice::Number')
    channel.options[:token] = SecureRandom.urlsafe_base64(48)
    channel.save!
    render json: {}
  end

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

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

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

  def channel_for_token(token)
    return false unless token

    Channel.where(area: 'Voice::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
       duration
       startTime
       endTime
       recording
       mimeType
       callSid].each do |field|
      errors[field] = 'required' if params[field].blank?
    end

    valid_mimetypes = ['audio/mpeg']
    unless valid_mimetypes.include?(params[:mimeType])
      errors[:mimeType] = "invalid. must be one of #{valid_mimetypes.join(',')}"
    end

    receiver_phone_number = params[:to]

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

    caller_phone_number = params[:from].strip

    customer = User.find_by(phone: caller_phone_number)
    customer ||= User.find_by(mobile: caller_phone_number)
    unless customer
      role_ids = Role.signup_role_ids
      customer = User.create(
        firstname: '',
        lastname: '',
        email: '',
        password: '',
        phone: caller_phone_number,
        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)
    unless group.present?
      Rails.logger.error "Voice channel #{channel_id} paired with Group #{channel.group_id}, but group does not exist!"
      return render json: { error: 'There was an error during voice 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 "Voice channel #{channel_id} paired with Organization #{organization_id}, but organization does not exist!"
        return render json: { error: 'There was an error during voice submission' }, status: 500
      end
      unless customer.organization_id.present?
        customer.organization_id = organization.id
        customer.save!
      end
    end

    call_id = params[:calLSid]
    duration = params[:duration]
    start_time = params[:startTime]
    end_time = params[:endTime]
    recording_data_base64 = params[:recording]
    recording_filename = "phone-call-#{start_time}-#{call_id}.mp3"
    recording_mimetype = params[:mimeType]

    title = "Call from #{caller_phone_number} at #{start_time}"
    body = %(
    <ul>
    <li>Caller: #{caller_phone_number}</li>
    <li>Service Number: #{receiver_phone_number}</li>
    <li>Call Duration: #{duration} seconds</li>
    <li>Start Time: #{start_time}</li>
    <li>End Time: #{end_time}</li>
    </ul>
    <p>See the attached recording.</p>
)

    ticket_params = {
      group_id: group.id,
      customer_id: customer.id,
      title: title,
      preferences: {},
      note: 'This ticket was created from a recorded voice message.'
    }

    article_params = {
      sender: 'Customer',
      subject: title,
      body: body,
      content_type: 'text/html',
      type: 'note',
      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' => recording_filename,
          :filename => recording_filename,
          :data => recording_data_base64,
          'data' => recording_data_base64,
          'mime-type' => recording_mimetype
        }
      ]
    }

    clean_params = Ticket.param_cleanup(ticket_params, true)
    ticket = Ticket.new(clean_params)

    ticket.save!
    ticket.with_lock do
      article_params[:sender] = 'Customer'
      article_create(ticket, article_params)
    end

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

    render json: result, status: :ok
  end
end
