<?php

declare(strict_types=1);

namespace Atk4\Ui\Tests\Table\Column;

use Atk4\Core\Phpunit\TestCase;
use Atk4\Data\Model;
use Atk4\Data\Persistence;
use Atk4\Ui\Table;
use Atk4\Ui\Tests\CreateAppTrait;
use Atk4\Ui\Tests\TableTestTrait;

class ColumnTest extends TestCase
{
    use CreateAppTrait;
    use TableTestTrait;

    private const NBSP = "\u{00a0}";

    protected function createTable(): Table
    {
        $arr = [
            'table' => [
                1 => ['id' => 1, 'name' => 'bar', 'ref' => 'ref123', 'salary' => -1234],
            ],
        ];
        $db = new Persistence\Array_($arr);
        $m = new Model($db, ['table' => 'table']);
        $m->addField('name');
        $m->addField('ref');
        $m->addField('salary', ['type' => 'integer']);

        $table = new Table();
        $table->setApp($this->createApp());
        $table->invokeInit();
        $table->setModel($m, ['name', 'ref']);

        return $table;
    }

    public function testGetDataRowHtml(): void
    {
        $table = $this->createTable();
        self::assertSame('<td>{$name}</td><td>{$ref}</td>', $table->getDataRowHtml());

        self::assertSame(
            '<tr data-id="1"><td>bar</td><td>ref123</td></tr>',
            $this->extractTableRow($table)
        );
    }

    public function testMultipleFormatters(): void
    {
        $table = $this->createTable();
        $table->addDecorator('name', new Table\Column\Template('<b>{$name}</b>'));

        self::assertSame('<td><b>{$name}</b></td><td>{$ref}</td>', $table->getDataRowHtml());

        self::assertSame(
            '<tr data-id="1"><td><b>bar</b></td><td>ref123</td></tr>',
            $this->extractTableRow($table)
        );
    }

    public function testTdLast(): void
    {
        $table = $this->createTable();
        $salary = $table->addColumn('salary', new Table\Column\Money());

        self::assertSame(
            '<td>{$name}</td><td>{$ref}</td><td class="right aligned single line {$' . $this->getColumnClass($salary) . '}">{$salary}</td>',
            $table->getDataRowHtml()
        );

        self::assertSame(
            '<tr data-id="1"><td>bar</td><td>ref123</td><td class="right aligned single line negative">-1' . self::NBSP . '234</td></tr>',
            $this->extractTableRow($table)
        );
    }

    public function testTdNotLast(): void
    {
        $table = $this->createTable();
        $salary = $table->addColumn('salary', new Table\Column\Money());
        $table->addDecorator('salary', new Table\Column\Template('<b>{$salary}</b>'));

        self::assertSame(
            '<td>{$name}</td><td>{$ref}</td><td class="right aligned single line {$' . $this->getColumnClass($salary) . '}"><b>{$salary}</b></td>',
            $table->getDataRowHtml()
        );

        self::assertSame(
            '<tr data-id="1"><td>bar</td><td>ref123</td><td class="right aligned single line negative"><b>-1' . self::NBSP . '234</b></td></tr>',
            $this->extractTableRow($table)
        );
    }

    public function testTwoMoneys(): void
    {
        $table = $this->createTable();
        $salary1 = $table->addDecorator('name', new Table\Column\Money());
        $salary2 = $table->addColumn('salary', new Table\Column\Money());
        $table->addDecorator('salary', new Table\Column\Template('<b>{$salary}</b>'));

        self::assertSame(
            '<td class="right aligned single line {$' . $this->getColumnClass($salary1) . '}">{$name}</td><td>{$ref}</td><td class="right aligned single line {$' . $this->getColumnClass($salary2) . '}"><b>{$salary}</b></td>',
            $table->getDataRowHtml()
        );

        self::assertSame(
            '<tr data-id="1"><td class="right aligned single line ">bar</td><td>ref123</td><td class="right aligned single line negative"><b>-1' . self::NBSP . '234</b></td></tr>',
            $this->extractTableRow($table)
        );
    }

    public function testTemplateStacking(): void
    {
        $table = $this->createTable();
        $table->addDecorator('name', new Table\Column\Template('<b>{$name}</b>'));
        $table->addDecorator('name', new Table\Column\Template('<u>{$name}</u>'));

        self::assertSame(
            '<td><u><b>{$name}</b></u></td><td>{$ref}</td>',
            $table->getDataRowHtml()
        );

        self::assertSame(
            '<tr data-id="1"><td><u><b>bar</b></u></td><td>ref123</td></tr>',
            $this->extractTableRow($table)
        );
    }

    public function testRender1(): void
    {
        $table = $this->createTable();
        $table->addDecorator('name', new Table\Column\Template('<b>{$name}</b>'));
        $table->addDecorator('name', new Table\Column\Template('<u>{$name}</u>'));

        self::assertSame(
            '<tr data-id="1"><td><u><b>bar</b></u></td><td>ref123</td></tr>',
            $this->extractTableRow($table)
        );
    }

