import time

import pytest
from pypom import Region, Page

from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC

# from pages.desktop.developers.submit_addon import SubmitAddon


class ManageVersions(Page):
    _addon_name_title_locator = (By.CSS_SELECTOR, 'div[class="section"] header h2')
    _listing_visibility_section_locator = (
        By.CSS_SELECTOR,
        "#edit-addon h3:nth-child(1)",
    )
    _visible_listing_radio_locator = (By.CSS_SELECTOR, 'input[value="listed"]')
    _visible_explainer_text_locator = (
        By.CSS_SELECTOR,
        "#addon-current-state label:nth-child(1)",
    )
    _invisible_listing_radio_locator = (By.CSS_SELECTOR, 'input[value="hidden"]')
    _invisible_explainer_text_locator = (
        By.CSS_SELECTOR,
        "#addon-current-state label:nth-of-type(2)",
    )
    _hide_addon_confirmation_text_locator = (
        By.CSS_SELECTOR,
        "#modal-disable p:nth-child(1)",
    )
    _hide_addon_button_locator = (By.CSS_SELECTOR, "#modal-disable p button")
    _hide_addon_cancel_link_locator = (By.CSS_SELECTOR, "#modal-disable p a")

    _disabled_by_mozilla_locator = (By.CSS_SELECTOR, ".file-status > div")
    _incomplete_status_locator = (By.CSS_SELECTOR, ".status-incomplete b")
    _invisible_status_locator = (By.CSS_SELECTOR, ".status-disabled b")
    _addon_listed_status_locator = (By.CSS_SELECTOR, ".addon-listed-status b")
    _delete_addon_button_locator = (By.CLASS_NAME, "delete-button.delete-addon")
    _upload_new_version_locator = (By.CSS_SELECTOR, ".button.version-upload")

    # Version List Section
    _version_list_locator = (By.ID, "version-list")
    _current_version_status_locator = (
        By.CSS_SELECTOR,
        "#current-version-status .file-status > div:nth-child(1)",
    )
    _version_approval_status_locator = (
        By.CSS_SELECTOR,
        "#version-list .file-status div:nth-child(1)",
    )
    _disable_delete_version_button_locator = (By.CSS_SELECTOR, ".version-delete a")
    _delete_version_help_text_locator = (By.CSS_SELECTOR, ".current-version-warning")
    _delete_version_warning_locator = (By.CSS_SELECTOR, ".highlight.warning")
    _delete_version_button_locator = (By.CSS_SELECTOR, ".modal-actions .delete-button")
    _disable_version_button_locator = (
        By.CSS_SELECTOR,
        ".modal-actions .disable-button",
    )
    _cancel_disable_version_link_locator = (By.CSS_SELECTOR, ".modal-actions .close")
    _enable_version_button_locator = (By.CSS_SELECTOR, ".file-status button")
    _cancel_request_review_button_locator = (By.ID, "cancel-review")
    _request_review_button_locator = (By.CSS_SELECTOR, ".version-status-actions > form")


    @staticmethod
    def open_manage_versions_page_for_addon(selenium, base_url, addon):
        return selenium.get(f"{base_url}/developers/addon/{addon}/versions")

    def wait_for_page_to_load(self):
        self.wait.until(EC.visibility_of_element_located(self._version_list_locator))
        return self

    @property
    def version_page_title(self):
        self.wait.until(
            EC.visibility_of_element_located(self._addon_name_title_locator)
        )
        return self.find_element(*self._addon_name_title_locator).text

    @property
    def listing_visibility_section(self):
        self.wait.until(
            EC.visibility_of_element_located(self._listing_visibility_section_locator)
        )
        return self.find_element(*self._listing_visibility_section_locator).text

    @property
    def cancel_request_review_button(self):
        self.wait.until(
            EC.visibility_of_element_located(self._cancel_request_review_button_locator)
        )
        return self.find_element(*self._cancel_request_review_button_locator)

    @property
    def request_review_button(self):
        self.wait.until(
            EC.visibility_of_element_located(self._request_review_button_locator)
        )
        return self.find_element(*self._request_review_button_locator)

    def click_request_review_button(self):
        self.wait.until(
            EC.visibility_of_element_located(self._request_review_button_locator)
        )
        return self.find_element(*self._request_review_button_locator).click()

    def click_visible_radio_button(self):
        self.wait.until(
            EC.visibility_of_element_located(self._visible_listing_radio_locator)
        )
        return self.find_element(*self._visible_listing_radio_locator).click()

    def click_upload_new_version_button(self):
        self.wait.until(
            EC.visibility_of_element_located(self._upload_new_version_locator)
        )
        return self.find_element(*self._upload_new_version_locator).click()


    def set_addon_visible(self):
        """Selects the Visible option and checks that the radio button is selected"""
        el = self.find_element(*self._visible_listing_radio_locator)
        el.click()
        assert el.is_selected()

    @property
    def incomplete_status_text(self):
        self.wait.until(
            EC.visibility_of_element_located(self._incomplete_status_locator)
        )
        return self.find_element(*self._incomplete_status_locator)

    @property
    def disabled_by_mozilla_text(self):
        self.wait.until(
            EC.visibility_of_element_located(self._disabled_by_mozilla_locator)
        )
        return self.find_element(*self._disabled_by_mozilla_locator)

    @property
    def visible_status_explainer(self):
        self.wait.until(
            EC.visibility_of_element_located(self._visible_explainer_text_locator)
        )
        return self.find_element(*self._visible_explainer_text_locator).text

    @property
    def invisible_status_explainer(self):
        self.wait.until(
            EC.visibility_of_element_located(self._invisible_explainer_text_locator)
        )
        return self.find_element(*self._invisible_explainer_text_locator).text

    def set_addon_invisible(self):
        """Selects the Invisible option and checks that the radio button is selected"""
        el = self.find_element(*self._invisible_listing_radio_locator)
        el.click()
        self.wait.until(
            EC.element_to_be_clickable(
                (By.CSS_SELECTOR, "#modal-disable p:nth-child(1)")
            )
        )

    def click_hide_addon(self):
        self.find_element(*self._hide_addon_button_locator).click()

    @property
    def hide_addon_confirmation_text(self):
        self.wait.until(
            EC.visibility_of_element_located(self._hide_addon_confirmation_text_locator)
        )
        return self.find_element(*self._hide_addon_confirmation_text_locator).text

    def cancel_hide_addon_process(self):
        """Cancel the hide addon process and check that the Visible radio button is still selected"""
        self.find_element(*self._hide_addon_cancel_link_locator).click()
        assert self.find_element(*self._visible_listing_radio_locator).is_selected()

    @property
    def addon_listed_status(self):
        self.wait.until(
            EC.visibility_of_element_located(self._addon_listed_status_locator)
        )
        return self.find_element(*self._addon_listed_status_locator).text

    @property
    def incomplete_status(self):
        self.wait.until(
            EC.visibility_of_element_located(self._incomplete_status_locator)
        )
        return self.find_element(*self._incomplete_status_locator)

    @property
    def current_version_status(self):
        self.wait.until(
            EC.visibility_of_element_located(self._current_version_status_locator)
        )
        return self.find_element(*self._current_version_status_locator).text

    @property
    def version_approval_status(self):
        self.wait.until(
            EC.visibility_of_element_located(self._version_approval_status_locator)
        )
        return self.find_elements(*self._version_approval_status_locator)

    def click_delete_disable_version(self):
        self.find_element(*self._disable_delete_version_button_locator).click()
        self.wait.until(
            EC.element_to_be_clickable(
                (By.CSS_SELECTOR, ".modal-actions .delete-button")
            ),
            message="The Delete/Disable modal was not opened",
        )

    @property
    def delete_disable_version_helptext(self):
        self.wait.until(
            EC.visibility_of_element_located(self._delete_version_help_text_locator)
        )
        return self.find_element(*self._delete_version_help_text_locator).text

    @property
    def delete_disable_version_warning(self):
        self.wait.until(
            EC.visibility_of_element_located(self._delete_version_warning_locator)
        )
        return self.find_element(*self._delete_version_warning_locator).text

    def click_delete_version_button(self):
        self.wait.until(EC.element_to_be_clickable(self._delete_version_button_locator))
        self.find_element(*self._delete_version_button_locator).click()

    def click_disable_version_button(self):
        self.wait.until(
            EC.element_to_be_clickable(self._disable_version_button_locator)
        )
        self.find_element(*self._disable_version_button_locator).click()

    def click_cancel_version_delete_link(self):
        self.wait.until(
            EC.element_to_be_clickable(self._cancel_disable_version_link_locator)
        )
        return self.find_element(*self._cancel_disable_version_link_locator).click()

    def click_enable_version(self):
        """Allows developers to re-enable a version that was previously disabled"""
        self.wait.until(EC.element_to_be_clickable(self._enable_version_button_locator))
        self.find_element(*self._enable_version_button_locator).click()

    def wait_for_version_autoapproval(self, value):
        """Method that verifies if auto-approval occurs within a set time"""
        timeout_start = time.time()
        # auto-approvals should normally take ~5 minutes;
        # set a loop to verify if approval occurs within this interval
        while time.time() < timeout_start + 420:
            # refresh the page to check if the status has changed
            self.driver.refresh()
            if value not in self.version_approval_status[0].text:
                # wait 30 seconds before we refresh again
                time.sleep(30)
            # break the loop if the status changed to the expected value within set time
            else:
                break
        # if auto-approval took longer than normal, we want to fail the test and capture the final status
        else:
            pytest.fail(
                f"Autoapproval took longer than normal; "
                f'Addon final status was "{self.version_approval_status[0].text}" instead of "{value}"'
            )

    def delete_addon(self):
        self.find_element(*self._delete_addon_button_locator).click()
        return self.DeleteAddonModal(self).wait_for_region_to_load()

    def click_cancel_review_request(self):
        self.find_element(*self._cancel_request_review_button_locator).click()
        return self.CancelReviewRequestModal(self).wait_for_region_to_load()

    def invisible_status_text(self):
        self.wait.until(
            EC.visibility_of_element_located(
                self._invisible_status_locator
            )
        )
        return self.find_element(*self._invisible_status_locator).text

    class CancelReviewRequestModal(Region):
        _root_locator = (By.ID, 'modal-cancel')
        _are_you_sure_message_locator = (By.CSS_SELECTOR, '#modal-cancel > form:nth-child(1) > p:nth-child(3)')
        _cancel_your_review_request_message_locator = (By.CSS_SELECTOR, '#modal-cancel > form:nth-child(1) > p:nth-child(2)')
        _cancel_review_request_button_locator = (By.CSS_SELECTOR, '#modal-cancel > form:nth-child(1) > p:nth-child(6) > button:nth-child(1)')

        def wait_for_region_to_load(self):
            self.wait.until(EC.visibility_of_element_located(self._root_locator))
            return self

        @property
        def are_you_sure_message(self):
            return self.find_element(*self._are_you_sure_message_locator)

        @property
        def cancel_your_review_request_message_locator(self):
            return self.find_element(*self._cancel_your_review_request_message_locator)

        def click_cancel_review_request_button(self):
            self.wait.until(EC.visibility_of_element_located(self._cancel_review_request_button_locator))
            self.find_element(*self._cancel_review_request_button_locator).click()
            return self


    class DeleteAddonModal(Region):
        _root_locator = (By.ID, "modal-delete")
        _delete_confirmation_string_locator = (
            By.CSS_SELECTOR,
            "p:nth-of-type(2) > label",
        )
        _delete_confirmation_text_input_locator = (
            By.CSS_SELECTOR,
            'input[name="slug"]',
        )
        _delete_button_locator = (By.CSS_SELECTOR, ".delete-button")

        def wait_for_region_to_load(self):
            self.wait.until(EC.visibility_of_element_located(self._root_locator))
            return self

        @property
        def delete_confirmation_string(self):
            """This is the addon slug which is required to confirm deleting an addon"""
            return self.find_element(
                *self._delete_confirmation_string_locator
            ).text.split()[-1]

        def input_delete_confirmation_string(self):
            self.find_element(*self._delete_confirmation_text_input_locator).send_keys(
                self.delete_confirmation_string
            )

        def confirm_delete_addon(self):
            self.find_element(*self._delete_button_locator).click()
            from pages.desktop.developers.addons_manage import ManageAddons

            return ManageAddons(self.driver, self.page.base_url).wait_for_page_to_load()
