CREATE TABLE `calendar_events` (
	`id` int AUTO_INCREMENT NOT NULL,
	`calendar_id` int NOT NULL,
	`uid` varchar(512) NOT NULL,
	`etag` varchar(256),
	`object_url` varchar(1024),
	`raw_vevent` text NOT NULL,
	`title` varchar(500),
	`dtstart_utc` timestamp,
	`dtstart_date` date,
	`all_day` boolean NOT NULL DEFAULT false,
	`has_rrule` boolean NOT NULL DEFAULT false,
	`updated_at` timestamp DEFAULT (now()) ON UPDATE CURRENT_TIMESTAMP,
	CONSTRAINT `calendar_events_id` PRIMARY KEY(`id`),
	CONSTRAINT `uniq_calendar_uid` UNIQUE(`calendar_id`,`uid`)
);
--> statement-breakpoint
CREATE TABLE `calendar_outbox` (
	`id` int AUTO_INCREMENT NOT NULL,
	`user_id` int NOT NULL,
	`operation` enum('create','update','delete') NOT NULL,
	`status` enum('pending','done','failed','dead') NOT NULL DEFAULT 'pending',
	`uid` varchar(512) NOT NULL,
	`calendar_url` varchar(1024) NOT NULL,
	`calendar_object_url` varchar(1024),
	`etag` varchar(256),
	`payload` text,
	`attempt_count` int NOT NULL DEFAULT 0,
	`next_attempt_at` timestamp NOT NULL DEFAULT (now()),
	`last_error` text,
	`group_id` varchar(64),
	`created_at` timestamp NOT NULL DEFAULT (now()),
	`updated_at` timestamp DEFAULT (now()) ON UPDATE CURRENT_TIMESTAMP,
	CONSTRAINT `calendar_outbox_id` PRIMARY KEY(`id`)
);
--> statement-breakpoint
CREATE TABLE `calendars` (
	`id` int AUTO_INCREMENT NOT NULL,
	`user_id` int NOT NULL,
	`url` varchar(1024) NOT NULL,
	`display_name` varchar(256),
	`color` varchar(7),
	`ctag` varchar(512),
	`sync_token` varchar(1024),
	`last_synced_at` timestamp,
	`is_shared` boolean NOT NULL DEFAULT false,
	CONSTRAINT `calendars_id` PRIMARY KEY(`id`),
	-- NOTE (IN-01): UNIQUE(user_id, url) with url varchar(1024)/utf8mb4 is ~4100 bytes,
	-- over InnoDB's 3072-byte index-key limit. Succeeds only because MariaDB 11 silently
	-- builds over-length UNIQUE constraints as long-unique HASH indexes; this same DDL
	-- fails on MySQL 8 or with stricter SQL modes. Engine-pinned to MariaDB (project hard
	-- constraint). Already applied on main/production — do not alter.
	CONSTRAINT `uniq_calendar_user_url` UNIQUE(`user_id`,`url`)
);
--> statement-breakpoint
CREATE TABLE `list_items` (
	`id` int AUTO_INCREMENT NOT NULL,
	`list_id` int NOT NULL,
	`text` varchar(500) NOT NULL,
	`checked` boolean NOT NULL DEFAULT false,
	`rank` varchar(255) COLLATE utf8mb4_bin NOT NULL,
	`created_at` timestamp NOT NULL DEFAULT (now()),
	`updated_at` timestamp DEFAULT (now()) ON UPDATE CURRENT_TIMESTAMP,
	CONSTRAINT `list_items_id` PRIMARY KEY(`id`)
);
--> statement-breakpoint
CREATE TABLE `list_shares` (
	`id` int AUTO_INCREMENT NOT NULL,
	`list_id` int NOT NULL,
	`user_id` int NOT NULL,
	`created_at` timestamp NOT NULL DEFAULT (now()),
	CONSTRAINT `list_shares_id` PRIMARY KEY(`id`),
	CONSTRAINT `uniq_list_share` UNIQUE(`list_id`,`user_id`)
);
--> statement-breakpoint
CREATE TABLE `lists` (
	`id` int AUTO_INCREMENT NOT NULL,
	`owner_id` int NOT NULL,
	`name` varchar(255) NOT NULL,
	`is_shared` boolean NOT NULL DEFAULT true,
	`created_at` timestamp NOT NULL DEFAULT (now()),
	`updated_at` timestamp DEFAULT (now()) ON UPDATE CURRENT_TIMESTAMP,
	CONSTRAINT `lists_id` PRIMARY KEY(`id`)
);
--> statement-breakpoint
CREATE TABLE `member_credentials` (
	`id` int AUTO_INCREMENT NOT NULL,
	`user_id` int NOT NULL,
	`encrypted_password` text NOT NULL,
	`fastmail_email` varchar(256) NOT NULL,
	`created_at` timestamp NOT NULL DEFAULT (now()),
	`updated_at` timestamp DEFAULT (now()) ON UPDATE CURRENT_TIMESTAMP,
	CONSTRAINT `member_credentials_id` PRIMARY KEY(`id`)
);
--> statement-breakpoint
CREATE TABLE `push_subscriptions` (
	`id` int AUTO_INCREMENT NOT NULL,
	`user_id` int NOT NULL,
	`endpoint` varchar(2048) NOT NULL,
	`p256dh` varchar(512) NOT NULL,
	`auth` varchar(256) NOT NULL,
	`created_at` timestamp NOT NULL DEFAULT (now()),
	`updated_at` timestamp DEFAULT (now()) ON UPDATE CURRENT_TIMESTAMP,
	CONSTRAINT `push_subscriptions_id` PRIMARY KEY(`id`),
	-- NOTE (IN-01): UNIQUE(endpoint) with endpoint varchar(2048)/utf8mb4 is ~8192 bytes,
	-- over InnoDB's 3072-byte index-key limit. Succeeds only because MariaDB 11 silently
	-- builds over-length UNIQUE constraints as long-unique HASH indexes; this same DDL
	-- fails on MySQL 8 or with stricter SQL modes. Engine-pinned to MariaDB (project hard
	-- constraint). Already applied on main/production — do not alter.
	CONSTRAINT `uniq_push_endpoint` UNIQUE(`endpoint`)
);
--> statement-breakpoint
CREATE TABLE `users` (
	`id` int AUTO_INCREMENT NOT NULL,
	`oidc_iss` varchar(512) NOT NULL,
	`oidc_sub` varchar(256) NOT NULL,
	`display_name` varchar(256),
	`color` varchar(7) NOT NULL,
	`created_at` timestamp NOT NULL DEFAULT (now()),
	CONSTRAINT `users_id` PRIMARY KEY(`id`),
	CONSTRAINT `uniq_oidc_identity` UNIQUE(`oidc_iss`,`oidc_sub`)
);
--> statement-breakpoint
ALTER TABLE `calendar_events` ADD CONSTRAINT `calendar_events_calendar_id_calendars_id_fk` FOREIGN KEY (`calendar_id`) REFERENCES `calendars`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `calendar_outbox` ADD CONSTRAINT `calendar_outbox_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `calendars` ADD CONSTRAINT `calendars_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `list_items` ADD CONSTRAINT `list_items_list_id_lists_id_fk` FOREIGN KEY (`list_id`) REFERENCES `lists`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `list_shares` ADD CONSTRAINT `list_shares_list_id_lists_id_fk` FOREIGN KEY (`list_id`) REFERENCES `lists`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `list_shares` ADD CONSTRAINT `list_shares_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `lists` ADD CONSTRAINT `lists_owner_id_users_id_fk` FOREIGN KEY (`owner_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `member_credentials` ADD CONSTRAINT `member_credentials_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `push_subscriptions` ADD CONSTRAINT `push_subscriptions_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
CREATE INDEX `idx_calendar_events_dtstart_utc` ON `calendar_events` (`dtstart_utc`);--> statement-breakpoint
CREATE INDEX `idx_calendar_events_dtstart_date` ON `calendar_events` (`dtstart_date`);--> statement-breakpoint
CREATE INDEX `idx_calendar_events_has_rrule` ON `calendar_events` (`has_rrule`);--> statement-breakpoint
CREATE INDEX `idx_outbox_user_status` ON `calendar_outbox` (`user_id`,`status`);--> statement-breakpoint
CREATE INDEX `idx_outbox_next_attempt` ON `calendar_outbox` (`next_attempt_at`,`status`);--> statement-breakpoint
CREATE INDEX `idx_outbox_uid` ON `calendar_outbox` (`uid`);--> statement-breakpoint
CREATE INDEX `idx_calendars_user_id` ON `calendars` (`user_id`);--> statement-breakpoint
CREATE INDEX `idx_list_items_list_id_rank` ON `list_items` (`list_id`,`rank`);--> statement-breakpoint
CREATE INDEX `idx_list_items_list_id_checked` ON `list_items` (`list_id`,`checked`);--> statement-breakpoint
CREATE INDEX `idx_list_shares_user_id` ON `list_shares` (`user_id`);--> statement-breakpoint
CREATE INDEX `idx_lists_owner_id` ON `lists` (`owner_id`);--> statement-breakpoint
CREATE INDEX `idx_member_credentials_user_id` ON `member_credentials` (`user_id`);--> statement-breakpoint
CREATE INDEX `idx_push_subscriptions_user_id` ON `push_subscriptions` (`user_id`);