import argparse
import os
import sys
from pathlib import Path
import yaml
from .scenario import Scenario
from .plotter import ElevatorPlotter


def get_available_scenarios():
    """Get list of available scenario files."""
    scenarios_dir = Path(__file__).parent / 'scenarios'
    if not scenarios_dir.exists():
        return []

    scenarios = []
    for scenario_file in scenarios_dir.glob('*.yaml'):
        scenarios.append(scenario_file.stem)
    return sorted(scenarios)


def get_default_output_path(scenario_path: str) -> str:
    """Generate default output path based on scenario name."""
    # Get the scenario filename without extension
    scenario_name = Path(scenario_path).stem

    # Create scenarios_out directory path
    scenarios_out_dir = Path(__file__).parent.parent / 'scenarios_out'

    # Ensure the scenarios_out directory exists
    scenarios_out_dir.mkdir(exist_ok=True)

    # Generate output filename with _out suffix
    output_filename = f"{scenario_name}_out.yaml"
    output_path = scenarios_out_dir / output_filename

    return str(output_path)


def get_default_plot_path(scenario_path: str) -> str:
    """Generate default plot path based on scenario name."""
    # Get the scenario filename without extension
    scenario_name = Path(scenario_path).stem

    # Create scenarios_plots directory path
    scenarios_plots_dir = Path(__file__).parent.parent / 'scenarios_plots'

    # Ensure the scenarios_plots directory exists
    scenarios_plots_dir.mkdir(exist_ok=True)

    # Generate plot filename
    plot_filename = f"{scenario_name}_plot.png"
    plot_path = scenarios_plots_dir / plot_filename

    return str(plot_path)


def get_default_plot_path_from_results(results_path: str) -> str:
    """Generate default plot path based on results file name."""
    # Get the results filename without extension and remove _out suffix if present
    results_name = Path(results_path).stem
    if results_name.endswith('_out'):
        results_name = results_name[:-4]

    # Create scenarios_plots directory path
    scenarios_plots_dir = Path(__file__).parent.parent / 'scenarios_plots'

    # Ensure the scenarios_plots directory exists
    scenarios_plots_dir.mkdir(exist_ok=True)

    # Generate plot filename
    plot_filename = f"{results_name}_plot.png"
    plot_path = scenarios_plots_dir / plot_filename

    return str(plot_path)


def run_simulation(scenario_path: str, output_path: str, verbose: bool = False):
    """Run elevator simulation with the given scenario."""
    if not os.path.exists(scenario_path):
        print(f"Error: Scenario file not found: {scenario_path}")
        return False

    try:
        if verbose:
            print(f"Loading scenario: {scenario_path}")

        scenario = Scenario(scenario_path)

        if verbose:
            print("Running simulation...")

        scenario.run()

        if verbose:
            scenario.print_summary()

        scenario.save(output_path)

        if verbose:
            print(f"Results saved to: {output_path}")

        return True

    except (FileNotFoundError, PermissionError, OSError) as e:
        print(f"I/O error running simulation: {e}")
        return False
    except yaml.YAMLError as e:
        print(f"YAML parsing error: {e}")
        return False
    except (ValueError, RuntimeError, TypeError) as e:
        print(f"Simulation error: {e}")
        return False


def generate_plot(results_path: str, output_path: str = None, show_plot: bool = False, show_passenger_ids: bool = False, verbose: bool = False):
    """Generate visualization plot from simulation results."""
    if not os.path.exists(results_path):
        print(f"Error: Results file not found: {results_path}")
        return False

    try:
        if verbose:
            print(f"Loading simulation results: {results_path}")

        plotter = ElevatorPlotter(results_path)

        if verbose:
            print("Simulation Summary:")
            print(f"- Algorithm: {plotter.elevator_logic}")
            print(f"- Elevators: {plotter.n_elevators}")
            print(f"- Floors: {plotter.n_floors}")
            print(f"- Total Passengers: {plotter.total_passengers}")
        plotter.plot_elevator_movements(save_path=output_path, show_plot=show_plot, show_passenger_ids=show_passenger_ids)

        if verbose and output_path:
            print(f"Plot saved to: {output_path}")

        return True

    except (FileNotFoundError, PermissionError, OSError) as e:
        print(f"I/O error generating plot: {e}")
        return False
    except yaml.YAMLError as e:
        print(f"YAML parsing error: {e}")
        return False
    except (ValueError, RuntimeError, TypeError) as e:
        print(f"Error generating plot: {e}")
        return False


