import { pgTable, timestamp, uuid, varchar, text, boolean, integer, jsonb, unique } from 'drizzle-orm/pg-core';

export const users = pgTable('users', {
  id: uuid('id').defaultRandom().primaryKey(),
  email: varchar('email', { length: 255 }).notNull().unique(),
  name: varchar('name', { length: 255 }).notNull(),
  passwordHash: varchar('password_hash', { length: 255 }),
  emailVerified: boolean('email_verified').default(false).notNull(),
  image: text('image'),
  createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
  updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
});

export const devices = pgTable('devices', {
  id: uuid('id').defaultRandom().primaryKey(),
  userId: uuid('user_id').notNull().references(() => users.id),
  name: varchar('name', { length: 255 }),
  role: varchar('role', { length: 32 }).default('client').notNull(),
  platform: varchar('platform', { length: 32 }),
  appVersion: varchar('app_version', { length: 64 }),
  pushToken: text('push_token'),
  status: varchar('status', { length: 32 }).default('offline').notNull(),
  isCamera: boolean('is_camera').default(false).notNull(),
  lastSeenAt: timestamp('last_seen_at', { withTimezone: true }),
  updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
  createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
});

export const deviceLinks = pgTable(
  'device_links',
  {
    id: uuid('id').defaultRandom().primaryKey(),
    ownerUserId: uuid('owner_user_id').notNull().references(() => users.id),
    cameraDeviceId: uuid('camera_device_id').notNull().references(() => devices.id),
    clientDeviceId: uuid('client_device_id').notNull().references(() => devices.id),
    status: varchar('status', { length: 32 }).default('active').notNull(),
    createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
    updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
  },
  (table) => ({
    uniqueDevicePair: unique('device_links_camera_client_unique').on(table.cameraDeviceId, table.clientDeviceId),
  }),
);

export const commands = pgTable('commands', {
  id: uuid('id').defaultRandom().primaryKey(),
  ownerUserId: uuid('owner_user_id').notNull().references(() => users.id),
  sourceDeviceId: uuid('source_device_id').notNull().references(() => devices.id),
  targetDeviceId: uuid('target_device_id').notNull().references(() => devices.id),
  commandType: varchar('command_type', { length: 64 }).notNull(),
  payload: jsonb('payload').$type<Record<string, unknown> | null>().default(null),
  status: varchar('status', { length: 32 }).default('queued').notNull(),
  retryCount: integer('retry_count').default(0).notNull(),
  lastDispatchedAt: timestamp('last_dispatched_at', { withTimezone: true }),
  acknowledgedAt: timestamp('acknowledged_at', { withTimezone: true }),
  error: text('error'),
  createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
  updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
});

export const streamSessions = pgTable('stream_sessions', {
  id: uuid('id').defaultRandom().primaryKey(),
  ownerUserId: uuid('owner_user_id').notNull().references(() => users.id),
  cameraDeviceId: uuid('camera_device_id').notNull().references(() => devices.id),
  requesterDeviceId: uuid('requester_device_id').notNull().references(() => devices.id),
  status: varchar('status', { length: 32 }).default('requested').notNull(),
  reason: varchar('reason', { length: 32 }).default('on_demand').notNull(),
  mediaProvider: varchar('media_provider', { length: 32 }).default('mock').notNull(),
  mediaSessionId: varchar('media_session_id', { length: 255 }),
  publishEndpoint: text('publish_endpoint'),
  subscribeEndpoint: text('subscribe_endpoint'),
  streamKey: varchar('stream_key', { length: 255 }),
  startedAt: timestamp('started_at', { withTimezone: true }),
  endedAt: timestamp('ended_at', { withTimezone: true }),
  metadata: jsonb('metadata').$type<Record<string, unknown> | null>().default(null),
  createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
  updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
});

export const recordings = pgTable('recordings', {
  id: uuid('id').defaultRandom().primaryKey(),
  ownerUserId: uuid('owner_user_id').notNull().references(() => users.id),
  streamSessionId: uuid('stream_session_id').references(() => streamSessions.id),
  cameraDeviceId: uuid('camera_device_id').notNull().references(() => devices.id),
  requesterDeviceId: uuid('requester_device_id').references(() => devices.id),
  eventId: uuid('event_id').references(() => events.id),
  objectKey: varchar('object_key', { length: 1024 }),
  bucket: varchar('bucket', { length: 255 }),
  durationSeconds: integer('duration_seconds'),
  sizeBytes: integer('size_bytes'),
  status: varchar('status', { length: 32 }).default('awaiting_upload').notNull(),
  availableAt: timestamp('available_at', { withTimezone: true }),
  error: text('error'),
  createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
  updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
});

