CREATE TABLE IF NOT EXISTS "audit_log" ( "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, "operator_id" uuid, "source" text NOT NULL, "action" text NOT NULL, "target_type" text, "target_id" uuid, "payload" jsonb DEFAULT '{}'::jsonb NOT NULL, "created_at" timestamp with time zone DEFAULT now() NOT NULL ); --> statement-breakpoint CREATE TABLE IF NOT EXISTS "auth_sessions" ( "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, "operator_id" uuid NOT NULL, "token_hash" text NOT NULL, "created_at" timestamp with time zone DEFAULT now() NOT NULL, "expires_at" timestamp with time zone NOT NULL, "last_used_at" timestamp with time zone DEFAULT now() NOT NULL, "ip_address" "inet", "user_agent" text, CONSTRAINT "auth_sessions_token_hash_unique" UNIQUE("token_hash") ); --> statement-breakpoint CREATE TABLE IF NOT EXISTS "media_files" ( "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, "operator_id" uuid NOT NULL, "filename_original" text NOT NULL, "mime_type" text NOT NULL, "size_bytes" bigint NOT NULL, "sha256" text NOT NULL, "storage_path" text NOT NULL, "created_at" timestamp with time zone DEFAULT now() NOT NULL ); --> statement-breakpoint CREATE TABLE IF NOT EXISTS "operators" ( "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, "telegram_user_id" bigint NOT NULL, "display_name" text NOT NULL, "role" text DEFAULT 'admin' NOT NULL, "default_timezone" text DEFAULT 'Asia/Kuala_Lumpur' NOT NULL, "created_at" timestamp with time zone DEFAULT now() NOT NULL ); --> statement-breakpoint CREATE TABLE IF NOT EXISTS "reminder_messages" ( "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, "reminder_id" uuid NOT NULL, "position" integer NOT NULL, "kind" text NOT NULL, "text_content" text, "media_id" uuid ); --> statement-breakpoint CREATE TABLE IF NOT EXISTS "reminder_run_targets" ( "run_id" uuid NOT NULL, "group_id" uuid NOT NULL, "status" text NOT NULL, "wa_message_id" text, "error" text, "latency_ms" integer, CONSTRAINT "reminder_run_targets_run_id_group_id_pk" PRIMARY KEY("run_id","group_id") ); --> statement-breakpoint CREATE TABLE IF NOT EXISTS "reminder_runs" ( "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, "reminder_id" uuid NOT NULL, "fired_at" timestamp with time zone DEFAULT now() NOT NULL, "status" text NOT NULL, "error_summary" text ); --> statement-breakpoint CREATE TABLE IF NOT EXISTS "reminder_targets" ( "reminder_id" uuid NOT NULL, "group_id" uuid NOT NULL, "position" integer DEFAULT 0 NOT NULL, CONSTRAINT "reminder_targets_reminder_id_group_id_pk" PRIMARY KEY("reminder_id","group_id") ); --> statement-breakpoint CREATE TABLE IF NOT EXISTS "reminders" ( "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, "account_id" uuid NOT NULL, "name" text NOT NULL, "schedule_kind" text NOT NULL, "scheduled_at" timestamp with time zone, "rrule" text, "timezone" text NOT NULL, "ends_at" timestamp with time zone, "max_runs" integer, "status" text DEFAULT 'active' NOT NULL, "created_by" uuid NOT NULL, "created_at" timestamp with time zone DEFAULT now() NOT NULL, "updated_at" timestamp with time zone DEFAULT now() NOT NULL ); --> statement-breakpoint CREATE TABLE IF NOT EXISTS "whatsapp_accounts" ( "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, "operator_id" uuid NOT NULL, "label" text NOT NULL, "phone_number" text, "status" text DEFAULT 'pending' NOT NULL, "last_connected_at" timestamp with time zone, "last_qr_at" timestamp with time zone, "created_at" timestamp with time zone DEFAULT now() NOT NULL ); --> statement-breakpoint CREATE TABLE IF NOT EXISTS "whatsapp_groups" ( "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, "account_id" uuid NOT NULL, "wa_group_jid" text NOT NULL, "name" text NOT NULL, "participant_count" integer DEFAULT 0 NOT NULL, "is_archived" boolean DEFAULT false NOT NULL, "last_synced_at" timestamp with time zone DEFAULT now() NOT NULL ); --> statement-breakpoint DO $$ BEGIN ALTER TABLE "audit_log" ADD CONSTRAINT "audit_log_operator_id_operators_id_fk" FOREIGN KEY ("operator_id") REFERENCES "public"."operators"("id") ON DELETE no action ON UPDATE no action; EXCEPTION WHEN duplicate_object THEN null; END $$; --> statement-breakpoint DO $$ BEGIN ALTER TABLE "auth_sessions" ADD CONSTRAINT "auth_sessions_operator_id_operators_id_fk" FOREIGN KEY ("operator_id") REFERENCES "public"."operators"("id") ON DELETE no action ON UPDATE no action; EXCEPTION WHEN duplicate_object THEN null; END $$; --> statement-breakpoint DO $$ BEGIN ALTER TABLE "media_files" ADD CONSTRAINT "media_files_operator_id_operators_id_fk" FOREIGN KEY ("operator_id") REFERENCES "public"."operators"("id") ON DELETE no action ON UPDATE no action; EXCEPTION WHEN duplicate_object THEN null; END $$; --> statement-breakpoint DO $$ BEGIN ALTER TABLE "reminder_messages" ADD CONSTRAINT "reminder_messages_reminder_id_reminders_id_fk" FOREIGN KEY ("reminder_id") REFERENCES "public"."reminders"("id") ON DELETE cascade ON UPDATE no action; EXCEPTION WHEN duplicate_object THEN null; END $$; --> statement-breakpoint DO $$ BEGIN ALTER TABLE "reminder_messages" ADD CONSTRAINT "reminder_messages_media_id_media_files_id_fk" FOREIGN KEY ("media_id") REFERENCES "public"."media_files"("id") ON DELETE no action ON UPDATE no action; EXCEPTION WHEN duplicate_object THEN null; END $$; --> statement-breakpoint DO $$ BEGIN ALTER TABLE "reminder_run_targets" ADD CONSTRAINT "reminder_run_targets_run_id_reminder_runs_id_fk" FOREIGN KEY ("run_id") REFERENCES "public"."reminder_runs"("id") ON DELETE cascade ON UPDATE no action; EXCEPTION WHEN duplicate_object THEN null; END $$; --> statement-breakpoint DO $$ BEGIN ALTER TABLE "reminder_run_targets" ADD CONSTRAINT "reminder_run_targets_group_id_whatsapp_groups_id_fk" FOREIGN KEY ("group_id") REFERENCES "public"."whatsapp_groups"("id") ON DELETE no action ON UPDATE no action; EXCEPTION WHEN duplicate_object THEN null; END $$; --> statement-breakpoint DO $$ BEGIN ALTER TABLE "reminder_runs" ADD CONSTRAINT "reminder_runs_reminder_id_reminders_id_fk" FOREIGN KEY ("reminder_id") REFERENCES "public"."reminders"("id") ON DELETE no action ON UPDATE no action; EXCEPTION WHEN duplicate_object THEN null; END $$; --> statement-breakpoint DO $$ BEGIN ALTER TABLE "reminder_targets" ADD CONSTRAINT "reminder_targets_reminder_id_reminders_id_fk" FOREIGN KEY ("reminder_id") REFERENCES "public"."reminders"("id") ON DELETE cascade ON UPDATE no action; EXCEPTION WHEN duplicate_object THEN null; END $$; --> statement-breakpoint DO $$ BEGIN ALTER TABLE "reminder_targets" ADD CONSTRAINT "reminder_targets_group_id_whatsapp_groups_id_fk" FOREIGN KEY ("group_id") REFERENCES "public"."whatsapp_groups"("id") ON DELETE no action ON UPDATE no action; EXCEPTION WHEN duplicate_object THEN null; END $$; --> statement-breakpoint DO $$ BEGIN ALTER TABLE "reminders" ADD CONSTRAINT "reminders_account_id_whatsapp_accounts_id_fk" FOREIGN KEY ("account_id") REFERENCES "public"."whatsapp_accounts"("id") ON DELETE no action ON UPDATE no action; EXCEPTION WHEN duplicate_object THEN null; END $$; --> statement-breakpoint DO $$ BEGIN ALTER TABLE "reminders" ADD CONSTRAINT "reminders_created_by_operators_id_fk" FOREIGN KEY ("created_by") REFERENCES "public"."operators"("id") ON DELETE no action ON UPDATE no action; EXCEPTION WHEN duplicate_object THEN null; END $$; --> statement-breakpoint DO $$ BEGIN ALTER TABLE "whatsapp_accounts" ADD CONSTRAINT "whatsapp_accounts_operator_id_operators_id_fk" FOREIGN KEY ("operator_id") REFERENCES "public"."operators"("id") ON DELETE no action ON UPDATE no action; EXCEPTION WHEN duplicate_object THEN null; END $$; --> statement-breakpoint DO $$ BEGIN ALTER TABLE "whatsapp_groups" ADD CONSTRAINT "whatsapp_groups_account_id_whatsapp_accounts_id_fk" FOREIGN KEY ("account_id") REFERENCES "public"."whatsapp_accounts"("id") ON DELETE no action ON UPDATE no action; EXCEPTION WHEN duplicate_object THEN null; END $$; --> statement-breakpoint CREATE UNIQUE INDEX IF NOT EXISTS "operators_telegram_user_id_uq" ON "operators" USING btree ("telegram_user_id");--> statement-breakpoint CREATE UNIQUE INDEX IF NOT EXISTS "whatsapp_accounts_operator_label_uq" ON "whatsapp_accounts" USING btree ("operator_id","label");--> statement-breakpoint CREATE UNIQUE INDEX IF NOT EXISTS "whatsapp_groups_account_jid_uq" ON "whatsapp_groups" USING btree ("account_id","wa_group_jid");