<?php

namespace MediaWiki\Extension\CustomQueryPage\Special;

use Html;
use MediaWiki\Extension\CustomQueryPage\Store\TagStore;
use MediaWiki\MediaWikiServices;
use SpecialPage;
use Title;
use const DB_REPLICA;
use const TS_MW;
use function wfTimestamp;

class ApprovedManuals extends SpecialPage {
    private TagStore $tagStore;

    public function __construct( ?TagStore $tagStore = null ) {
        parent::__construct( 'ApprovedManuals' );
        $this->tagStore = $tagStore ?? MediaWikiServices::getInstance()->getService( 'CustomQueryPage.TagStore' );
    }

    public function execute( $subPage ): void {
        $this->setHeaders();
        $this->checkPermissions();
        $out = $this->getOutput();
        $out->addHelpLink( 'Manual:CustomQueryPage' );

        $requestedSort = $this->getRequest()->getText( 'sort', 'title' );
        $requestedOrder = $this->getRequest()->getText( 'order', 'asc' );
        [ $sortField, $sortDirection ] = $this->normalizeSort( $requestedSort, $requestedOrder );

        $tag = $this->tagStore->getActiveTag();
        $results = $this->runQuery( $sortField, $sortDirection, $tag );

        if ( !$results->numRows() ) {
            $out->addWikiMsg( 'customquerypage-special-nodata', $tag );
            return;
        }

        $out->addWikiMsg( 'customquerypage-special-approvedmanuals-intro', $tag );
        $out->addHTML( $this->buildTable( $results, $sortField, $sortDirection ) );
    }

    private function normalizeSort( string $sort, string $order ): array {
        $sort = strtolower( $sort ) === 'date' ? 'date' : 'title';
        $order = strtoupper( $order ) === 'DESC' ? 'DESC' : 'ASC';
        return [ $sort, $order ];
    }

    private function runQuery( string $sortField, string $sortDirection, string $tag ) {
        $dbr = MediaWikiServices::getInstance()->getDBLoadBalancer()->getConnectionRef( DB_REPLICA );

        $options = [
            'ORDER BY' => $sortField === 'date' ? "r.rev_timestamp $sortDirection" : "p.page_title $sortDirection",
        ];

        return $dbr->select(
            [
                'p' => 'page',
                'mt' => 'tag_pages',
                't' => 'tags',
                'r' => 'revision',
            ],
            [
                'page_id' => 'p.page_id',
                'page_namespace' => 'p.page_namespace',
                'page_title' => 'p.page_title',
                'tag_id' => 't.tag_id',
                'revision_id' => 'mt.tag_rev',
                'deployment_date' => 'r.rev_timestamp',
            ],
            [ 't.tag_id' => $tag ],
            __METHOD__,
            $options,
            [
                'mt' => [ 'JOIN', 'p.page_id = mt.tag_page' ],
                't' => [ 'JOIN', 'mt.tag_id = t.tag_id' ],
                'r' => [ 'JOIN', 'mt.tag_rev = r.rev_id' ],
            ]
        );
    }

    private function buildTable( $results, string $sortField, string $sortDirection ): string {
        $title = $this->getPageTitle();
        $titleOrder = $sortField === 'title' && $sortDirection === 'ASC' ? 'DESC' : 'ASC';
        $dateOrder = $sortField === 'date' && $sortDirection === 'ASC' ? 'DESC' : 'ASC';

        $titleUrl = $title->getLocalURL( [ 'sort' => 'title', 'order' => $titleOrder ] );
        $dateUrl = $title->getLocalURL( [ 'sort' => 'date', 'order' => $dateOrder ] );

        $html = Html::openElement( 'table', [ 'class' => 'wikitable custom-query-table' ] );
        $html .= Html::openElement( 'thead' );
        $html .= Html::rawElement( 'tr', [],
            Html::element( 'th', [], $this->msg( 'customquerypage-column-pageid' )->text() ) .
            Html::rawElement( 'th', [], Html::element( 'a', [ 'href' => $titleUrl ], $this->msg( 'customquerypage-column-title' )->text() ) ) .
            Html::element( 'th', [], $this->msg( 'customquerypage-column-tag' )->text() ) .
            Html::element( 'th', [], $this->msg( 'customquerypage-column-revision' )->text() ) .
            Html::rawElement( 'th', [], Html::element( 'a', [ 'href' => $dateUrl ], $this->msg( 'customquerypage-column-date' )->text() ) )
        );
        $html .= Html::closeElement( 'thead' );
        $html .= Html::openElement( 'tbody' );

        foreach ( $results as $row ) {
            $titleObj = Title::makeTitle( (int)$row->page_namespace, $row->page_title );
            $link = $this->getLinkRenderer()->makeLink( $titleObj, $row->page_title );
            $formattedDate = $this->getLanguage()->timeanddate( wfTimestamp( TS_MW, $row->deployment_date ), true );

            $html .= Html::rawElement( 'tr', [],
                Html::element( 'td', [], (string)$row->page_id ) .
                Html::rawElement( 'td', [], $link ) .
                Html::element( 'td', [], (string)$row->tag_id ) .
                Html::element( 'td', [], (string)$row->revision_id ) .
                Html::element( 'td', [], $formattedDate )
            );
        }

        $html .= Html::closeElement( 'tbody' );
        $html .= Html::closeElement( 'table' );
        return $html;
    }
}
