#!/usr/bin/env perl

use strict;
use warnings;
use autodie qw(:all);

use Getopt::Long qw(GetOptions);
use Path::Tiny;
use Text::Diff;
use App::makefilepl2cpanfile;

=head1 NAME

makefilepl2cpanfile - Convert a Makefile.PL to a cpanfile

=head1 SYNOPSIS

    bin/makefilepl2cpanfile [options]

Options:

    --with-develop    Include author/development dependencies (default)
    --no-develop      Exclude author/development dependencies
    --dry-run         Print output to STDOUT instead of writing cpanfile
    --diff            Show diff against existing cpanfile if it exists
    --check           Verify all Makefile.PL dependencies appear in output
    --help            Show this usage message

=head1 DESCRIPTION

Reads a F<Makefile.PL> in the current directory and generates a corresponding
F<cpanfile>.  Existing C<develop> blocks in a pre-existing F<cpanfile> are
preserved and merged.

=cut

my ($with_dev, $no_dev, $dry, $diff, $check, $help);

GetOptions(
	'with-develop' => \$with_dev,
	'no-develop'   => \$no_dev,
	'dry-run'      => \$dry,
	'diff'         => \$diff,
	'check'        => \$check,
	'help'         => \$help,
) or _usage();

_usage() if $help;

die "--with-develop and --no-develop are mutually exclusive\n"
	if $with_dev && $no_dev;

$with_dev //= !$no_dev;

# Read existing cpanfile so its develop block can be preserved during merge.
my $cpanfile_path = path('cpanfile');
my $existing = $cpanfile_path->is_file ? $cpanfile_path->slurp_utf8 : '';

my $out = App::makefilepl2cpanfile::generate(
	makefile     => 'Makefile.PL',
	existing     => $existing,
	with_develop => $with_dev,
);

# --check: reuse the library's parser to verify nothing was dropped.
# This avoids duplicating the extraction regex in the script.
if ($check) {
	my $content  = path('Makefile.PL')->slurp_utf8;
	my $expected = App::makefilepl2cpanfile::parse_prereqs($content);

	my @missing;
	for my $phase (keys %{$expected}) {
		for my $rel (keys %{ $expected->{$phase} }) {
			for my $mod (sort keys %{ $expected->{$phase}{$rel} }) {
				push @missing, $mod unless $out =~ /\b\Q$mod\E\b/;
			}
		}
	}

	if (@missing) {
		warn "WARNING: The following modules from Makefile.PL did not appear in the output:\n";
		warn "  $_\n" for @missing;
	} else {
		print "All Makefile.PL prerequisites are present in the output.\n";
	}
}

# --diff: show unified diff against the existing file, then exit.
if ($diff && $existing) {
	print diff(\$existing, \$out, { STYLE => 'Unified' });
	exit 0;
}

# --dry-run: print to STDOUT instead of writing to disk.
if ($dry) {
	print $out;
	exit 0;
}

$cpanfile_path->spew_utf8($out);
print "cpanfile written successfully.\n";

sub _usage {
	print <<"END_USAGE";

Usage: $0 [options]

  --with-develop    Include author/development dependencies (default)
  --no-develop      Exclude author/development dependencies
  --dry-run         Print output instead of writing cpanfile
  --diff            Show diff against existing cpanfile
  --check           Verify all Makefile.PL dependencies appear in output
  --help            Show this help message

END_USAGE
	exit 0;
}

__END__

=head1 SUPPORT

This program is provided as-is without any warranty.

=head1 AUTHOR

Nigel Horne E<lt>njh@nigelhorne.comE<gt>

=head1 LICENCE AND COPYRIGHT

Copyright 2025-2026 Nigel Horne.

Personal single user, single computer use: GPL2.
All other users must apply in writing for a licence.

=cut
