package main

import (
	"reflect"
	"sort"
	"testing"

	"code.justin.tv/rhys/nursery/pgparse"
)

func TestThing(t *testing.T) {
	tests := [...]struct {
		query  string
		tables []string
	}{
		{query: `SELECT  "tickets".* FROM "tickets" INNER JOIN "ticket_products" ON "ticket_products"."id" = "tickets"."ticket_product_id" WHERE "tickets"."owner_id" = 43296162 AND "ticket_products"."ticket_type" = 'turbo' AND (NOT (("tickets"."access_end" IS NOT NULL AND "tickets"."access_end" < '2014-12-04 00:59:09.543281' OR "tickets"."access_start" IS NOT NULL AND "tickets"."access_start" > '2014-12-04 00:59:09.543325'))) ORDER BY created_on LIMIT 1 /*application:Twitch,controller:viewer,action:info*/`,
			tables: []string{"ticket_products", "tickets"}},
		{query: `SELECT  "favorites".* FROM "favorites" INNER JOIN "users" ON "users"."id" = "favorites"."to_user_id" WHERE "favorites"."to_user_id" = 43362782 AND (users.category = 'gaming') AND (hidden is distinct from true) ORDER BY favorites.created_on DESC LIMIT 100 OFFSET 0 /*application:Twitch,controller:channels,action:follows*/`,
			tables: []string{"favorites", "users"}},
		{query: `SELECT  "tickets".* FROM "tickets"  WHERE "tickets"."ticket_product_id" IN (SELECT "ticket_products"."id" FROM "ticket_products"  WHERE (("ticket_products"."ticket_product_owner_type" = 'User' AND "ticket_products"."ticket_product_owner_id" = 14342567 OR "ticket_products"."ticket_product_owner_type" = 'Team' AND "ticket_products"."ticket_product_owner_id" IN (535, 1073, 1155, 1116))) ORDER BY default_price, created_on) AND (NOT (("tickets"."access_end" IS NOT NULL AND "tickets"."access_end" < '2014-12-04 00:59:09.610134' OR "tickets"."access_start" IS NOT NULL AND "tickets"."access_start" > '2014-12-04 00:59:09.610147'))) ORDER BY created_on DESC LIMIT 25 OFFSET 0 /*application:Twitch,controller:subscriptions,action:index*/`,
			tables: []string{"ticket_products", "tickets"}},
		{query: `SELECT  "messages".* FROM "messages"  WHERE "messages"."user_id" = 36114941 AND "messages"."safe" = 'f' AND (user_id = to_user_id) ORDER BY created_on DESC LIMIT 10 OFFSET 0 /*application:Twitch,controller:message,action:list*/`,
			tables: []string{"messages"}},
		{query: `SELECT  "message_blocks".* FROM "message_blocks"  WHERE "message_blocks"."user_id" = 53032055 ORDER BY updated_on DESC NULLS LAST LIMIT 25 OFFSET 0 /*application:Twitch,controller:blocks,action:index*/`,
			tables: []string{"message_blocks"}},
		{query: `SELECT "users".* FROM "users"  WHERE (lower(email) = 'redacted@gmail.com') /*application:Twitch,controller:follows,action:update*/`,
			tables: []string{"users"}},
		{query: `SELECT  "oauth2_clients".* FROM "oauth2_clients"  WHERE "oauth2_clients"."client_id" = 'redacted' AND (hidden IS false) LIMIT 1 /*application:Twitch,controller:clients,action:video_status*/`,
			tables: []string{"oauth2_clients"}},
		{query: `SELECT featured_events.* FROM "featured_events" join events ce on ce.id = event_id WHERE (now() at time zone 'utc' BETWEEN ce.start_time AND (ce.start_time + ce.length * '1 second'::interval)) AND (promotional_text IS NOT NULL and promotional_image IS NOT NULL) AND (COALESCE(language, '') = '' OR 'es' = ANY(regexp_split_to_array(language, ' *, *'))) ORDER BY featured_events.position ASC, random() /*application:Twitch,controller:streams,action:featured*/`,
			tables: []string{"featured_events", "events"}},
		// {query: `SELECT featured_events.* FROM "featured_events" join events ce on ce.id = event_id WHERE (now() at time zone 'utc' BETWEEN ce.start_time AND (ce.start_time + ce.length * '1 second'::interval)) AND (xarth) AND (promotional_text IS NOT NULL and promotional_image IS NOT NULL) AND (COALESCE(language, '') = '' OR 'es' = ANY(regexp_split_to_array(language, ' *, *'))) ORDER BY featured_events.position ASC, random() /*application:Twitch,controller:streams,action:featured*/`,
		// 	tables: []string{"featured_events", "events"}},
		{query: `SELECT COUNT(*) FROM "messages"  WHERE "messages"."user_id" = 7501036 AND (user_id = to_user_id) AND (safe is null or safe = true) /*application:Twitch,controller:message,action:list*/`,
			tables: []string{"messages"}},
		{query: `SELECT COUNT(count_column) FROM (SELECT  1 AS count_column FROM "channel_audits"  WHERE "channel_audits"."channel_id" = 43404079 AND "channel_audits"."action" IN ('commercial', 'cut', 'status_change', 'game_change', 'add_editor', 'remove_editor') AND (channel_audits.id < 78523808) LIMIT 10) "subquery_for_count"  /*application:Twitch,controller:dashboards,action:action_log*/`,
			tables: []string{"channel_audits"}},
		// {query: ``,
		// 	tables: []string{}},
		// {query: ``,
		// 	tables: []string{}},
		// {query: ``,
		// 	tables: []string{}},
		// {query: ``,
		// 	tables: []string{}},
	}
	for _, tt := range tests {
		stmt, err := pgparse.Parse(tt.query)
		if err != nil {
			t.Errorf("parse: %v\nquery=%q", err, tt.query)
			continue
		}
		tr := newStatementTracker()
		tr.dumpStmt(stmt)
		if err := tr.Err(); err != nil {
			t.Errorf("tr.dumpStmt(); err == %q", err)
			continue
		}
		sort.Strings(tt.tables)
		if have, want := tr.Tables(), tt.tables; !reflect.DeepEqual(have, want) {
			t.Errorf("tr.Tables(); %q != %q", have, want)
			continue
		}
	}
}

