import io
import sys

import numpy as np
import pytest

from pandas.errors import Pandas4Warning

import pandas as pd
import pandas._testing as tm

from pandas.io.excel import ExcelFile
from pandas.io.excel._base import inspect_excel_format

xlrd = pytest.importorskip("xlrd")

pytestmark = pytest.mark.filterwarnings(
    "ignore:The xlrd engine is deprecated:pandas.errors.Pandas4Warning"
)


@pytest.fixture
def read_ext_xlrd():
    """
    Valid extensions for reading Excel files with xlrd.

    Similar to read_ext, but excludes .ods, .xlsb, and for xlrd>2 .xlsx, .xlsm
    """
    return ".xls"


def test_read_xlrd_book(read_ext_xlrd, datapath):
    engine = "xlrd"
    sheet_name = "Sheet1"
    pth = datapath("io", "data", "excel", "test1.xls")
    with xlrd.open_workbook(pth) as book:
        with ExcelFile(book, engine=engine) as xl:
            result = pd.read_excel(xl, sheet_name=sheet_name, index_col=0)

        expected = pd.read_excel(
            book, sheet_name=sheet_name, engine=engine, index_col=0
        )
    tm.assert_frame_equal(result, expected)


def test_read_xlsx_fails(datapath):
    # GH 29375
    from xlrd.biffh import XLRDError

    path = datapath("io", "data", "excel", "test1.xlsx")
    with pytest.raises(XLRDError, match="Excel xlsx file; not supported"):
        pd.read_excel(path, engine="xlrd")


def test_nan_in_xls(datapath):
    # GH 54564
    path = datapath("io", "data", "excel", "test6.xls")

    expected = pd.DataFrame({0: np.r_[0, 2].astype("int64"), 1: np.r_[1, np.nan]})

    result = pd.read_excel(path, header=None)

    tm.assert_frame_equal(result, expected)


@pytest.mark.parametrize(
    "file_header",
    [
        b"\x09\x00\x04\x00\x07\x00\x10\x00",
        b"\x09\x02\x06\x00\x00\x00\x10\x00",
        b"\x09\x04\x06\x00\x00\x00\x10\x00",
        b"\xd0\xcf\x11\xe0\xa1\xb1\x1a\xe1",
    ],
)
def test_read_old_xls_files(file_header):
    # GH 41226
    f = io.BytesIO(file_header)
    assert inspect_excel_format(f) == "xls"


def test_xlrd_engine_deprecated(datapath):
    # GH#56542
    path = datapath("io", "data", "excel", "test1.xls")
    with tm.assert_produces_warning(Pandas4Warning, match="xlrd engine is deprecated"):
        pd.read_excel(path, engine="xlrd")


def test_read_xlrd_book_no_engine(datapath):
    # GH#68086 - a Book has "read" but no "seek", so it passes is_file_like
    # and used to reach inspect_excel_format instead of the xlrd branch
    sheet_name = "Sheet1"
    pth = datapath("io", "data", "excel", "test1.xls")
    expected = pd.read_excel(pth, sheet_name=sheet_name, engine="xlrd", index_col=0)

    with xlrd.open_workbook(pth) as book:
        with ExcelFile(book) as xl:
            assert xl.engine == "xlrd"
            result = pd.read_excel(xl, sheet_name=sheet_name, index_col=0)
    with xlrd.open_workbook(pth) as book:
        from_book = pd.read_excel(book, sheet_name=sheet_name, index_col=0)

    tm.assert_frame_equal(result, expected)
    tm.assert_frame_equal(from_book, expected)


def test_read_excel_does_not_import_xlrd(datapath, monkeypatch):
    # GH#56692 - the xlrd.Book check must not import xlrd
    monkeypatch.delitem(sys.modules, "xlrd", raising=False)
    with pd.option_context("io.excel.xlsx.reader", "openpyxl"):
        pd.read_excel(datapath("io", "data", "excel", "test1.xlsx"))
    assert "xlrd" not in sys.modules
