#!/usr/bin/env perl

use v5.36;

use strict;
use warnings;

use Getopt::Long qw(:config no_ignore_case);
use Pod::Usage;
use Term::ANSIColor qw(colored);
use Path::Tiny;
use YAML::XS qw(LoadFile);

use App::GHGen::Generator qw(generate_workflow list_workflow_types);
use App::GHGen::Analyzer qw(analyze_workflow find_workflows);
use App::GHGen::Detector qw(detect_project_type get_project_indicators);
use App::GHGen::Interactive qw(customize_workflow);
use App::GHGen::PerlCustomizer qw(generate_custom_perl_workflow);
use App::GHGen::Fixer qw(fix_workflow can_auto_fix);
use App::GHGen::CostEstimator qw(estimate_current_usage estimate_savings);

our $VERSION = '0.01';

my %opts = (
	help	=> 0,
	version => 0,
	list	=> 0,
);

GetOptions(
	'help|h'	=> \$opts{help},
	'version|v'   => \$opts{version},
	'type|t=s'	=> \$opts{type},
	'output|o=s'  => \$opts{output},
	'list|l'	  => \$opts{list},
	'interactive|i' => \$opts{interactive},
	'auto|a'	  => \$opts{auto},
	'customize|c' => \$opts{customize},
	'fix|f'	   => \$opts{fix},
	'estimate|e'  => \$opts{estimate},
) or pod2usage(2);

pod2usage(1) if $opts{help};

if ($opts{version}) {
	say "ghgen version $VERSION";
	exit 0;
}

my $command = shift @ARGV // '';

if ($command eq 'generate') {
	cmd_generate();
} elsif ($command eq 'analyze') {
	cmd_analyze();
} else {
	pod2usage(-message => "Unknown command: $command", -exitval => 1);
}

