"""Mocked Google Sheet tests for DataTable."""

from types import SimpleNamespace

import pytest

import soigia.datatable as dtpkg
from soigia.datatable import DataTable
from tests.datatable_mock_helpers import FakeClient, FakeWorkbook, FakeWorksheet


def test_from_google_sheet_with_mock_worksheet():
    worksheet = FakeWorksheet(records=[{"name": "alice", "age": 19}, {"name": "bob", "age": 24}])
    table = DataTable.from_google_sheet(worksheet)

    assert table.to_rows() == [{"name": "alice", "age": 19}, {"name": "bob", "age": 24}]


def test_from_google_sheet_with_range_and_client_resolution():
    worksheet = FakeWorksheet(values=[["name", "age"], ["alice", 19], ["bob", 24]])
    client = FakeClient(worksheet)
    table = DataTable.from_google_sheet("sheet-id", worksheet=0, range_name="A1:B3", client=client)

    assert table.to_rows() == [{"name": "alice", "age": 19}, {"name": "bob", "age": 24}]
    assert client.opened == [("open_by_key", "sheet-id")]


def test_to_google_sheet_writes_and_clear():
    worksheet = FakeWorksheet()
    table = DataTable({"name": ["alice", "bob"], "age": [19, 24]})

    returned = table.to_google_sheet(worksheet, clear=True, include_index=False)

    assert returned is worksheet
    assert worksheet.cleared is True
    assert worksheet.updated["start_cell"] == "A1"
    assert worksheet.updated["value_input_option"] == "RAW"
    assert worksheet.updated["values"][0] == ["name", "age"]
    assert worksheet.updated["values"][1:] == [["alice", 19], ["bob", 24]]


def test_to_google_sheet_uses_append_rows_when_update_missing():
    worksheet = SimpleNamespace(clear=lambda: None, append_rows=None)
    worksheet.append_rows = lambda values, value_input_option="RAW": setattr(
        worksheet,
        "captured",
        {"values": values, "value_input_option": value_input_option},
    )
    table = DataTable({"name": ["carol"], "age": [31]})

    returned = table.to_google_sheet(worksheet, clear=False)

    assert returned is worksheet
    assert worksheet.captured["values"][0] == ["name", "age"]
    assert worksheet.captured["values"][1:] == [["carol", 31]]


def test_module_level_google_wrappers(monkeypatch):
    worksheet = FakeWorksheet(records=[{"name": "alice", "age": 19}])
    monkeypatch.setattr(dtpkg, "_DEFAULT_CONNECTOR", None)

    assert dtpkg.from_google_sheet(worksheet).to_rows() == [{"name": "alice", "age": 19}]
    assert dtpkg.to_google_sheet(DataTable({"name": ["alice"], "age": [19]}), worksheet) is worksheet


def test_google_sheet_resolution_errors():
    with pytest.raises(ImportError):
        DataTable.from_google_sheet(object())


