from __future__ import annotations

import pytest

from cleo.ui.table import Table
from cleo.ui.table_cell import TableCell
from cleo.ui.table_separator import TableSeparator
from cleo.ui.table_style import TableStyle


books = [
    ["99921-58-10-7", "Divine Comedy", "<NAME>"],
    ["9971-5-0210-0", "A Tale of Two Cities", "<NAME>"],
    ["960-425-059-0", "The Lord of the Rings", "<NAME>"],
    ["80-902734-1-6", "And Then There Were None", "<NAME>"],
    ["9782070409341", "Le Père Goriot", "<NAME>"],
]


@pytest.mark.parametrize(
    ["headers", "rows", "style", "expected"],
    [
        (
            ["ISBN", "Title", "Author"],
            books,
            "default",
            """\
+---------------+--------------------------+------------------+
| ISBN          | Title                    | Author           |
+---------------+--------------------------+------------------+
| 99921-58-10-7 | Divine Comedy            | <NAME>  |
| 9971-5-0210-0 | A Tale of Two Cities     | <NAME>  |
| 960-425-059-0 | The Lord of the Rings    | <NAME> |
| 80-902734-1-6 | And Then There Were None | <NAME>  |
| 9782070409341 | Le Père Goriot           | <NAME> |
+---------------+--------------------------+------------------+
""",
        ),
        (
            ["ISBN", "Title", "Author"],
            books,
            "compact",
            """\
 ISBN          Title                    Author           
 99921-58-10-7 Divine Comedy            <NAME>  
 9971-5-0210-0 A Tale of Two Cities     <NAME>  
 960-425-059-0 The Lord of the Rings    <NAME> 
 80-902734-1-6 And Then There Were None Ag<NAME>  
 9782070409341 Le Père Goriot           <NAME> 
""",
        ),
        (
            ["ISBN", "Title", "Author"],
            books,
            "borderless",
            """\
 =============== ========================== ================== 
  ISBN            Title                      Author            
 =============== ========================== ================== 
  99921-58-10-7   Divine Comedy              <NAME>   
  9971-5-0210-0   A Tale of Two Cities       <NAME>   
  960-425-059-0   The Lord of the Rings      <NAME>  
  80-902734-1-6   And Then There Were None   <NAME>   
  9782070409341   Le Père Goriot             <NAME>  
 =============== ========================== ================== 
""",
        ),
        (
            ["ISBN", "Title", "Author"],
            books,
            "box",
            """\
┌───────────────┬──────────────────────────┬──────────────────┐
│ ISBN          │ Title                    │ Author           │
├───────────────┼──────────────────────────┼──────────────────┤
│ 99921-58-10-7 │ Divine Comedy            │ <NAME>  │
│ 9971-5-0210-0 │ A Tale of Two Cities     │ <NAME>  │
│ 960-425-059-0 │ The Lord of the Rings    │ <NAME> │
│ 80-902734-1-6 │ And Then There Were None │ <NAME>  │
│ 9782070409341 │ Le Père Goriot           │ <NAME> │
└───────────────┴──────────────────────────┴──────────────────┘
""",
        ),
        (
            ["ISBN", "Title", "Author"],
            [
                ["99921-58-10-7", "Divine Comedy", "<NAME>i"],
                ["9971-5-0210-0", "A Tale of Two Cities", "<NAME>"],
                TableSeparator(),
                ["960-425-059-0", "The Lord of the Rings", "<NAME>"],
                ["80-902734-1-6", "And Then There Were None", "<NAME>"],
            ],
            "box-double",
            """\
╔═══════════════╤══════════════════════════╤══════════════════╗
║ ISBN          │ Title                    │ Author           ║
╠═══════════════╪══════════════════════════╪══════════════════╣
║ 99921-58-10-7 │ Divine Comedy            │ <NAME>i  ║
║ 9971-5-0210-0 │ A Tale of Two Cities     │ Charles Dickens  ║
╟───────────────┼──────────────────────────┼──────────────────╢
║ 960-425-059-0 │ The Lord of the Rings    │ <NAME> ║
║ 80-902734-1-6 │ And Then There Were None │ <NAME>  ║
╚═══════════════╧══════════════════════════╧══════════════════╝
""",
        ),
        (
            ["ISBN", "Title"],
            [
                ["99921-58-10-7", "Divine Comedy", "Dante Alighieri"],
                ["9971-5-0210-0"],
                ["960-425-059-0", "The Lord of the Rings", "<NAME>"],
                ["80-902734-1-6", "And Then There Were None", "<NAME>"],
            ],
            "default",
            """\
+---------------+--------------------------+------------------+
| ISBN          | Title                    |                  |
+---------------+--------------------------+------------------+
| 99921-58-10-7 | Divine Comedy            | <NAME>  |
| 9971-5-0210-0 |                          |                  |
| 960-425-059-0 | The Lord of the Rings    | <NAME> |
| 80-902734-1-6 | And Then There Were None | <NAME>  |
+---------------+--------------------------+------------------+
""",
        ),
        (
            [],
            [
                ["99921-58-10-7", "Divine Comedy", "<NAME>"],
                ["9971-5-0210-0"],
                ["960-425-059-0", "The Lord of the Rings", "<NAME>"],
                ["80-902734-1-6", "And Then There Were None", "<NAME>"],
            ],
            "default",
            """\
+---------------+--------------------------+------------------+
| 99921-58-10-7 | Divine Comedy            | <NAME>  |
| 9971-5-0210-0 |                          |                  |
| 960-425-059-0 | The Lord of the Rings    | <NAME> |
| 80-902734-1-6 | And Then There Were None | <NAME>  |
+---------------+--------------------------+------------------+
""",
        ),
        (
            ["ISBN", "Title"],
            [],
            "default",
            """\
+------+-------+
| ISBN | Title |
+------+-------+
""",
        ),
        ([], [], "default", ""),
        (
            ["ISBN", "Title", "Author"],
            [
                ["99921-58-10-7", "Divine\nComedy", "<NAME>"],
                [
                    "9971-5-0210-2",
                    "Harry Potter\nand the Chamber of Secrets",
                    "Rowling\nJo<NAME>.",
                ],
                [
                    "9971-5-0210-2",
                    "Harry Potter\nand the Chamber of Secrets",
                    "Rowling\nJoan<NAME>.",
                ],
                ["960-425-059-0", "The Lord of the Rings", "<NAME>.\nTolkien"],
            ],
            "default",
            """\
+---------------+----------------------------+-----------------+
| ISBN          | Title                      | Author          |
+---------------+----------------------------+-----------------+
| 99921-58-10-7 | Divine                     | <NAME> |
|               | Comedy                     |                 |
| 9971-5-0210-2 | <NAME>               | Rowling         |
|               | and the Chamber of Secrets | <NAME>.       |
| 9971-5-0210-2 | <NAME>               | Rowling         |
|               | and the Chamber of Secrets | Joanne K.       |
| 960-425-059-0 | The Lord of the Rings      | <NAME>.        |
|               |                            | Tolkien         |
+---------------+----------------------------+-----------------+
""",
        ),
        (
            ["ISBN", "Title", "Author"],
            [
                [
                    "<info>99921-58-10-7</info>",
                    "<error>Divine Comedy</error>",
                    "<fg=blue;bg=white><NAME></fg=blue;bg=white>",
                ],
                ["9971-5-0210-0", "A Tale of Two Cities", "<info><NAME></>"],
            ],
            "default",
            """\
+---------------+----------------------+-----------------+
| ISBN          | Title                | Author          |
+---------------+----------------------+-----------------+
| 99921-58-10-7 | Divine Comedy        | <NAME> |
| 9971-5-0210-0 | A Tale of Two Cities | <NAME> |
+---------------+----------------------+-----------------+
""",
        ),
        (
            ["ISBN", "Title", "Author"],
            [
                ["99921-58-10-7", "Divine Comedy", "<NAME>"],
                TableSeparator(),
                [TableCell("Divine Comedy(Dante Alighieri)", colspan=3)],
                TableSeparator(),
                [TableCell("Arduino: A Quick-Start Guide", colspan=2), "<NAME>"],
                TableSeparator(),
                ["9971-5-0210-0", TableCell("A Tale of \nTwo Cities", colspan=2)],
            ],
            "default",
            """\
+----------------+----------------+-----------------+
| ISBN           | Title          | Author          |
+----------------+----------------+-----------------+
| 99921-58-10-7  | Divine Comedy  | <NAME> |
+----------------+----------------+-----------------+
| Divine Comedy(Dante Alighieri)                    |
+----------------+----------------+-----------------+
| Arduino: A Quick-Start Guide    | <NAME>    |
+----------------+----------------+-----------------+
| 9971-5-0210-0  | A Tale of                        |
|                | Two Cities                       |
+----------------+----------------+-----------------+
""",
        ),
        (
            ["ISBN", "Title", "Author"],
            [
                [
                    TableCell("9971-5-0210-0", rowspan=3),
                    "Divine Comedy",
                    "<NAME>",
                ],
                ["A Tale of Two Cities", "<NAME>"],
                ["The Lord of \nthe Rings", "<NAME>. \n<NAME>"],
                TableSeparator(),
                [
                    "80-902734-1-6",
                    TableCell("And Then \nThere \nWere None", rowspan=3),
                    "<NAME>",
                ],
                ["80-902734-1-7", "Test"],
            ],
            "default",
            """\
+---------------+----------------------+-----------------+
| ISBN          | Title                | Author          |
+---------------+----------------------+-----------------+
| 9971-5-0210-0 | Divine Comedy        | <NAME> |
|               | A Tale of Two Cities | <NAME> |
|               | The Lord of          | <NAME>.           |
|               | the Rings            | <NAME>      |
+---------------+----------------------+-----------------+
| 80-902734-1-6 | And Then             | <NAME> |
| 80-902734-1-7 | There                | Test            |
|               | Were None            |                 |
+---------------+----------------------+-----------------+
""",
        ),
        (
            ["ISBN", "Title", "Author"],
            [
                [TableCell("9971-5-0210-0", rowspan=2, colspan=2), "<NAME>"],
                ["<NAME>"],
                TableSeparator(),
                ["<NAME>", TableCell("9971-5-0210-0", rowspan=3, colspan=2)],
                ["<NAME>"],
                ["<NAME>"],
            ],
            "default",
            """\
+------------------+---------+-----------------+
| ISBN             | Title   | Author          |
+------------------+---------+-----------------+
| 9971-5-0210-0              | <NAME> |
|                            | <NAME> |
+------------------+---------+-----------------+
| <NAME>  | 9971-5-0210-0             |
| <NAME> |                           |
| <NAME>          |                           |
+------------------+---------+-----------------+
""",
        ),
        (
            ["ISBN", "Title", "Author"],
            [
                [
                    TableCell("9971\n-5-\n021\n0-0", rowspan=2, colspan=2),
                    "<NAME>",
                ],
                ["<NAME>"],
                TableSeparator(),
                [
                    "<NAME>",
                    TableCell("9971\n-5-\n021\n0-0", rowspan=2, colspan=2),
                ],
                ["<NAME>"],
                TableSeparator(),
                [
                    TableCell("9971\n-5-\n021\n0-0", rowspan=2, colspan=2),
                    TableCell("Dante \nAlighieri", rowspan=2, colspan=1),
                ],
            ],
            "default",
            """\
+-----------------+-------+-----------------+
| ISBN            | Title | Author          |
+-----------------+-------+-----------------+
| 9971                    | <NAME> |
| -5-                     | <NAME> |
| 021                     |                 |
| 0-0                     |                 |
+-----------------+-------+-----------------+
| <NAME> | 9971                    |
| <NAME> | -5-                     |
|                 | 021                     |
|                 | 0-0                     |
+-----------------+-------+-----------------+
| 9971                    | Dante           |
| -5-                     | Alighieri       |
| 021                     |                 |
| 0-0                     |                 |
+-----------------+-------+-----------------+
""",
        ),
        (
            ["ISBN", "Title", "Author"],
            [
                [
                    TableCell("9971\n-5-\n021\n0-0", rowspan=2, colspan=2),
                    "<NAME>",
                ],
                ["<NAME>"],
                [
                    "<NAME>",
                    TableCell("9971\n-5-\n021\n0-0", rowspan=2, colspan=2),
                ],
                ["<NAME>"],
            ],
            "default",
            """\
+-----------------+-------+-----------------+
| ISBN            | Title | Author          |
+-----------------+-------+-----------------+
| 9971                    | <NAME> |
| -5-                     | <NAME> |
| 021                     |                 |
| 0-0                     |                 |
| <NAME> | 9971                    |
| <NAME> | -5-                     |
|                 | 021                     |
|                 | 0-0                     |
+-----------------+-------+-----------------+
""",
        ),
        (
            ["ISBN", "Author"],
            [
                [TableCell("9971-5-0210-0", rowspan=3, colspan=1), "<NAME>"],
                [TableSeparator()],
                ["<NAME>"],
            ],
            "default",
            """\
+---------------+-----------------+
| ISBN          | Author          |
+---------------+-----------------+
| 9971-5-0210-0 | <NAME> |
|               |-----------------|
|               | <NAME> |
+---------------+-----------------+
""",
        ),
        (
            [[TableCell("Main title", colspan=3)], ["ISBN", "Title", "Author"]],
            [],
            "default",
            """\
+------+-------+--------+
| Main title            |
+------+-------+--------+
| ISBN | Title | Author |
+------+-------+--------+
""",
        ),
        (
            [],
            [
                [
                    TableCell("1", colspan=3),
                    TableCell("2", colspan=2),
                    TableCell("3", colspan=2),
                    TableCell("4", colspan=2),
                ]
            ],
            "default",
            """\
+---+--+--+---+--+---+--+---+--+
| 1       | 2    | 3    | 4    |
+---+--+--+---+--+---+--+---+--+
""",
        ),
    ],
)
def test_render(io, headers, rows, style, expected):
    table = Table(io, style=style)
    table.set_headers(headers)
    table.set_rows(rows)

    table.render()

    assert io.fetch_output() == expected


