#!/usr/bin/env ruby
# frozen_string_literal: true

# Ruby internal
# Project internal
require 'pass_station'
require 'pass_station/output'
# External
require 'docopt'
require 'paint'

doc = <<~DOCOPT
  #{Paint['Pass Station', :bold, '#2db453']} v#{Paint[PassStation::VERSION, :bold]}

  #{Paint['Usage:', '#2db453']}
    pass-station list [--sort <col> --output <format>] [--source <id> --debug]
    pass-station search <term> [--field <col> --sort <col> --sensitive --output <format>] [--source <id> --no-color --debug]
    pass-station update ([--force] <path> | --check) [--debug]
    pass-station -h | --help
    pass-station --version

  #{Paint['List options:', '#2db453']} #{Paint['list all default credentials', :underline]}

  #{Paint['Output options:', '#2db453']} #{Paint['can be used with list and search commands', :underline]}
    -o <format>, --output <format>  Output format: JSON, CSV, YAML, table, pretty-table [default: pretty-table]
    -s <col>, --sort <col>          Sort by column (see documentation, columns depends on the database source)

  #{Paint['Search options:', '#2db453']} #{Paint['search for default credentials', :underline]}
    --field <col>   Search in column: column name (see documentation, columns depends on the database source) or all
    --sensitive     Search is case sensitive (case insensitive by default)

  #{Paint['Update options:', '#2db453']} #{Paint['update the password database (replace Pass Station DB with upstream DB, use with care)', :underline]}
    -f, --force   Bypass hash checking
    -c, --check   Check for possible update

  #{Paint['Other options:', '#2db453']}
    --source <id> Credentials source database: 1 (Default Credentials Cheat Sheet), 2 (Many passwords) [default: 1]
    --no-color    Disable colorized output
    --debug       Display arguments
    -h, --help    Show this screen
    --version     Show version

  #{Paint['Examples:', '#2db453']}
    pass-station search WEBLOGIC --field username --sensitive
    pass-station search 'admin[0-9]+' --field all
    pass-station list --sort username --output json

  #{Paint['Project:', '#2db453']}
    #{Paint['author', :underline]} (https://pwn.by/noraj / https://x.com/noraj_rawsec)
    #{Paint['source', :underline]} (https://github.com/noraj/pass-station)
    #{Paint['documentation', :underline]} (https://noraj.github.io/pass-station)
DOCOPT

begin
  args = Docopt.docopt(doc, version: PassStation::VERSION)
  Paint.mode = 0 if args['--no-color']
  puts args if args['--debug']
  if args['update']
    if args['<path>']
      PassStation::DB::UPSTREAM_DATABASE[:MAPPING].each do |k, v|
        opts = {}
        opts[:sha256] = args['--force'] ? nil : PassStation::DB::UPSTREAM_DATABASE[v][:HASH]
        puts "[+] Updating database: #{v}"
        opts[:source_db] = k
        path = PassStation::DB.download_upstream(args['<path>'], opts)
        if path
          puts "[+] Database updated: #{v} (#{path})"
        else
          puts "[+] Database #{v} already up to date"
        end
      end
    elsif args['--check']
      if PassStation::DB.check_for_update
        puts '[+] Update available'
      else
        puts '[+] No update available'
      end
    end
  elsif args['list']
    db = args['--source']&.to_i
    ps = PassStation::DB.new(db)
    args['--sort'].nil? ? ps.parse : ps.parse(args['--sort'].to_sym)
    puts ps.output_list(args['--output'])
  elsif args['search']
    db = args['--source']&.to_i
    ps = PassStation::DB.new(db)
    args['--sort'].nil? ? ps.parse : ps.parse(args['--sort'].to_sym)
    field = args['--field']&.to_sym
    ps.search(args['<term>'], field, sensitive: args['--sensitive'])
    output = ps.output_search(args['--output'])
    puts '[-] No result' if output.empty?
    puts ps.highlight_found(args['<term>'], output, args['--sensitive'])
  end
rescue Docopt::Exit => e
  puts e.message
end