def test_google_sheet_resolution_and_empty_branches(monkeypatch):
    worksheet = FakeWorksheet(records=[{"name": "alice", "age": 19}])
    client = FakeClient(worksheet)

    # spreadsheet is not a worksheet, worksheet already is a worksheet-like object
    resolved = dtpkg._resolve_google_worksheet("sheet-id", worksheet=worksheet, client=client)
    assert resolved is worksheet

    # open_by_url branch
    url_client = SimpleNamespace(
        open_by_url=lambda url: FakeWorkbook(worksheet),
        open_by_key=lambda key: FakeWorkbook(worksheet),
        open=lambda key: FakeWorkbook(worksheet),
    )
    resolved = dtpkg._resolve_google_worksheet("https://docs.google.com/spreadsheets/d/x", client=url_client)
    assert resolved is worksheet

    # open branch when open_by_key/open_by_url are absent
    open_only_client = SimpleNamespace(open=lambda key: FakeWorkbook(worksheet))
    resolved = dtpkg._resolve_google_worksheet("sheet-id", client=open_only_client)
    assert resolved is worksheet

    # fallback to the resolved_client object itself when open methods are absent
    bare_client = SimpleNamespace(get_worksheet=lambda index: worksheet)
    resolved = dtpkg._resolve_google_worksheet("sheet-id", client=bare_client)
    assert resolved is worksheet

    # string worksheet name via workbook.worksheet(...)
    name_workbook = SimpleNamespace(worksheet=lambda name: worksheet)
    name_client = SimpleNamespace(open_by_key=lambda key: name_workbook)
    resolved = dtpkg._resolve_google_worksheet("sheet-id", worksheet="NamedSheet", client=name_client)
    assert resolved is worksheet

    # fallback to workbook.worksheet(...) when get_worksheet returns None
    workbook = SimpleNamespace(get_worksheet=lambda index: None, worksheet=lambda name: worksheet)
    fallback_client = SimpleNamespace(open_by_key=lambda key: workbook)
    resolved = dtpkg._resolve_google_worksheet("sheet-id", client=fallback_client)
    assert resolved is worksheet

    # range branch with empty values
    empty_range_sheet = FakeWorksheet(values=[])
    assert DataTable.from_google_sheet(empty_range_sheet, range_name="A1:B2").empty

    # get_all_values empty branch
    class EmptyValuesSheet:
        def get_all_values(self):
            return []

    empty_values_sheet = EmptyValuesSheet()
    assert DataTable.from_google_sheet(empty_values_sheet).empty

    class ValuesOnlySheet:
        def get_all_values(self):
            return [["name", "age"], ["alice", 19]]

    values_only_sheet = ValuesOnlySheet()
    assert values_only_sheet.get_all_values()[0] == ["name", "age"]
    assert DataTable.from_google_sheet(values_only_sheet).to_rows() == [{"name": "alice", "age": 19}]


def test_google_client_builder_error_branch(monkeypatch):
    fake_gspread = SimpleNamespace(authorize=lambda credentials: {"client": credentials})
    monkeypatch.setitem(__import__("sys").modules, "gspread", fake_gspread)
    monkeypatch.setitem(__import__("sys").modules, "google", SimpleNamespace())
    monkeypatch.setitem(__import__("sys").modules, "google.oauth2", SimpleNamespace())
    monkeypatch.setitem(__import__("sys").modules, "google.oauth2.service_account", SimpleNamespace())

    with pytest.raises(ImportError):
        dtpkg._build_google_client()


def test_google_sheet_to_google_sheet_error_branch():
    table = DataTable({"name": ["alice"]})
    worksheet = SimpleNamespace(clear=lambda: None)
    original_resolver = dtpkg._resolve_google_worksheet
    dtpkg._resolve_google_worksheet = lambda *args, **kwargs: worksheet
    try:
        with pytest.raises(TypeError):
            table.to_google_sheet(worksheet)
    finally:
        dtpkg._resolve_google_worksheet = original_resolver


def test_google_helper_direct_branches(monkeypatch):
    empty_sheet = SimpleNamespace(get_all_values=lambda: [])
    assert dtpkg._google_worksheet_to_frame(empty_sheet).empty

    values_sheet = SimpleNamespace(get_all_values=lambda: [["name", "age"], ["alice", 19]])
    assert dtpkg._google_worksheet_to_frame(values_sheet).to_rows() == [{"name": "alice", "age": 19}]

    with pytest.raises(TypeError):
        dtpkg._google_worksheet_to_frame(SimpleNamespace())

    bare_client = SimpleNamespace()
    monkeypatch.setattr(dtpkg, "_build_google_client", lambda **kwargs: bare_client)
    with pytest.raises(TypeError):
        dtpkg._resolve_google_worksheet("sheet-id", client=bare_client)

    bare_sheet = SimpleNamespace()
    monkeypatch.setattr(dtpkg, "_build_google_client", lambda **kwargs: SimpleNamespace())
    with pytest.raises(TypeError):
        dtpkg._resolve_google_worksheet(bare_sheet, client=SimpleNamespace())