def test_column_style(io):
    table = Table(io)
    table.set_headers(["ISBN", "Title", "Author", "Price"])
    table.set_rows(
        [
            ["99921-58-10-7", "Divine Comedy", "<NAME>", "9.95"],
            ["9971-5-0210-0", "A Tale of Two Cities", "<NAME>", "139.25"],
        ]
    )

    style = TableStyle()
    style.set_pad_type("left")
    table.set_column_style(3, style)

    table.render()

    expected = """\
+---------------+----------------------+-----------------+--------+
| ISBN          | Title                | Author          |  Price |
+---------------+----------------------+-----------------+--------+
| 99921-58-10-7 | Divine Comedy        | <NAME> |   9.95 |
| 9971-5-0210-0 | A Tale of Two Cities | <NAME> | 139.25 |
+---------------+----------------------+-----------------+--------+
"""

    assert io.fetch_output() == expected


def test_style_for_side_effects(io):
    headers = ["Type", "Class", "Name"]
    rows = [
        ["GSV", "Range", "Bora Horza Gobuchul"],
        ["GSV", "Plate", "Sleeper Service"],
        ["GCU", "Ridge", "Grey Area"],
        ["PS", "Abominator", "Falling Outside the Normal Moral Constraints"],
    ]

    table1 = Table(io)
    table1.set_headers(headers)
    table1.set_rows(rows)
    table1.style.set_vertical_border_chars("x", "y")
    table1.render()

    output1 = io.fetch_output()

    table2 = Table(io)
    table2.set_headers(headers)
    table2.set_rows(rows)
    table2.render()

    output2 = io.fetch_output()

    assert output1 != output2
