from dostadmin import db_model, app_logger, app
from utils import campaign_scheduler_utils, config_parser
from config import EXOTEL_CALLS_PERMITTED, SERVER_TYPE
import time


class CallAttemptService:
    def attempt_call(
        self,
        experience,
        campaign,
        pre_calculated_campaign_data,
        ignore_out_of_window_check=False,
    ):
        # We need to do a mandatory feature flag check which defines if the system
        # should be allowed to make Exotel calls
        with app.app_context():
            exotel_calls_allowed = config_parser.SystemConfigurationUtil.parse_config(
                EXOTEL_CALLS_PERMITTED
            )
            if (
                not exotel_calls_allowed
                or exotel_calls_allowed.value.upper() == "FALSE"
            ):
                # Terminate the process as call scheduling is disabled
                user_phone = experience.phone
                campaign_id = campaign.id
                error_message = f"Call scheduling failed for user phone {user_phone} and campaign id {campaign_id} due to disabled call scheduling in the {SERVER_TYPE} environment. Please enable it to schedule calls."

                app_logger.warning("Call attempt service: %s", error_message)
                return None

            campaign_id = campaign.id
            max_retry_flag = pre_calculated_campaign_data.max_retry_flag

            if not hasattr(campaign, "content_version"):
                content_version = db_model.content_version.ContentVersion.query.get_content_version_by_content_and_language_id(
                    campaign.content_id, experience.language_id
                )
                exotel_appid = content_version.exotel_appid
            else:
                exotel_appid = campaign.content_version.exotel_appid

            if ignore_out_of_window_check:
                time.sleep(
                    2
                )  # wait for 2 seconds before processing missed call callback

            provider_number = experience.provider_number[-10:]
            campaign_response = campaign_scheduler_utils.make_call(
                experience.phone,
                exotel_appid,
                campaign_id,
                provider_number,
                max_retry_flag,
                ignore_check=ignore_out_of_window_check,
            )

            self.update_campaign_response(
                campaign_response, campaign, pre_calculated_campaign_data, experience
            )

            return campaign_response

    def update_campaign_response(
        self, campaign_response, campaign, pre_calculated_campaign_data, experience
    ):
        with app.app_context():
            campaign.attempted_timestamp = campaign_response.get("attempted_timestamp")

            if campaign_response.get("connect"):
                app_logger.info(
                    f"Call Attempt Service: Got campaign response for phone {campaign.user_number} after attempting the call. Response: {campaign_response}."
                )
                campaign.callsid = campaign_response.get("callsid")
                campaign.call_status = campaign_response.get("call_status")
                campaign.call_start_time = campaign_response.get("call_start_time")
                campaign.provider_number = campaign_response.get("to_number")
                campaign.user_number = campaign_response.get("from_number")
            else:
                app_logger.warning(
                    f"Call Attempt Service: Campaign response failed for phone number {campaign.user_number} and campaign_id {campaign.id}. The response details are: {campaign_response}"
                )

                fail_status = campaign_response.get(
                    "fail_status", db_model.Campaign.Status.FAILED_SYSTEM
                )
                campaign.status = campaign_response.get("fail_status")
                if fail_status == db_model.Campaign.Status.FAILED_DND:
                    app_logger.info(
                        f"Marking experience id {campaign.experience_id} as DND for user phone number {campaign.user_number}."
                    )
                    db_model.Experience.update_experience_status(
                        experience, db_model.Experience.Status.DND_WAIT
                    )
                    pre_calculated_campaign_data.is_eligible_to_call = False

                if campaign.scheduled_by == db_model.Campaign.ScheduledBy.CRON_REGULAR:
                    pre_calculated_campaign_data.previous_regular_campaign_status = (
                        campaign.status
                    )
                elif (
                    campaign.scheduled_by
                    == db_model.Campaign.ScheduledBy.CRON_MISSED_CALL
                ):
                    pre_calculated_campaign_data.previous_missed_call_campaign_status = (
                        campaign.status
                    )
                elif campaign.scheduled_by == db_model.Campaign.ScheduledBy.CRON_NUDGE:
                    pre_calculated_campaign_data.previous_nudge_campaign_status = (
                        campaign.status
                    )
                elif campaign.scheduled_by == db_model.Campaign.ScheduledBy.UI_MANUAL:
                    pre_calculated_campaign_data.previous_blast_call_campaign_status = (
                        campaign.status
                    )
