# @@tag
desc 'Add tag(s) to last entry'
long_desc 'Add (or remove) tags from the last entry, or from multiple entries
          (with `--count`), entries matching a search (with `--search`), or entries
          containing another tag (with `--tag`).

          When removing tags with `-r`, wildcards are allowed (`*` to match
          multiple characters, `?` to match a single character). With `--regex`,
          regular expressions will be interpreted instead of wildcards.

          For all tag removals the match is case insensitive by default, but if
          the tag search string contains any uppercase letters, the match will
          become case sensitive automatically.

          Tag name arguments do not need to be prefixed with @.'
arg_name 'TAG', :multiple
command :tag do |c|
  c.example 'doing tag mytag', desc: 'Add @mytag to the last entry created'
  c.example 'doing tag --remove mytag', desc: 'Remove @mytag from the last entry created'
  c.example 'doing tag --rename "other*" --count 10 newtag', desc: 'Rename tags beginning with "other" (wildcard) to @newtag on the last 10 entries'
  c.example 'doing tag --search "developing" coding', desc: 'Add @coding to the last entry containing string "developing" (fuzzy matching)'
  c.example 'doing tag --interactive --tag project1 coding', desc: 'Create an interactive menu from entries tagged @project1, selection(s) will be tagged with @coding'

  c.desc 'Section'
  c.arg_name 'SECTION_NAME'
  c.flag %i[s section], default_value: 'All', multiple: true

  c.desc 'How many recent entries to tag (0 for all)'
  c.arg_name 'COUNT'
  c.flag %i[c count], default_value: 1, must_match: /^\d+$/, type: Integer

  c.desc 'Replace existing tag with tag argument, wildcards (*,?) allowed, or use with --regex'
  c.arg_name 'ORIG_TAG'
  c.flag %i[rename]

  c.desc 'Include a value, e.g. @tag(value)'
  c.arg_name 'VALUE'
  c.flag %i[v value]

  c.desc 'Don\'t ask permission to tag all entries when count is 0'
  c.switch %i[force], negatable: false, default_value: false

  c.desc 'Include current date/time with tag'
  c.switch %i[d date], negatable: false, default_value: false

  c.desc 'Remove given tag(s)'
  c.switch %i[r remove], negatable: false, default_value: false

  c.desc 'Interpret tag string as regular expression (with --remove)'
  c.switch %i[regex], negatable: false, default_value: false

  c.desc 'Tag last entry (or entries) not marked @done'
  c.switch %i[u unfinished], negatable: false, default_value: false

  c.desc 'Autotag entries based on autotag configuration in ~/.config/doing/config.yml'
  c.switch %i[a autotag], negatable: false, default_value: false

  c.desc 'Select item(s) to tag from a menu of matching entries'
  c.switch %i[i interactive], negatable: false, default_value: false

  add_options(:search, c)
  add_options(:tag_filter, c)

  c.action do |_global_options, options, args|
    options[:fuzzy] = false
    # raise MissingArgument, 'You must specify at least one tag' if args.empty? && !options[:autotag]

    raise InvalidArgument, '--search and --tag can not be used together' if options[:search] && options[:tag]

    section = 'All'

    if options[:section]
      section = @wwid.guess_section(options[:section]) || options[:section].cap_first
    end

    search_tags = options[:tag].nil? ? [] : options[:tag]

    if options[:autotag]
      tags = []
    else
      tags = if args.empty?
               []
             elsif args.join('') =~ /,/
               args.join('').split(/ *, */)
             else
               args.join(' ').split(' ') # in case tags are quoted as one arg
             end

      tags.map! { |tag| tag.sub(/^@/, '').strip }
    end

    if options[:interactive]
      count = 0
      options[:force] = true
    else
      count = options[:count].to_i
    end

    if options[:search]
      search = options[:search]
      search.sub!(/^'?/, "'") if options[:exact]
      options[:search] = search
    end

    options[:count] = count
    options[:section] = section
    options[:tag] = search_tags
    options[:tags] = tags
    options[:tag_bool] = options[:bool]

    if count.zero? && !options[:force]
      matches = @wwid.filter_items([], opt: options).count

      if matches > 5
        if options[:search]
          section_q = ' matching your search terms'
        elsif options[:tag]
          section_q = ' matching your tag search'
        elsif section == 'All'
          section_q = ''
        else
          section_q = " in section #{section}"
        end


        question = if options[:autotag]
                     "Are you sure you want to autotag #{matches} records#{section_q}"
                   elsif options[:remove]
                     "Are you sure you want to remove #{tags.join(' and ')} from #{matches} records#{section_q}"
                   else
                     "Are you sure you want to add #{tags.join(' and ')} to #{matches} records#{section_q}"
                   end

        res = Doing::Prompt.yn(question, default_response: false)

        raise UserCancelled unless res
      end
    end

    @wwid.tag_last(options)
  end
end