package System::Introspector::Report::Publish::MediaWiki::Connection;
use Moo;
use MediaWiki::API;
use URI;
use aliased 'System::Introspector::Report::Publish::MediaWiki::Page';

has api             => (is => 'lazy');
has api_uri         => (is => 'ro', required => 1);
has username        => (is => 'ro', required => 1);
has password        => (is => 'ro', required => 1);
has allow_create    => (is => 'ro', default => sub { 0 });
has http_auth       => (is => 'ro');
has http_realm      => (is => 'ro');

my $_api_fail = sub {
  my $api = shift;
  die sprintf "MediaWiki Error %s: %s\n",
    $api->{error}{code},
    $api->{error}{details};
};

sub _build_api {
  my ($self) = @_;
  my $api_uri = URI->new($self->api_uri);
  my $api = MediaWiki::API->new({ api_url => $self->api_uri });
  my $passwd = $self->password;
  if ($ENV{TEST_SI_MEDIAWIKI_GETPW}) {
    system "stty -echo";
    printf "MediaWiki password for '%s': ", $self->username;
    $passwd = <STDIN>;
    chomp $passwd;
    system "stty echo";
    print "\n";
  }
  $api->{ua}->credentials(
    join(':', $api_uri->host, $api_uri->port),
    $self->http_realm || 'Wiki',
    $self->username,
    $passwd,
  ) if $self->http_auth;
  $api->login({
    lgname      => $self->username,
    lgpassword  => $passwd,
  }) or $api->$_api_fail;
  return $api;
}

sub get {
  my ($self, $page_name) = @_;
  my $page = $self->api->get_page({ title => $page_name })
    or $self->api->$_api_fail;
  if (defined $page->{missing}) {
    die "MediaWiki page '$page_name' does not exist\n"
      unless $self->allow_create;
    return Page->new(
      name      => $page_name,
      content   => '',
    );
  }
  return Page->new(
    name        => $page_name,
    timestamp   => $page->{timestamp},
    content     => $page->{'*'} || '',
  );
}

sub put {
  my ($self, $page) = @_;
  $self->api->edit({
    action      => 'edit',
    title       => $page->name,
    text        => $page->content,
    summary     => 'System-Introspector-Report Update',
    bot         => 1,
    $page->has_timestamp
      ? (basetimestamp => $page->timestamp)
      : (),
  }) or $self->api->$_api_fail;
  return 1;
}

1;
