package Debian::PkgJs::PackageLock;

use strict;
use Debian::Control;
use Dpkg::IPC;
use Exporter 'import';
use JSON;
use Debian::PkgJs::Utils;
use Debian::PkgJs::Version;

our @EXPORT = ( '&buildPackageLock', '&builtUsing' );

our $BUILTUSING = {};

my $WEBPACKS = qr/^.*(?:browserify|webpack|rollup).*$/i;
*debug = \&Debian::PkgJs::Utils::debug;

sub buildPackageLock {
    my ( $src, $dst, $check ) = @_;
    die 'Destination needed' unless $dst;
    if ($check) {
        require Debian::Control;
        my $c = Debian::Control->new;
        $c->read('debian/control');
        my $bundle = 0;
        map { $bundle++ if $_->pkg =~ $WEBPACKS }
          @{ $c->source->Build_Depends };
        return unless $bundle;
        debug("Package looks like a bundle, generating pkgjs-lock.json file");
    }
    my $pjson = pjson($src);
    my $deps  = {
        %{ $pjson->{devDependencies} // {} },
        %{ $pjson->{dependencies}    // {} }
    };
    my $res = {
        name            => $pjson->{name},
        version         => $pjson->{version},
        lockfileVersion => 2,
        packages        => {
            "" => {
                name    => $pjson->{name},
                version => $pjson->{version},
            },
        },
        dependencies  => {},
        pkgjs_version => $VERSION,
    };
    my $count = 0;
    if ( $deps and %$deps ) {
        foreach my $dep ( keys %$deps ) {
            my ( $out, $err );
            if ( -d "node_modules/$dep" ) {
                $out = "node_modules/$dep";
            }
            else {
                spawn(
                    exec            => [ 'nodepath', $dep ],
                    nocheck         => 1,
                    wait_child      => 1,
                    to_string       => \$out,
                    error_to_string => \$err,
                );
                chomp $out;

                # Fix reproducibility
                unless (
                    $out =~ s#.*(/usr/(?:share|lib(?:/[^/]+)?)/nodejs/)#$1# )
                {
                    $out =~ s#^/.*$#node_modules/$dep#;
                }
            }
            if ( $out and my $pjs = pjson($out) ) {
                $count++;
                $res->{packages}->{$out} = {
                    name    => $dep,
                    version => $pjs->{version} || 'unknown',
                };
                $res->{dependencies}->{$dep} =
                  { version => $pjs->{version} || '*', };
                $BUILTUSING->{"node-$dep"} = $pjs->{version} || '';
            }
        }
    }
    unless ($count) {
        debug("No build dependencies found, skip pkgjs-lock.json");
        return;
    }
    open my $fdst, '>', $dst or die "Unable to write package-lock.json: $!";
    my $str = JSON->new->canonical->indent->encode($res);
    $str =~ s/   / /g;
    chomp $str;
    print $fdst $str;
    close $fdst;
}

sub builtUsing {
    return join(
        ',',
        map {
            normalize_name($_)
              . (
                $BUILTUSING->{$_}
                ? " (= $BUILTUSING->{$_})"
                : ''
              )
          }
          sort keys %$BUILTUSING
    );
}

1;