sub cmd_generate() {
	if ($opts{list}) {
		list_types();
		return;
	}

	my $type = $opts{type};
	my $config;

	# Auto-detect if requested
	if ($opts{auto} || (!$type && !$opts{interactive} && !$opts{customize})) {
		$type = auto_detect_with_prompt();
		return unless $type;  # User cancelled
	}

	# Interactive mode
	if ($opts{interactive} && !$type) {
		$type = interactive_select_type();
	}

	unless ($type) {
		die colored(['red'], "Error: ") .
			"Please specify --type, use --auto, or use --interactive\n";
	}

	# Customization mode
	if ($opts{customize}) {
		$config = customize_workflow($type);
	}

	# Generate workflow with optional customization
	my $yaml;
	if ($config && $type eq 'perl') {
		# Use customized Perl workflow
		my @perl_versions = @{$config->{perl_versions} // ['5.40', '5.38', '5.36']};
		$yaml = generate_custom_perl_workflow({
			min_perl_version => $perl_versions[0],
			max_perl_version => $perl_versions[-1],
			perl_versions => \@perl_versions,
			os => $config->{os} // ['ubuntu-latest', 'macos-latest', 'windows-latest'],
			enable_critic => $config->{enable_critic} // 1,
			enable_coverage => $config->{enable_coverage} // 1,
		});
	} else {
		$yaml = generate_workflow($type);
	}

	unless ($yaml) {
		die colored(['red'], "Error: ") .
			"Unknown project type '$type'. Use --list to see options.\n";
	}

	# Determine output file
	my $output_file = $opts{output};
	unless ($output_file) {
		my $workflows_dir = path('.github/workflows');
		$workflows_dir->mkpath unless $workflows_dir->exists;
		$output_file = $workflows_dir->child("$type-ci.yml");
	}

	# Write the workflow
	path($output_file)->spew_utf8($yaml);

	say colored(['green'], "✓ ") . "Generated workflow: " . colored(['bold'], $output_file);
	say '';
	say colored(['cyan'], "Next steps:");
	say "  1. Review the generated workflow";
	say "  2. Customize it for your project";
	say "  3. Commit and push to trigger the workflow";
	say '';
	say colored(['yellow'], "💡 Tip: ") . "Run 'ghgen analyze' to check for optimizations";
}

sub cmd_analyze() {
	my @workflow_files = find_workflows();

	unless (@workflow_files) {
		die colored(['red'], "Error: ") .
			"No .github/workflows directory found\n" .
			"Run this from the root of a repository with GitHub Actions.\n";
	}

	say colored(['bold cyan'], "GitHub Actions Workflow Analyzer");
	if ($opts{fix}) {
		say colored(['yellow'], "(Auto-fix mode enabled)");
	}
	if ($opts{estimate}) {
		say colored(['cyan'], "(Cost estimation mode)");
	}
	say colored(['cyan'], "=" x 50);
	say '';

	# Get cost estimate first if requested
	my $current_usage;
	if ($opts{estimate}) {
		say colored(['bold'], "📊 Estimating current CI usage...");
		say '';
		$current_usage = estimate_current_usage(\@workflow_files);

		say colored(['bold'], "Current Monthly Usage:");
		say "  Total CI minutes: " . colored(['yellow'], $current_usage->{total_minutes});
		say "  Billable minutes: " . colored(['yellow'], $current_usage->{billable_minutes}) .
			" (after 2,000 free tier)";
		say "  Estimated cost: " . colored(['yellow'], sprintf("\$%.2f", $current_usage->{monthly_cost}));
		say '';

		if (@{$current_usage->{workflows}} > 1) {
			say colored(['bold'], "Per-Workflow Breakdown:");
			for my $wf (sort { $b->{minutes_per_month} <=> $a->{minutes_per_month} }
						@{$current_usage->{workflows}}) {
				say sprintf("  %-40s %4d min/month (%3d runs × %4.1f min/run)",
					$wf->{name},
					$wf->{minutes_per_month},
					$wf->{runs_per_month},
					$wf->{minutes_per_run});
			}
			say '';
		}
	}

	my @all_issues;
	my $total_workflows = 0;
	my $total_fixes = 0;

	# Analyze each workflow file
	for my $file (@workflow_files) {
		$total_workflows++;
		say colored(['bold'], "📄 Analyzing: ") . $file->basename;

		my $workflow;
		eval { $workflow = LoadFile($file) };
		if ($@) {
			say colored(['red'], "  ✗ Failed to parse YAML: $@");
			next;
		}

		my @issues = analyze_workflow($workflow, $file->basename);

		if (@issues) {
			# Filter to auto-fixable issues if in fix mode
			my @fixable = $opts{fix} ? grep { can_auto_fix($_) } @issues : @issues;

			if ($opts{fix} && @fixable) {
				say "  " . colored(['yellow'], "⚙ ") . "Applying " . scalar(@fixable) . " fix(es)...";

				my $fixes = fix_workflow($file, \@fixable);
				$total_fixes += $fixes;

				if ($fixes > 0) {
					say "  " . colored(['green'], "✓ ") . "Applied $fixes fix(es)";
				} else {
					say "  " . colored(['yellow'], "⚠ ") . "Could not apply some fixes automatically";
				}
			} else {
				# Just report issues
				for my $issue (@issues) {
					my $icon = can_auto_fix($issue) ? "⚠" : "ℹ";
					say "  " . colored(['yellow'], "$icon ") . $issue->{message};
					if ($issue->{fix} && !$opts{fix} && !$opts{estimate}) {
						say colored(['cyan'], "	 💡 Fix:");
						for my $line (split /\n/, $issue->{fix}) {
							say "	 " . $line;
						}
					}
				}
			}

			push @all_issues, map { { file => $file->basename, %$_ } } @issues;
		} else {
			say "  " . colored(['green'], "✓ No issues found");
		}
		say '';
	}

	# Summary
	say colored(['bold cyan'], "=" x 50);
	say colored(['bold'], "Summary:");
	say "  Workflows analyzed: $total_workflows";
	say "  Total issues found: " . scalar(@all_issues);

	if ($opts{fix}) {
		say "  Fixes applied: " . colored(['green'], $total_fixes);
	}

	# Cost savings estimate
	if ($opts{estimate} && @all_issues) {
		say '';
		my $savings = estimate_savings(\@all_issues, \@workflow_files);

		if ($savings->{minutes} > 0) {
			say colored(['bold'], "💰 Potential Savings:");
			say '  With recommended changes: ' . colored(['green'], ($current_usage->{total_minutes} - $savings->{minutes})) .
				" CI minutes/month";
			say "  Reduction: " . colored(['green'], "-$savings->{minutes} minutes") .
				" (" . colored(['green'], "$savings->{percentage}%") . ")";
			say "  Cost savings: " . colored(['green'], "\$savings->{cost}/month") .
				" (for private repos)";

			if (@{$savings->{details}}) {
				say '';
				say "  Breakdown:";
				for my $detail (@{$savings->{details}}) {
					say "	• $detail->{description}: ~$detail->{minutes} min/month";
				}
			}
		}
	}

	if (@all_issues && !$opts{fix}) {
		say '';
		say colored(['bold yellow'], "Recommendations:");
		my %by_type;
		push @{$by_type{$_->{type}}}, $_ for @all_issues;

		for my $type (sort keys %by_type) {
			my $count = scalar @{$by_type{$type}};
			my $fixable = grep { can_auto_fix($_) } @{$by_type{$type}};
			my $suffix = $fixable > 0 ? " ($fixable auto-fixable)" : '';
			say "  • " . colored(['yellow'], "$type") . ": $count workflow(s) affected$suffix";
		}

		say '';
		say colored(['cyan'], "💡 Tip: ") .  "Run " . colored(['bold'], "ghgen analyze --fix") .
			" to automatically apply fixes";

		if (!$opts{estimate}) {
			say colored(['cyan'], "💡 Tip: ") . "Run " . colored(['bold'], "ghgen analyze --estimate") .
				" to see potential cost savings";
		}
	}

	exit(@all_issues ? 1 : 0);
}

sub list_types() {
	say colored(['bold cyan'], "Available workflow templates:");
	say '';

	my %types = list_workflow_types();

	for my $type (sort keys %types) {
		say "  " . colored(['green'], sprintf("%-10s", $type)) . " - $types{$type}";
	}

	say '';
	say "Usage: ghgen generate --type=<type> [--output=<file>]";
	say "   or: ghgen generate --interactive";
}

sub interactive_select_type() {
	say colored(['bold cyan'], "GitHub Actions Workflow Generator");
	say colored(['cyan'], "=" x 50);
	say '';
	say "Select a project type:";
	say '';

	my @types = qw(node python rust go ruby perl java cpp php docker static);
	my %descriptions = (
		node   => 'Node.js/npm',
		python => 'Python',
		rust   => 'Rust',
		go	 => 'Go',
		ruby   => 'Ruby',
		perl   => 'Perl',
		java   => 'Java (Maven/Gradle)',
		cpp	=> 'C++ (CMake)',
		php	=> 'PHP (Composer)',
		docker => 'Docker',
		static => 'Static site (GitHub Pages)',
	);

	for my $i (0..$#types) {
		say "  " . colored(['green'], $i + 1) . ". $descriptions{$types[$i]}";
	}

	say '';
	print "Enter number (1-" . scalar(@types) . "): ";
	chomp(my $choice = <STDIN>);

	if ($choice =~ /^\d+$/ && $choice >= 1 && $choice <= @types) {
		return $types[$choice - 1];
	}

	die colored(['red'], "Invalid choice\n");
}

sub auto_detect_with_prompt() {
	say colored(['bold cyan'], "Auto-detecting project type...");
	say '';

	my @detections = detect_project_type();

	unless (@detections) {
		say colored(['yellow'], "⚠ ") . "Could not auto-detect project type.";
		say '';
		say "Try one of these options:";
		say "  • " . colored(['cyan'], "ghgen generate --list") . " - see all available types";
		say "  • " . colored(['cyan'], "ghgen generate --interactive") . " - choose interactively";
		say "  • " . colored(['cyan'], "ghgen generate --type=<type>") . " - specify type directly";
		return undef;
	}

	# Show top detection
	my $top = $detections[0];
	say colored(['green'], "✓ ") . "Detected project type: " .
		colored(['bold'], uc($top->{type}));

	# Show evidence
	my $indicators = get_project_indicators($top->{type});
	my @found_indicators;
	for my $indicator (@$indicators) {
		# Simple file check (not glob patterns)
		if ($indicator !~ /[\*\?]/ && path($indicator)->exists) {
			push @found_indicators, $indicator;
			last if @found_indicators >= 3;  # Show max 3
		}
	}

	if (@found_indicators) {
		say colored(['cyan'], "  Evidence: ") . join(', ', @found_indicators);
	}
	say '';

	# Show alternatives if any
	if (@detections > 1) {
		say colored(['yellow'], "Other possibilities:");
		for my $i (1 .. min(2, $#detections)) {
			say "  • $detections[$i]->{type} (confidence: " . int($detections[$i]->{score} / $top->{score} * 100) . "%)";
		}
		say '';
	}

	# Prompt for confirmation
	print "Generate " . colored(['bold'], uc($top->{type})) . " workflow? [Y/n]: ";
	chomp(my $response = <STDIN>);

	if ($response =~ /^(y|yes|)$/i) {
		return $top->{type};
	} elsif ($response =~ /^(n|no)$/i) {
		say '';
		say "Cancelled. Use " . colored(['cyan'], "--interactive") .  " to choose manually.";
		return undef;
	} else {
		say colored(['red'], "Invalid response. Cancelled.");
		return undef;
	}
}

sub min($a, $b) {
	return $a < $b ? $a : $b;
}

__END__

=head1 NAME

ghgen - GitHub Actions workflow generator and analyzer

=head1 SYNOPSIS

  ghgen generate --auto
  ghgen generate --type=perl [--output=FILE]
  ghgen generate --type=perl --customize
  ghgen generate --interactive
  ghgen generate --list

  ghgen analyze
  ghgen analyze --fix

  ghgen --help
  ghgen --version

=head1 DESCRIPTION

B<ghgen> helps you create and optimize GitHub Actions workflows.

=head1 COMMANDS

=head2 generate

Generate a new GitHub Actions workflow.

  ghgen generate --auto
  ghgen generate --type=perl
  ghgen generate --type=perl --customize
  ghgen generate --type=node --output=custom.yml
  ghgen generate --interactive
  ghgen generate --list

Options:

  --auto, -a			Auto-detect project type and prompt for confirmation
  --type, -t TYPE	   Project type (perl, node, python, rust, go, ruby, docker, static)
  --customize, -c	   Interactively customize the workflow
  --output, -o FILE	 Output file (default: .github/workflows/TYPE-ci.yml)
  --interactive, -i	 Interactive mode to select type
  --list, -l			List available workflow types

=head2 analyze

Analyze existing workflows for issues and optimizations.

  ghgen analyze

Checks for:
- Missing dependency caching
- Unpinned action versions
- Overly broad triggers
- Missing concurrency controls
- Outdated runner versions

=head1 OPTIONS

=over 4

=item B<--help, -h>

Show this help message.

=item B<--version, -v>

Show version information.

=back

=head1 EXAMPLES

Auto-detect and generate workflow:

  cd my-project
  ghgen generate --auto

Generate a Perl workflow with customization:

  ghgen generate --type=perl --customize

Interactively select and generate a workflow:

  ghgen generate --interactive

Analyze all workflows in current repository:

  ghgen analyze

=head1 AUTHOR

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

L<https://github.com/nigelhorne>

=head1 LICENSE

This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.

=cut