def main(): #pylint: disable=too-many-return-statements
    """Main entry point for the elevator traffic analysis application."""
    parser = argparse.ArgumentParser(
        prog='elevator-traffic-analysis',
        description="Elevator Traffic Analysis - Simulate and visualize elevator systems",
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog="""
Examples:
  %(prog)s list-scenarios                           # List available built-in scenarios
  %(prog)s run example --plot --show-passenger-ids  # Run simulation and generate plot with passenger IDs
  %(prog)s run example --plot                       # Run simulation and generate plot
        """
    )

    subparsers = parser.add_subparsers(dest='command', help='Available commands')

    # Run simulation command
    run_parser = subparsers.add_parser('run', help='Run elevator simulation')
    run_parser.add_argument(
        'scenario',
        help='Scenario name (built-in) or path to scenario YAML file'
    )
    run_parser.add_argument(
        '-o', '--output',
        help='Output file for simulation results (default: scenarios_out/<scenario_name>_out.yaml)'
    )
    run_parser.add_argument(
        '--plot',
        action='store_true',
        help='Generate plot after running simulation'
    )
    run_parser.add_argument(
        '--plot-output',
        help='Output file for plot (default: scenarios_plots/<scenario_name>_plot.png)'
    )
    run_parser.add_argument(
        '--show-plot',
        action='store_true',
        help='Display plot in window (if supported by environment)'
    )
    run_parser.add_argument(
        '--show-passenger-ids',
        action='store_true',
        help='Show passenger IDs on the plot (may clutter with many passengers)'
    )
    run_parser.add_argument(
        '-v', '--verbose',
        action='store_true',
        help='Enable verbose output'
    )

    # Plot generation command
    plot_parser = subparsers.add_parser('plot', help='Generate visualization from results')
    plot_parser.add_argument(
        '-i', '--input',
        default='simulation_results.yaml',
        help='Input simulation results file (default: simulation_results.yaml)'
    )
    plot_parser.add_argument(
        '-o', '--output',
        help='Output plot file (default: scenarios_plots/<results_name>_plot.png)'
    )
    plot_parser.add_argument(
        '--show',
        action='store_true',
        help='Display plot in window (if supported by environment)'
    )
    plot_parser.add_argument(
        '--show-passenger-ids',
        action='store_true',
        help='Show passenger IDs on the plot (may clutter with many passengers)'
    )
    plot_parser.add_argument(
        '-v', '--verbose',
        action='store_true',
        help='Enable verbose output'
    )

    # List scenarios command
    subparsers.add_parser('list-scenarios', help='List available built-in scenarios')

    args = parser.parse_args()

    if args.command is None:
        parser.print_help()
        return 1

    # Handle list-scenarios command
    if args.command == 'list-scenarios':
        scenarios = get_available_scenarios()
        if scenarios:
            print("Available built-in scenarios:")
            for scenario in scenarios:
                print(f"  - {scenario}")
        else:
            print("No scenarios found.")
        return 0

    # Handle run command
    if args.command == 'run':
        # Determine scenario path
        scenario_path = args.scenario
        if not os.path.exists(scenario_path):
            # Try to find it in the package scenarios directory
            scenarios_dir = Path(__file__).parent / 'scenarios'
            potential_path = scenarios_dir / f"{args.scenario}.yaml"
            if potential_path.exists():
                scenario_path = str(potential_path)
            else:
                print(f"Error: Scenario '{args.scenario}' not found.")
                print("Available scenarios:")
                for scenario in get_available_scenarios():
                    print(f"  - {scenario}")
                return 1

        # Determine output path
        output_path = args.output if args.output else get_default_output_path(scenario_path)

        # Run simulation
        if not run_simulation(scenario_path, output_path, args.verbose):
            return 1

        # Generate plot if requested
        if args.plot:
            plot_output = args.plot_output or get_default_plot_path(scenario_path)
            if not generate_plot(output_path, plot_output, args.show_plot, args.show_passenger_ids, args.verbose):
                return 1

    # Handle plot command
    if args.command == 'plot':
        # Determine plot output path
        plot_output = args.output if args.output else get_default_plot_path_from_results(args.input)
        if not generate_plot(args.input, plot_output, args.show, args.show_passenger_ids, args.verbose):
            return 1

    return 0


if __name__ == "__main__":
    sys.exit(main())