import { relations, sql } from "drizzle-orm";
import {
  index,
  integer,
  jsonb,
  pgEnum,
  pgTable,
  text,
  timestamp,
  uniqueIndex,
} from "drizzle-orm/pg-core";

export const serverStatusEnum = pgEnum("server_status", ["active", "maintenance", "inactive"]);

export const serviceTypeEnum = pgEnum("service_type", [
  "web_app",
  "mail",
  "database",
  "api",
  "proxy",
  "other",
]);

export const serviceProtocolEnum = pgEnum("service_protocol", [
  "http",
  "https",
  "tcp",
  "udp",
  "other",
]);

export const serviceStatusEnum = pgEnum("service_status", ["active", "down", "maintenance"]);

export const domainResolutionStatusEnum = pgEnum("domain_resolution_status", [
  "MATCH",
  "MISMATCH",
  "UNRESOLVED",
]);

export const server = pgTable(
  "server",
  {
    id: text("id").primaryKey(),
    name: text("name").notNull(),
    primaryIpAddress: text("primary_ip_address").notNull(),
    secondaryIpAddress: text("secondary_ip_address"),
    operatingSystem: text("operating_system"),
    location: text("location"),
    provider: text("provider"),
    description: text("description"),
    status: serverStatusEnum("status").default("active").notNull(),
    createdAt: timestamp("created_at").defaultNow().notNull(),
    updatedAt: timestamp("updated_at")
      .defaultNow()
      .$onUpdate(() => /* @__PURE__ */ new Date())
      .notNull(),
  },
  (table) => [
    uniqueIndex("server_name_unique").on(table.name),
    index("server_status_idx").on(table.status),
  ],
);

export const service = pgTable(
  "service",
  {
    id: text("id").primaryKey(),
    serverId: text("server_id")
      .notNull()
      .references(() => server.id, { onDelete: "cascade" }),
    name: text("name").notNull(),
    type: serviceTypeEnum("type").default("other").notNull(),
    internalPort: integer("internal_port"),
    externalPort: integer("external_port"),
    protocol: serviceProtocolEnum("protocol").default("http").notNull(),
    status: serviceStatusEnum("status").default("active").notNull(),
    description: text("description"),
    createdAt: timestamp("created_at").defaultNow().notNull(),
    updatedAt: timestamp("updated_at")
      .defaultNow()
      .$onUpdate(() => /* @__PURE__ */ new Date())
      .notNull(),
  },
  (table) => [
    index("service_server_id_idx").on(table.serverId),
    index("service_status_idx").on(table.status),
    uniqueIndex("service_server_name_unique").on(table.serverId, table.name),
  ],
);

export const domain = pgTable(
  "domain",
  {
    id: text("id").primaryKey(),
    serviceId: text("service_id")
      .notNull()
      .references(() => service.id, { onDelete: "cascade" }),
    name: text("name").notNull(),
    expectedServerIp: text("expected_server_ip").notNull(),
    lastResolvedIp: text("last_resolved_ip"),
    lastResolvedIps: jsonb("last_resolved_ips")
      .$type<string[]>()
      .default(sql`'[]'::jsonb`)
      .notNull(),
    resolutionStatus: domainResolutionStatusEnum("resolution_status")
      .default("UNRESOLVED")
      .notNull(),
    lastCheckedAt: timestamp("last_checked_at"),
    remarks: text("remarks"),
    lastCheckMessage: text("last_check_message"),
    createdAt: timestamp("created_at").defaultNow().notNull(),
    updatedAt: timestamp("updated_at")
      .defaultNow()
      .$onUpdate(() => /* @__PURE__ */ new Date())
      .notNull(),
  },
  (table) => [
    uniqueIndex("domain_name_unique").on(table.name),
    index("domain_service_id_idx").on(table.serviceId),
    index("domain_resolution_status_idx").on(table.resolutionStatus),
  ],
);

export const note = pgTable(
  "note",
  {
    id: text("id").primaryKey(),
    serverId: text("server_id")
      .notNull()
      .references(() => server.id, { onDelete: "cascade" }),
    title: text("title").notNull(),
    content: text("content").notNull(),
    category: text("category"),
    createdAt: timestamp("created_at").defaultNow().notNull(),
    updatedAt: timestamp("updated_at")
      .defaultNow()
      .$onUpdate(() => /* @__PURE__ */ new Date())
      .notNull(),
  },
  (table) => [index("note_server_id_idx").on(table.serverId), index("note_category_idx").on(table.category)],
);

export const serverRelations = relations(server, ({ many }) => ({
  services: many(service),
  notes: many(note),
}));

export const serviceRelations = relations(service, ({ one, many }) => ({
  server: one(server, {
    fields: [service.serverId],
    references: [server.id],
  }),
  domains: many(domain),
}));

export const domainRelations = relations(domain, ({ one }) => ({
  service: one(service, {
    fields: [domain.serviceId],
    references: [service.id],
  }),
}));

export const noteRelations = relations(note, ({ one }) => ({
  server: one(server, {
    fields: [note.serverId],
    references: [server.id],
  }),
}));
