<?php

namespace MediaWiki\Extension\CustomQueryPage\Special;

use HTMLForm;
use Html;
use MediaWiki\Extension\CustomQueryPage\Store\TagStore;
use MediaWiki\Extension\CustomQueryPage\Store\RoutineCloner;
use MediaWiki\Extension\CustomQueryPage\Store\RoutineCloneException;
use MediaWiki\MediaWikiServices;
use FormSpecialPage;
use MediaWiki\User\UserIdentityLookup;
use MediaWiki\User\UserFactory;
use const TS_MW;
use function trim;
use function wfTimestamp;

class CustomQuerySettings extends FormSpecialPage {
    private TagStore $tagStore;
    /** @var UserIdentityLookup|UserFactory */
    private $userLookup;
    private RoutineCloner $routineCloner;
    private ?string $submittedTag = null;

    public function __construct( ?TagStore $tagStore = null, ?UserIdentityLookup $userLookup = null, ?RoutineCloner $routineCloner = null ) {
        parent::__construct( 'CustomQuerySettings', 'customquerypage-manage' );
        $services = MediaWikiServices::getInstance();
        $this->tagStore = $tagStore ?? $services->getService( 'CustomQueryPage.TagStore' );
        $this->routineCloner = $routineCloner ?? $services->getService( 'CustomQueryPage.RoutineCloner' );
        if ( method_exists( $services, 'getUserIdentityLookup' ) ) {
            $this->userLookup = $userLookup ?? $services->getUserIdentityLookup();
        } else {
            $this->userLookup = $userLookup ?? $services->getUserFactory();
        }
    }

    public function execute( $subPage ): void {
        parent::execute( $subPage );
        $this->showCloneForm();
    }

    protected function getFormFields(): array {
        $currentTag = $this->tagStore->getActiveTag();
        return [
            'tag' => [
                'type' => 'text',
                'maxlength' => 255,
                'required' => true,
                'label-message' => 'customquerypage-form-tag-label',
                'default' => $currentTag,
                'help-message' => 'customquerypage-form-tag-help',
            ],
        ];
    }

    protected function alterForm( HTMLForm $form ): void {
        $form->setSubmitTextMsg( 'customquerypage-form-submit-label' );
    }

    public function onSubmit( array $data ) {
        $tag = trim( $data['tag'] );
        $this->tagStore->setActiveTag( $tag, $this->getUser() );
        $this->submittedTag = $tag;
        return true;
    }

    public function onSuccess(): void {
        if ( $this->submittedTag !== null ) {
            $this->getOutput()->addWikiMsg( 'customquerypage-special-settings-success', $this->submittedTag );
        }
    }

    protected function preHtml(): string {
        $info = $this->tagStore->getLastUpdate();
        if ( !$info ) {
            return $this->msg( 'customquerypage-settings-never-set' )->parse();
        }

        $username = $this->lookupUsername( (int)$info['user_id'] )
            ?? $this->msg( 'customquerypage-settings-unknown-user' )->text();
        $timestamp = $info['timestamp'] ?: wfTimestamp();
        $formatted = $this->getLanguage()->timeanddate( wfTimestamp( TS_MW, $timestamp ), true );

        return $this->msg( 'customquerypage-settings-last-updated', $username, $formatted )->parse();
    }

    private function lookupUsername( int $userId ): ?string {
        if ( method_exists( $this->userLookup, 'getUserIdentityByUserId' ) ) {
            $user = $this->userLookup->getUserIdentityByUserId( $userId );
            return $user ? $user->getName() : null;
        }

        $user = $this->userLookup->newFromId( $userId );
        return ( $user && $user->getId() ) ? $user->getName() : null;
    }

    private function showCloneForm(): void {
        $this->getOutput()->addHTML( Html::element( 'h2', [], $this->msg( 'customquerypage-clone-heading' )->text() ) );
        $fields = [
            'source_tag' => [
                'type' => 'text',
                'label-message' => 'customquerypage-clone-source-label',
                'help-message' => 'customquerypage-clone-source-help',
                'maxlength' => 255,
                'required' => true,
            ],
            'target_tag' => [
                'type' => 'text',
                'label-message' => 'customquerypage-clone-target-label',
                'help-message' => 'customquerypage-clone-target-help',
                'maxlength' => 255,
                'required' => true,
            ],
            'deploy_comment' => [
                'type' => 'text',
                'label-message' => 'customquerypage-clone-comment-label',
                'help-message' => 'customquerypage-clone-comment-help',
                'maxlength' => 1024,
            ],
        ];

        $form = HTMLForm::factory( 'ooui', $fields, $this->getContext() );
        $form->setId( 'customquerypage-clone-form' );
        $form->setFormIdentifier( 'customquerypage-clone' );
        $form->setIntro( $this->msg( 'customquerypage-clone-intro' )->parse() );
        $form->setSubmitTextMsg( 'customquerypage-clone-submit' );
        $form->setSubmitCallback( function ( array $formData ) {
            return $this->handleCloneFormSubmit( $formData );
        } );
        $form->show();
    }

    private function handleCloneFormSubmit( array $data ) {
        $sourceTag = trim( $data['source_tag'] ?? '' );
        $targetTag = trim( $data['target_tag'] ?? '' );
        $deployComment = $data['deploy_comment'] ?? null;
        if ( $deployComment !== null ) {
            $deployComment = trim( $deployComment );
            if ( $deployComment === '' ) {
                $deployComment = null;
            }
        }

        try {
            $result = $this->routineCloner->cloneTag( $sourceTag, $targetTag, $deployComment, $this->getUser() );
            $this->tagStore->setActiveTag( $targetTag, $this->getUser() );
            $this->getOutput()->addWikiMsg(
                'customquerypage-clone-success',
                $sourceTag,
                $targetTag,
                $this->getLanguage()->formatNum( $result->getPageCount() ),
                $this->getLanguage()->formatNum( $result->getRevisionCount() )
            );
            return true;
        } catch ( RoutineCloneException $e ) {
            return $this->msg( $e->getMessageKey(), ...$e->getMessageParams() );
        } catch ( \Throwable $e ) {
            return $this->msg( 'customquerypage-clone-error-generic' );
        }
    }
}