export const events = pgTable('events', {
  id: uuid('id').defaultRandom().primaryKey(),
  userId: uuid('user_id').notNull().references(() => users.id),
  deviceId: uuid('device_id').references(() => devices.id),
  title: varchar('title', { length: 255 }),
  triggeredBy: varchar('triggered_by', { length: 64 }).default('motion'),
  status: varchar('status', { length: 32 }).default('recording').notNull(),
  startedAt: timestamp('started_at', { withTimezone: true }).notNull(),
  endedAt: timestamp('ended_at', { withTimezone: true }),
  notifiedAt: timestamp('notified_at', { withTimezone: true }),
  videoUrl: varchar('video_url', { length: 1024 }).unique(),
  createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
  updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
});

export const notifications = pgTable('notifications', {
  id: uuid('id').defaultRandom().primaryKey(),
  eventId: uuid('event_id').references(() => events.id).notNull(),
  userId: uuid('user_id').references(() => users.id).notNull(),
  sentAt: timestamp('sent_at', { withTimezone: true }).defaultNow().notNull(),
  channel: varchar('channel', { length: 32 }).notNull(),
  status: varchar('status', { length: 32 }).default('queued').notNull(),
  isRead: boolean('is_read').default(false).notNull(),
});

export const notificationDeliveries = pgTable('notification_deliveries', {
  id: uuid('id').defaultRandom().primaryKey(),
  ownerUserId: uuid('owner_user_id').notNull().references(() => users.id),
  recipientDeviceId: uuid('recipient_device_id').notNull().references(() => devices.id),
  type: varchar('type', { length: 64 }).notNull(),
  payload: jsonb('payload').$type<Record<string, unknown> | null>().default(null),
  status: varchar('status', { length: 32 }).default('queued').notNull(),
  attempts: integer('attempts').default(0).notNull(),
  lastError: text('last_error'),
  sentAt: timestamp('sent_at', { withTimezone: true }),
  nextAttemptAt: timestamp('next_attempt_at', { withTimezone: true }).defaultNow().notNull(),
  createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
  updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
});

export const auditLogs = pgTable('audit_logs', {
  id: uuid('id').defaultRandom().primaryKey(),
  ownerUserId: uuid('owner_user_id').notNull().references(() => users.id),
  actorDeviceId: uuid('actor_device_id').references(() => devices.id),
  action: varchar('action', { length: 128 }).notNull(),
  targetType: varchar('target_type', { length: 64 }).notNull(),
  targetId: varchar('target_id', { length: 255 }).notNull(),
  metadata: jsonb('metadata').$type<Record<string, unknown> | null>().default(null),
  ipAddress: text('ip_address'),
  createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
});

export const accounts = pgTable('account', {
  id: uuid('id').defaultRandom().primaryKey(),
  userId: uuid('user_id').notNull().references(() => users.id),
  accountId: text('account_id').notNull(),
  providerId: text('provider_id').notNull(),
  accessToken: text('access_token'),
  refreshToken: text('refresh_token'),
  accessTokenExpiresAt: timestamp('access_token_expires_at', { withTimezone: true }),
  refreshTokenExpiresAt: timestamp('refresh_token_expires_at', { withTimezone: true }),
  idToken: text('id_token'),
  scope: text('scope'),
  password: text('password'),
  createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
  updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
});

export const sessions = pgTable('session', {
  id: uuid('id').defaultRandom().primaryKey(),
  userId: uuid('user_id').notNull().references(() => users.id),
  token: text('token').notNull().unique(),
  expiresAt: timestamp('expires_at', { withTimezone: true }).notNull(),
  ipAddress: text('ip_address'),
  userAgent: text('user_agent'),
  createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
  updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
});

export const verifications = pgTable('verification', {
  id: uuid('id').defaultRandom().primaryKey(),
  identifier: text('identifier').notNull(),
  value: text('value').notNull(),
  expiresAt: timestamp('expires_at', { withTimezone: true }).notNull(),
  createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
  updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
});

export const schema = {
  users,
  devices,
  deviceLinks,
  commands,
  streamSessions,
  recordings,
  events,
  notifications,
  notificationDeliveries,
  auditLogs,
  accounts,
  sessions,
  verifications,
};
