CREATE TYPE "public"."level" AS ENUM('basic', 'beginner', 'intermediate', 'advanced', 'expert');--> statement-breakpoint CREATE TYPE "public"."plan" AS ENUM('free', 'pro');--> statement-breakpoint CREATE TYPE "public"."question_source" AS ENUM('llm_generated', 'manual');--> statement-breakpoint CREATE TYPE "public"."question_status" AS ENUM('pending', 'approved', 'rejected');--> statement-breakpoint CREATE TYPE "public"."question_type" AS ENUM('single_choice', 'multiple_select', 'true_false', 'short_text');--> statement-breakpoint CREATE TYPE "public"."report_status" AS ENUM('open', 'resolved', 'dismissed');--> statement-breakpoint CREATE TYPE "public"."self_level" AS ENUM('jun', 'mid', 'sen');--> statement-breakpoint CREATE TYPE "public"."stack" AS ENUM('html', 'css', 'js', 'ts', 'react', 'vue', 'nodejs', 'git', 'web_basics');--> statement-breakpoint CREATE TYPE "public"."subscription_status" AS ENUM('active', 'trialing', 'cancelled', 'expired');--> statement-breakpoint CREATE TYPE "public"."test_mode" AS ENUM('fixed', 'infinite', 'marathon');--> statement-breakpoint CREATE TYPE "public"."test_status" AS ENUM('in_progress', 'completed', 'abandoned');--> statement-breakpoint CREATE TYPE "public"."user_role" AS ENUM('guest', 'free', 'pro', 'admin');--> statement-breakpoint CREATE TABLE IF NOT EXISTS "users" ( "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, "email" varchar(255) NOT NULL, "password_hash" varchar(255) NOT NULL, "nickname" varchar(30) NOT NULL, "avatar_url" varchar(500), "country" varchar(100), "city" varchar(100), "self_level" "self_level", "is_public" boolean DEFAULT true NOT NULL, "role" "user_role" DEFAULT 'free' NOT NULL, "email_verified_at" timestamp with time zone, "created_at" timestamp with time zone DEFAULT now() NOT NULL, "updated_at" timestamp with time zone DEFAULT now() NOT NULL, CONSTRAINT "users_email_unique" UNIQUE("email") ); --> statement-breakpoint CREATE TABLE IF NOT EXISTS "sessions" ( "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, "user_id" uuid NOT NULL, "refresh_token_hash" varchar(255) NOT NULL, "user_agent" varchar(500), "ip_address" varchar(45), "last_active_at" timestamp with time zone DEFAULT now() NOT NULL, "expires_at" timestamp with time zone NOT NULL, "created_at" timestamp with time zone DEFAULT now() NOT NULL ); --> statement-breakpoint CREATE TABLE IF NOT EXISTS "subscriptions" ( "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, "user_id" uuid NOT NULL, "plan" "plan" NOT NULL, "status" "subscription_status" NOT NULL, "started_at" timestamp with time zone NOT NULL, "expires_at" timestamp with time zone, "cancelled_at" timestamp with time zone, "payment_provider" varchar(50), "external_id" varchar(255), CONSTRAINT "subscriptions_user_id_unique" UNIQUE("user_id") ); --> statement-breakpoint CREATE TABLE IF NOT EXISTS "tests" ( "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, "user_id" uuid NOT NULL, "stack" "stack" NOT NULL, "level" "level" NOT NULL, "question_count" integer NOT NULL, "mode" "test_mode" DEFAULT 'fixed' NOT NULL, "status" "test_status" DEFAULT 'in_progress' NOT NULL, "score" integer, "started_at" timestamp with time zone DEFAULT now() NOT NULL, "finished_at" timestamp with time zone, "time_limit_seconds" integer ); --> statement-breakpoint CREATE TABLE IF NOT EXISTS "test_questions" ( "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, "test_id" uuid NOT NULL, "question_bank_id" uuid, "order_number" integer NOT NULL, "type" "question_type" NOT NULL, "question_text" text NOT NULL, "options" jsonb, "correct_answer" jsonb NOT NULL, "explanation" text NOT NULL, "user_answer" jsonb, "is_correct" boolean, "answered_at" timestamp with time zone ); --> statement-breakpoint CREATE TABLE IF NOT EXISTS "question_bank" ( "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, "stack" "stack" NOT NULL, "level" "level" NOT NULL, "type" "question_type" NOT NULL, "question_text" text NOT NULL, "options" jsonb, "correct_answer" jsonb NOT NULL, "explanation" text NOT NULL, "status" "question_status" DEFAULT 'pending' NOT NULL, "source" "question_source" NOT NULL, "usage_count" integer DEFAULT 0 NOT NULL, "created_at" timestamp with time zone DEFAULT now() NOT NULL, "approved_at" timestamp with time zone ); --> statement-breakpoint CREATE TABLE IF NOT EXISTS "question_cache_meta" ( "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, "question_bank_id" uuid NOT NULL, "llm_model" varchar(100) NOT NULL, "prompt_hash" varchar(64) NOT NULL, "generation_time_ms" integer NOT NULL, "raw_response" jsonb, "created_at" timestamp with time zone DEFAULT now() NOT NULL ); --> statement-breakpoint CREATE TABLE IF NOT EXISTS "question_reports" ( "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, "question_bank_id" uuid NOT NULL, "user_id" uuid NOT NULL, "reason" text NOT NULL, "status" "report_status" DEFAULT 'open' NOT NULL, "created_at" timestamp with time zone DEFAULT now() NOT NULL, "resolved_at" timestamp with time zone ); --> statement-breakpoint CREATE TABLE IF NOT EXISTS "user_stats" ( "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, "user_id" uuid NOT NULL, "stack" "stack" NOT NULL, "level" "level" NOT NULL, "total_questions" integer DEFAULT 0 NOT NULL, "correct_answers" integer DEFAULT 0 NOT NULL, "tests_taken" integer DEFAULT 0 NOT NULL, "last_test_at" timestamp with time zone, CONSTRAINT "user_stats_user_id_stack_level_unique" UNIQUE("user_id","stack","level") ); --> statement-breakpoint CREATE TABLE IF NOT EXISTS "audit_logs" ( "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, "admin_id" uuid NOT NULL, "action" varchar(100) NOT NULL, "target_type" varchar(50) NOT NULL, "target_id" uuid NOT NULL, "details" jsonb, "created_at" timestamp with time zone DEFAULT now() NOT NULL ); --> statement-breakpoint CREATE TABLE IF NOT EXISTS "user_question_log" ( "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, "user_id" uuid NOT NULL, "question_bank_id" uuid NOT NULL, "seen_at" timestamp with time zone DEFAULT now() NOT NULL ); --> statement-breakpoint CREATE TABLE IF NOT EXISTS "email_verification_codes" ( "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, "user_id" uuid NOT NULL, "code" varchar(10) NOT NULL, "expires_at" timestamp with time zone NOT NULL, "created_at" timestamp with time zone DEFAULT now() NOT NULL ); --> statement-breakpoint CREATE TABLE IF NOT EXISTS "password_reset_tokens" ( "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, "user_id" uuid NOT NULL, "token_hash" varchar(255) NOT NULL, "expires_at" timestamp with time zone NOT NULL, "created_at" timestamp with time zone DEFAULT now() NOT NULL ); --> statement-breakpoint DO $$ BEGIN ALTER TABLE "sessions" ADD CONSTRAINT "sessions_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action; EXCEPTION WHEN duplicate_object THEN null; END $$; --> statement-breakpoint DO $$ BEGIN ALTER TABLE "subscriptions" ADD CONSTRAINT "subscriptions_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action; EXCEPTION WHEN duplicate_object THEN null; END $$; --> statement-breakpoint DO $$ BEGIN ALTER TABLE "tests" ADD CONSTRAINT "tests_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action; EXCEPTION WHEN duplicate_object THEN null; END $$; --> statement-breakpoint DO $$ BEGIN ALTER TABLE "test_questions" ADD CONSTRAINT "test_questions_test_id_tests_id_fk" FOREIGN KEY ("test_id") REFERENCES "public"."tests"("id") ON DELETE cascade ON UPDATE no action; EXCEPTION WHEN duplicate_object THEN null; END $$; --> statement-breakpoint DO $$ BEGIN ALTER TABLE "test_questions" ADD CONSTRAINT "test_questions_question_bank_id_question_bank_id_fk" FOREIGN KEY ("question_bank_id") REFERENCES "public"."question_bank"("id") ON DELETE set null ON UPDATE no action; EXCEPTION WHEN duplicate_object THEN null; END $$; --> statement-breakpoint DO $$ BEGIN ALTER TABLE "question_cache_meta" ADD CONSTRAINT "question_cache_meta_question_bank_id_question_bank_id_fk" FOREIGN KEY ("question_bank_id") REFERENCES "public"."question_bank"("id") ON DELETE cascade ON UPDATE no action; EXCEPTION WHEN duplicate_object THEN null; END $$; --> statement-breakpoint DO $$ BEGIN ALTER TABLE "question_reports" ADD CONSTRAINT "question_reports_question_bank_id_question_bank_id_fk" FOREIGN KEY ("question_bank_id") REFERENCES "public"."question_bank"("id") ON DELETE cascade ON UPDATE no action; EXCEPTION WHEN duplicate_object THEN null; END $$; --> statement-breakpoint DO $$ BEGIN ALTER TABLE "question_reports" ADD CONSTRAINT "question_reports_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action; EXCEPTION WHEN duplicate_object THEN null; END $$; --> statement-breakpoint DO $$ BEGIN ALTER TABLE "user_stats" ADD CONSTRAINT "user_stats_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action; EXCEPTION WHEN duplicate_object THEN null; END $$; --> statement-breakpoint DO $$ BEGIN ALTER TABLE "audit_logs" ADD CONSTRAINT "audit_logs_admin_id_users_id_fk" FOREIGN KEY ("admin_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action; EXCEPTION WHEN duplicate_object THEN null; END $$; --> statement-breakpoint DO $$ BEGIN ALTER TABLE "user_question_log" ADD CONSTRAINT "user_question_log_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action; EXCEPTION WHEN duplicate_object THEN null; END $$; --> statement-breakpoint DO $$ BEGIN ALTER TABLE "user_question_log" ADD CONSTRAINT "user_question_log_question_bank_id_question_bank_id_fk" FOREIGN KEY ("question_bank_id") REFERENCES "public"."question_bank"("id") ON DELETE cascade ON UPDATE no action; EXCEPTION WHEN duplicate_object THEN null; END $$; --> statement-breakpoint DO $$ BEGIN ALTER TABLE "email_verification_codes" ADD CONSTRAINT "email_verification_codes_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action; EXCEPTION WHEN duplicate_object THEN null; END $$; --> statement-breakpoint DO $$ BEGIN ALTER TABLE "password_reset_tokens" ADD CONSTRAINT "password_reset_tokens_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action; EXCEPTION WHEN duplicate_object THEN null; END $$;