import datetime

import pytest
from playwright.sync_api import Page, expect
from sqlalchemy import select

from testutils import load_gpx_asset
from fietsboek import models
from fietsboek.models.track import Visibility


def test_login_failed(page: Page):
    page.goto("/")
    page.get_by_role("button", name="User").click()
    page.get_by_text("Login").click()

    page.get_by_label("E-Mail").fill("not-john@doe.com")
    page.get_by_label("Password").fill("password")
    page.get_by_role("button", name="Login").click()

    expect(page.locator(".alert")).to_have_text("Invalid login credentials")


def test_login_success(page: Page, playwright_helper):
    playwright_helper.john_doe()

    page.goto("/")
    page.get_by_role("button", name="User").click()
    page.get_by_text("Login").click()

    page.get_by_label("E-Mail").fill("john@doe.com")
    page.get_by_label("Password").fill("password")
    page.get_by_role("button", name="Login").click()

    expect(page.locator(".alert")).to_have_text("You are now logged in")


def test_upload(page: Page, playwright_helper, tmp_path, dbaccess):
    playwright_helper.login()

    page.goto("/")
    page.get_by_text("Upload").click()

    # We unpack one of the test GPX files
    gpx_data = load_gpx_asset("Teasi_1.gpx.gz")
    gpx_path = tmp_path / "Upload.gpx"
    with open(gpx_path, "wb") as gpx_fobj:
        gpx_fobj.write(gpx_data)

    page.get_by_label("GPX file").set_input_files(gpx_path)
    page.locator(".bi-upload").click()

    # We now fill in most of the data
    page.get_by_label("Title", exact=True).fill("An awesome track!")
    page.get_by_label("Date").type("07302022")
    #page.get_by_label("Date").press("Tab")
    page.get_by_label("Date").type("12:41")
    page.get_by_label("Visibility").select_option(label="Public")
    page.get_by_label("Tags").fill("Tolle Tour")
    page.get_by_role("button", name="Add Tag").click()
    page.get_by_label("Description").fill("Beschreibung der tollen Tour")

    page.locator(".btn", has_text="Upload").click()

    # Once we have finished the upload, extract the ID of the track and check
    # the properties
    new_track_id = int(page.url.rsplit("/", 1)[1])
    track = dbaccess.execute(select(models.Track).filter_by(id=new_track_id)).scalar_one()

    assert track.title == "An awesome track!"
    assert track.date.replace(tzinfo=None) == datetime.datetime(2022, 7, 30, 12, 41)
    assert track.visibility == Visibility.PUBLIC
    assert track.text_tags() == {"Tolle Tour"}
    assert track.description == "Beschreibung der tollen Tour"


def test_edit(page: Page, playwright_helper, dbaccess):
    playwright_helper.login()
    track_id = playwright_helper.add_track().id

    page.goto(f"/track/{track_id}")
    page.locator(".btn", has_text="Edit").click()

    # We now fill in most of the data
    page.get_by_label("Title", exact=True).fill("Not so awesome anymore!")
    page.get_by_label("Date").type("09232019")
    page.get_by_label("Date").type("15:28")
    page.get_by_label("Visibility").select_option(label="Public")
    page.get_by_label("Tags").fill("Shitty Tour")
    page.get_by_role("button", name="Add Tag").click()
    page.get_by_label("Description").fill("Not so descriptive anymore")

    page.locator(".btn", has_text="Save").click()

    track = dbaccess.execute(select(models.Track).filter_by(id=track_id)).scalar_one()

    assert track.title == "Not so awesome anymore!"
    assert track.date.replace(tzinfo=None) == datetime.datetime(2019, 9, 23, 15, 28)
    assert track.visibility == Visibility.PUBLIC
    assert track.text_tags() == {"Shitty Tour"}
    assert track.description == "Not so descriptive anymore"


def test_browse(page: Page, playwright_helper, dbaccess):
    playwright_helper.login()
    track = playwright_helper.add_track()

    with dbaccess:
        track = dbaccess.merge(track)
        track.title = "We're looking for this track"
        dbaccess.commit()

    page.goto("/")
    page.get_by_text("Browse").click()

    expect(page.locator(".card-header", has_text="We're looking for this track")).to_be_visible()

    page.get_by_role("textbox", name="Search terms").fill("Nothing")
    page.get_by_role("button", name="Apply filters").click()

    expect(
        page.locator("p", has_text="No results matching the filters were found.")
    ).to_be_visible()

    page.get_by_role("textbox", name="Search terms").fill("looking for")
    page.get_by_role("button", name="Apply filters").click()

    expect(page.locator(".card-header", has_text="We're looking for this track")).to_be_visible()


def test_delete(page: Page, playwright_helper, dbaccess, data_manager):
    playwright_helper.login()
    track_id = playwright_helper.add_track().id

    page.goto(f"/track/{track_id}")
    page.locator("#deleteLink", has_text="Delete").click()

    expect(page.get_by_text(
        "Deleting this track will remove all associated information with it!"
    )).to_be_visible()

    page.locator("#deleteModal form").get_by_text("Delete").click()

    track = dbaccess.execute(select(models.Track).filter_by(id=track_id)).scalar_one_or_none()
    assert track is None
    with pytest.raises(FileNotFoundError):
        data_manager.open(track_id)


def test_favour(page: Page, playwright_helper, dbaccess, data_manager):
    john = playwright_helper.john_doe()
    playwright_helper.login()
    track_id = playwright_helper.add_track().id

    page.goto(f"/track/{track_id}")

    with page.expect_request_finished(predicate=lambda req: "/toggle-favourite" in req.url):
        page.locator(".favourite-star").click()

    track = dbaccess.execute(select(models.Track).filter_by(id=track_id)).scalar_one_or_none()
    assert john.id in [user.id for user in track.favourees]

    with page.expect_request_finished(predicate=lambda req: "/toggle-favourite" in req.url):
        page.locator(".favourite-star").click()

    dbaccess.refresh(track, ["favourees"])
    assert john.id not in [user.id for user in track.favourees]