require_relative '../../../spec_helper'
require 'helpers/unique_names_helper'

describe Carto::Api::TablesController do
  include UniqueNamesHelper

  describe '#show legacy tests' do

    before(:all) do
      @user = create(:valid_user, private_tables_enabled: true)
      @carto_user = Carto::User.find(@user.id)

      CartoDB::Varnish.any_instance.stubs(:send_command).returns(true)
      host! "#{@user.username}.localhost.lan"
    end

    before(:each) do
      bypass_named_maps
      delete_user_data @user
    end

    after(:all) do
      @user.destroy
    end

    let(:params) {{ api_key: @user.api_key }}

    it 'returns table attributes' do
      table = create_table(
        user_id:      @user.id,
        name:         'My table #1',
        privacy:      UserTable::PRIVACY_PRIVATE,
        tags:         "tag 1, tag 2,tag 3, tag 3",
        description:  'Testing is awesome'
      )

      get_json api_v1_tables_show_url(params.merge(id: table.id)) do |response|
        response.status.should == 200
        response.body.fetch(:name).should == 'my_table_1'
        response.body.fetch(:description).should == 'Testing is awesome'
      end
    end

    it 'returns dependent visualizations' do
      table = create_table(user_id: @user.id)
      visualization = create(:carto_visualization, user: @carto_user)
      visualization.map = create(:carto_map, user: @carto_user)
      visualization.save!
      layer = build(:carto_layer)
      layer.options[:table_name] = table.name
      layer.save
      visualization.layers << layer

      get_json api_v1_tables_show_url(params.merge(id: table.id)) do |response|
        response.status.should == 200
        expect(response.body[:dependent_visualizations]).not_to be_empty
        expect(response.body[:dependent_visualizations][0][:id]).to eq visualization.id
      end
    end

    it "check imported table metadata" do
      data_import = DataImport.create(
        user_id: @user.id,
        data_source: Rails.root.join('spec/support/data/TM_WORLD_BORDERS_SIMPL-0.3.zip').to_s
      ).run_import!

      get_json api_v1_tables_show_url(params.merge(id: data_import.table_id)) do |response|
        response.status.should be_success
        response.body[:name].should == "tm_world_borders_simpl_0_3"
        response.body[:privacy].should == "PRIVATE"
        filter_timestamps(response.body[:schema]).should == [["cartodb_id", "number"], ["the_geom", "geometry", "geometry", "multipolygon"], ["area", "number"], ["fips", "string"], ["iso2", "string"], ["iso3", "string"], ["lat", "number"], ["lon", "number"], ["name", "string"], ["pop2005", "number"], ["region", "number"], ["subregion", "number"], ["un", "number"]]
        response.body[:rows_counted].should == 246
        response.body[:description].should == nil
        response.body[:geometry_types].should == ["ST_MultiPolygon"]
      end
    end

    it "creates a new table without schema" do
      post_json api_v1_tables_create_url(params) do |response|
        response.status.should be_success
        response.body[:id].should == response.headers['Location'].match(/\/([a-f\-\d]+)$/)[1]
        response.body[:name].should match(/^untitled/)
        filter_timestamps(response.body[:schema]).should =~ default_schema
      end
    end

    it "creates a new table without schema when a table of the same name exists on the database" do
      create_table(name: 'untitled_table', user_id: @user.id)
      post_json api_v1_tables_create_url(params) do |response|
        response.status.should be_success
        response.body[:name].should match(/^untitled_table/)
        response.body[:name].should_not == 'untitled_table'
        filter_timestamps(response.body[:schema]).should =~ default_schema
      end
      @user.tables.count.should == 2
    end

    it "creates a new table specifing a name, description and a schema" do
      post_json api_v1_tables_create_url(params.merge(
        name: "My new blank table",
        schema: "code varchar, title varchar, did integer, date_prod timestamp, kind varchar",
        description: "Testing is awesome")) do |response|
        response.status.should be_success
        response.body[:name].should == "my_new_blank_table"
        response.body[:description].should == "Testing is awesome"
        filter_timestamps(response.body[:schema]).should =~ [
           ["cartodb_id", "number"], ["code", "string"], ["title", "string"], ["did", "number"],
           ["the_geom", "geometry", "geometry", "geometry"],
           ["date_prod", "date"], ["kind", "string"]
         ]
      end
    end

    it "updates the metadata of an existing table" do
      table = create_table :user_id => @user.id, :name => 'My table #1',  :tags => "tag 1, tag 2,tag 3, tag 3", :description => ""

       put_json api_v1_tables_update_url(params.merge(
          id: table.id,
          name: table.name,
          tags: "bars,disco",
          privacy: UserTable::PRIVACY_PRIVATE,
          description: "Testing is awesome")) do |response|
        response.status.should be_success
        response.body[:id].should == table.id
        response.body[:name].should == table.name
        response.body[:privacy] == "PRIVATE"
        response.body[:description].should == "Testing is awesome"
        (filter_timestamps(response.body[:schema]) - default_schema).should be_empty
      end
    end

    it "updates with bad values the metadata of an existing table" do
      table1 = create_table :user_id => @user.id, :name => 'My table #1', :tags => "tag 1, tag 2,tag 3, tag 3"
      put_json api_v1_tables_update_url(params.merge(id: table1.id, privacy: 666)) do |response|
        response.status.should == 400
        table1.reload.privacy.should == ::UserTable::PRIVACY_PRIVATE
      end
    end

    it "updates a table and sets the lat and long columns" do
      table = Table.new :privacy => UserTable::PRIVACY_PRIVATE, :name => 'Madrid Bars',
                        :tags => 'movies, personal'
      table.user_id = @user.id
      table.force_schema = "name varchar, address varchar, latitude float, longitude float"
      table.save
      pk = table.insert_row!({:name => "Hawai", :address => "Calle de Pérez Galdós 9, Madrid, Spain", :latitude => 40.423012, :longitude => -3.699732})
      table.insert_row!({:name => "El Estocolmo", :address => "Calle de la Palma 72, Madrid, Spain", :latitude => 40.426949, :longitude => -3.708969})
      table.insert_row!({:name => "El Rey del Tallarín", :address => "Plaza Conde de Toreno 2, Madrid, Spain", :latitude => 40.424654, :longitude => -3.709570})
      table.insert_row!({:name => "El Lacón", :address => "Manuel Fernández y González 8, Madrid, Spain", :latitude => 40.415113, :longitude => -3.699871})
      table.insert_row!({:name => "El Pico", :address => "Calle Divino Pastor 12, Madrid, Spain", :latitude => 40.428198, :longitude => -3.703991})

      put_json api_v1_tables_update_url(params.merge(
        :id => table.id,
        :latitude_column => "latitude",
        :longitude_column => "longitude"
      )) do |response|
        response.status.should be_success
        response.body[:schema].should include(["the_geom", "geometry", "geometry", "point"])
      end
    end

  end

  describe '#show' do
    include_context 'visualization creation helpers'
    include_context 'organization with users helper'

    it 'loads my table if other user has shared a table with the same name with me' do
      table_name = unique_name('table')
      his_table = create_table(privacy: UserTable::PRIVACY_PRIVATE, name: table_name, user_id: @org_user_2.id)
      http_share_table(his_table, @org_user_2, @org_user_1)
      my_table = create_table(privacy: UserTable::PRIVACY_PRIVATE, name: table_name, user_id: @org_user_1.id)
      login(@org_user_1)
      get api_v1_tables_show_url(id: my_table.id) do |response|
        last_response.status.should == 200
        json_body = JSON.parse(last_response.body)
        json_body.fetch(:name).should == my_table.name
        json_body[:table_visualization]['permission']['owner']['username'].should == @org_user_1.username
      end
    end
  end

  private

  # Filter out timestamp columns for compatibility as they won't be
  # present in next version of cartodb-postgresql extension.
  def filter_timestamps(schema)
    schema.reject { |item| ['created_at', 'updated_at'].include?(item[0]) }
  end

end