    public function testRender1a(): void
    {
        $table = $this->createTable();
        $table->addColumn(null, [Table\Column\Template::class, 'hello<b>world</b>']);

        self::assertSame(
            '<td>{$name}</td><td>{$ref}</td><td>hello<b>world</b></td>',
            $table->getDataRowHtml()
        );

        self::assertSame(
            '<tr data-id="1"><td>bar</td><td>ref123</td><td>hello<b>world</b></td></tr>',
            $this->extractTableRow($table)
        );
    }

    public function testLink1a(): void
    {
        $table = $this->createTable();
        $link = $table->addDecorator('name', new Table\Column\Link('example.php?id={$id}'));

        self::assertSame(
            '<td><a href="{$' . $this->getColumnRef($link) . '}">{$name}</a></td><td>{$ref}</td>',
            $table->getDataRowHtml()
        );

        self::assertSame(
            '<tr data-id="1"><td><a href="example.php?id=1">bar</a></td><td>ref123</td></tr>',
            $this->extractTableRow($table)
        );
    }

    public function testLink1b(): void
    {
        $table = $this->createTable();
        $link = $table->addDecorator('name', [Table\Column\Link::class, 'url' => 'example.php?id={$id}']);

        self::assertSame(
            '<td><a href="{$' . $this->getColumnRef($link) . '}">{$name}</a></td><td>{$ref}</td>',
            $table->getDataRowHtml()
        );

        self::assertSame(
            '<tr data-id="1"><td><a href="example.php?id=1">bar</a></td><td>ref123</td></tr>',
            $this->extractTableRow($table)
        );
    }

    public function testLink2(): void
    {
        $table = $this->createTable();
        $table->addDecorator('name', new Table\Column\Link(['example', 'id' => '{$id}']));

        // url is properly encoded

        self::assertSame(
            '<tr data-id="1"><td><a href="example.php?id=%7B%24id%7D">bar</a></td><td>ref123</td></tr>',
            $this->extractTableRow($table)
        );
    }

    public function testLink3(): void
    {
        $table = $this->createTable();
        $table->addDecorator('name', new Table\Column\Link(['example'], ['id']));

        self::assertSame(
            '<tr data-id="1"><td><a href="example.php?id=1">bar</a></td><td>ref123</td></tr>',
            $this->extractTableRow($table)
        );
    }

    public function testLink4(): void
    {
        $table = $this->createTable();
        $table->addDecorator('name', new Table\Column\Link(['example'], ['test' => 'id']));

        self::assertSame(
            '<tr data-id="1"><td><a href="example.php?test=1">bar</a></td><td>ref123</td></tr>',
            $this->extractTableRow($table)
        );
    }

    public function testLink5(): void
    {
        $table = $this->createTable();
        $table->addDecorator('name', [Table\Column\Link::class, ['example'], ['test' => 'id']]);

        self::assertSame(
            '<tr data-id="1"><td><a href="example.php?test=1">bar</a></td><td>ref123</td></tr>',
            $this->extractTableRow($table)
        );
    }

    public function testLink6(): void
    {
        $table = $this->createTable();
        $table->addDecorator('name', [Table\Column\Link::class, ['example'], ['test' => 'id'], 'forceDownload' => true]);

        self::assertSame(
            '<tr data-id="1"><td><a href="example.php?test=1" download="true">bar</a></td><td>ref123</td></tr>',
            $this->extractTableRow($table)
        );
    }

    public function testLink7(): void
    {
        $table = $this->createTable();
        $table->addDecorator('name', [Table\Column\Link::class, ['example'], ['test' => 'id'], 'target' => '_blank']);

        self::assertSame(
            '<tr data-id="1"><td><a href="example.php?test=1" target="_blank">bar</a></td><td>ref123</td></tr>',
            $this->extractTableRow($table)
        );
    }

    public function testLink8(): void
    {
        $table = $this->createTable();
        $table->addDecorator('name', [Table\Column\Link::class, ['example'], ['test' => 'id'], 'icon' => 'info']);

        self::assertSame(
            '<tr data-id="1"><td><a href="example.php?test=1"><i class="info icon"></i>bar</a></td><td>ref123</td></tr>',
            $this->extractTableRow($table)
        );
    }

    public function testLink9(): void
    {
        $table = $this->createTable();
        $table->addDecorator('name', [Table\Column\Link::class, ['example'], ['test' => 'id'], 'useLabel' => false]);

        self::assertSame(
            '<tr data-id="1"><td><a href="example.php?test=1"></a></td><td>ref123</td></tr>',
            $this->extractTableRow($table)
        );
    }

    public function testNoValue(): void
    {
        $table = $this->createTable();
        $table->addDecorator('name', [Table\Column\NoValue::class, ['noValue' => ' empty ']]);
        $table->model->load(1)->save(['name' => '']);

        self::assertSame(
            '<tr data-id="1"><td> empty </td><td>ref123</td></tr>',
            $this->extractTableRow($table)
        );
    }

    public function testTooltip(): void
    {
        $table = $this->createTable();
        $table->addDecorator('name', [Table\Column\Tooltip::class, ['tooltipField' => 'salary']]);

        self::assertSame(
            '<tr data-id="1"><td class=""> bar<span class="ui icon link " data-tooltip="-1' . self::NBSP . '234"><i class="ui icon info circle"></span></td><td>ref123</td></tr>',
            $this->extractTableRow($table)
        );
    }
}