func BenchmarkTablesShort(b *testing.B) {
	for i := 0; i < b.N; i++ {
		stmt, err := pgparse.Parse(`SELECT "users".* FROM "users"  WHERE (lower(email) = 'redacted@gmail.com') /*application:Twitch,controller:follows,action:update*/`)
		if err != nil {
			b.Fatalf("parse err: %v", err)
		}
		tr := newStatementTracker()
		tr.dumpStmt(stmt)
		if err := tr.Err(); err != nil {
			b.Fatalf("dumpStmt err: %v", err)
		}
		_ = tr.Tables()
	}
}

func BenchmarkTablesLong(b *testing.B) {
	for i := 0; i < b.N; i++ {
		stmt, err := pgparse.Parse(`SELECT  "tickets".* FROM "tickets"  WHERE "tickets"."ticket_product_id" IN (SELECT "ticket_products"."id" FROM "ticket_products"  WHERE (("ticket_products"."ticket_product_owner_type" = 'User' AND "ticket_products"."ticket_product_owner_id" = 14342567 OR "ticket_products"."ticket_product_owner_type" = 'Team' AND "ticket_products"."ticket_product_owner_id" IN (535, 1073, 1155, 1116))) ORDER BY default_price, created_on) AND (NOT (("tickets"."access_end" IS NOT NULL AND "tickets"."access_end" < '2014-12-04 00:59:09.610134' OR "tickets"."access_start" IS NOT NULL AND "tickets"."access_start" > '2014-12-04 00:59:09.610147'))) ORDER BY created_on DESC LIMIT 25 OFFSET 0 /*application:Twitch,controller:subscriptions,action:index*/`)
		if err != nil {
			b.Fatalf("parse err: %v", err)
		}
		tr := newStatementTracker()
		tr.dumpStmt(stmt)
		if err := tr.Err(); err != nil {
			b.Fatalf("dumpStmt err: %v", err)
		}
		_ = tr.Tables()
	}
}
