import { pgTable, timestamp, varchar, boolean, serial, integer, text } from 'drizzle-orm/pg-core';
import { relations, eq, and, gt, lt } from 'drizzle-orm';
import { randomBytes } from 'crypto';
import bcrypt from 'bcryptjs';

// src/auth/legacy/schema/index.ts
var legacyUsers = pgTable("users", {
  id: serial("id").primaryKey(),
  phone: varchar("phone", { length: 20 }).notNull().unique(),
  password: varchar("password", { length: 255 }).notNull(),
  name: varchar("name", { length: 100 }),
  email: varchar("email", { length: 255 }),
  isActive: boolean("is_active").notNull().default(true),
  role: varchar("role", { length: 20 }).notNull().default("user"),
  lastLoginAt: timestamp("last_login_at"),
  createdAt: timestamp("created_at").defaultNow().notNull(),
  updatedAt: timestamp("updated_at").defaultNow().notNull()
});
var legacyUserSessions = pgTable("user_sessions", {
  id: serial("id").primaryKey(),
  userId: integer("user_id").notNull().references(() => legacyUsers.id, { onDelete: "cascade" }),
  sessionToken: varchar("session_token", { length: 255 }).notNull().unique(),
  expiresAt: timestamp("expires_at").notNull(),
  createdAt: timestamp("created_at").defaultNow().notNull()
});
var legacyVerificationCodes = pgTable("verification_codes", {
  id: serial("id").primaryKey(),
  phone: text("phone").notNull(),
  code: text("code").notNull(),
  expiresAt: timestamp("expires_at").notNull(),
  createdAt: timestamp("created_at").defaultNow().notNull(),
  used: boolean("used").default(false).notNull()
});
var legacyUsersRelations = relations(legacyUsers, ({ many }) => ({
  sessions: many(legacyUserSessions)
}));
var legacyUserSessionsRelations = relations(legacyUserSessions, ({ one }) => ({
  user: one(legacyUsers, {
    fields: [legacyUserSessions.userId],
    references: [legacyUsers.id]
  })
}));
var LegacyAuthDbService = class {
  constructor(config) {
    this.db = config.db;
    this.tables = {
      users: config.tables?.users ?? legacyUsers,
      userSessions: config.tables?.userSessions ?? legacyUserSessions,
      verificationCodes: config.tables?.verificationCodes ?? legacyVerificationCodes
    };
    this.saltRounds = config.saltRounds || 12;
    this.sessionDurationMs = config.sessionDurationMs || 30 * 24 * 60 * 60 * 1e3;
  }
  async verifyPassword(phone, password) {
    try {
      const result = await this.db.select().from(this.tables.users).where(eq(this.tables.users.phone, phone)).limit(1);
      const user = result[0];
      if (!user) return null;
      if (!user.isActive) return null;
      const isValid = await bcrypt.compare(password, user.password);
      if (!isValid) return null;
      const { password: _, ...userWithoutPassword } = user;
      return userWithoutPassword;
    } catch (error) {
      console.error("\u{1F4A5} [LegacyAuthDbService] \u5BC6\u7801\u9A8C\u8BC1\u5F02\u5E38:", error);
      return null;
    }
  }
  async createUser(phone, password, name) {
    try {
      const existingUser = await this.db.select().from(this.tables.users).where(eq(this.tables.users.phone, phone)).limit(1);
      if (existingUser.length > 0) {
        throw new Error("\u7528\u6237\u5DF2\u5B58\u5728");
      }
      const hashedPassword = await bcrypt.hash(password, this.saltRounds);
      const result = await this.db.insert(this.tables.users).values({
        phone,
        password: hashedPassword,
        name: name || null,
        isActive: true,
        role: "user"
      }).returning();
      const createdUser = result[0];
      if (!createdUser) {
        throw new Error("\u521B\u5EFA\u7528\u6237\u5931\u8D25: \u672A\u8FD4\u56DE\u7528\u6237\u8BB0\u5F55");
      }
      const { password: _, ...userWithoutPassword } = createdUser;
      return userWithoutPassword;
    } catch (error) {
      console.error("\u521B\u5EFA\u7528\u6237\u5931\u8D25:", error);
      throw new Error("\u521B\u5EFA\u7528\u6237\u5931\u8D25");
    }
  }
  async updateLastLogin(userId) {
    try {
      await this.db.update(this.tables.users).set({ lastLoginAt: /* @__PURE__ */ new Date(), updatedAt: /* @__PURE__ */ new Date() }).where(eq(this.tables.users.id, userId));
    } catch (error) {
      console.error("\u66F4\u65B0\u6700\u540E\u767B\u5F55\u65F6\u95F4\u5931\u8D25:", error);
      throw new Error("\u66F4\u65B0\u6700\u540E\u767B\u5F55\u65F6\u95F4\u5931\u8D25");
    }
  }
  async createSession(userId) {
    try {
      const sessionToken = randomBytes(32).toString("hex");
      const expiresAt = new Date(Date.now() + this.sessionDurationMs);
      const result = await this.db.insert(this.tables.userSessions).values({
        userId,
        sessionToken,
        expiresAt
      }).returning();
      const session = result[0];
      if (!session) {
        throw new Error("\u521B\u5EFA\u4F1A\u8BDD\u5931\u8D25: \u672A\u8FD4\u56DE\u4F1A\u8BDD\u8BB0\u5F55");
      }
      return session;
    } catch (error) {
      console.error("\u521B\u5EFA\u4F1A\u8BDD\u5931\u8D25:", error);
      throw new Error("\u521B\u5EFA\u4F1A\u8BDD\u5931\u8D25");
    }
  }
  async validateSession(sessionToken) {
    try {
      const now = /* @__PURE__ */ new Date();
      const result = await this.db.select({
        session: this.tables.userSessions,
        user: this.tables.users
      }).from(this.tables.userSessions).innerJoin(this.tables.users, eq(this.tables.userSessions.userId, this.tables.users.id)).where(
        and(
          eq(this.tables.userSessions.sessionToken, sessionToken),
          gt(this.tables.userSessions.expiresAt, now),
          eq(this.tables.users.isActive, true)
        )
      ).limit(1);
      const row = result[0];
      if (!row) {
        return { valid: false };
      }
      const { password: _, ...userWithoutPassword } = row.user;
      return { valid: true, user: userWithoutPassword };
    } catch (error) {
      console.error("\u4F1A\u8BDD\u9A8C\u8BC1\u5931\u8D25:", error);
      return { valid: false };
    }
  }
  async deleteSession(sessionToken) {
    try {
      await this.db.delete(this.tables.userSessions).where(eq(this.tables.userSessions.sessionToken, sessionToken));
    } catch (error) {
      console.error("\u5220\u9664\u4F1A\u8BDD\u5931\u8D25:", error);
      throw new Error("\u5220\u9664\u4F1A\u8BDD\u5931\u8D25");
    }
  }
  async deleteUserSessions(userId) {
    try {
      await this.db.delete(this.tables.userSessions).where(eq(this.tables.userSessions.userId, userId));
    } catch (error) {
      console.error("\u5220\u9664\u7528\u6237\u4F1A\u8BDD\u5931\u8D25:", error);
      throw new Error("\u5220\u9664\u7528\u6237\u4F1A\u8BDD\u5931\u8D25");
    }
  }
  async cleanupExpiredSessions() {
    try {
      const now = /* @__PURE__ */ new Date();
      await this.db.delete(this.tables.userSessions).where(lt(this.tables.userSessions.expiresAt, now));
    } catch (error) {
      console.error("\u6E05\u7406\u8FC7\u671F\u4F1A\u8BDD\u5931\u8D25:", error);
    }
  }
  async getUserByPhone(phone) {
    try {
      const result = await this.db.select().from(this.tables.users).where(eq(this.tables.users.phone, phone)).limit(1);
      const user = result[0];
      if (!user) return null;
      const { password: _, ...userWithoutPassword } = user;
      return userWithoutPassword;
    } catch (error) {
      console.error("\u67E5\u8BE2\u7528\u6237\u5931\u8D25:", error);
      throw error;
    }
  }
  async sendVerificationCode(phone) {
    try {
      await this.cleanupExpiredVerificationCodes();
      const existingCode = await this.db.select().from(this.tables.verificationCodes).where(
        and(
          eq(this.tables.verificationCodes.phone, phone),
          eq(this.tables.verificationCodes.used, false),
          gt(this.tables.verificationCodes.expiresAt, /* @__PURE__ */ new Date())
        )
      ).limit(1);
      const currentCode = existingCode[0];
      if (currentCode) {
        const timeDiff = Date.now() - currentCode.createdAt.getTime();
        if (timeDiff < 60 * 1e3) {
          throw new Error("\u9A8C\u8BC1\u7801\u53D1\u9001\u8FC7\u4E8E\u9891\u7E41\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5");
        }
      }
      const code = Math.floor(1e5 + Math.random() * 9e5).toString();
      await this.db.insert(this.tables.verificationCodes).values({
        phone,
        code,
        expiresAt: new Date(Date.now() + 10 * 60 * 1e3)
      }).returning();
      return code;
    } catch (error) {
      console.error("\u53D1\u9001\u9A8C\u8BC1\u7801\u5931\u8D25:", error);
      throw error;
    }
  }
  async verifyCode(phone, code) {
    try {
      const result = await this.db.select().from(this.tables.verificationCodes).where(
        and(
          eq(this.tables.verificationCodes.phone, phone),
          eq(this.tables.verificationCodes.code, code),
          eq(this.tables.verificationCodes.used, false),
          gt(this.tables.verificationCodes.expiresAt, /* @__PURE__ */ new Date())
        )
      ).limit(1);
      const verificationCode = result[0];
      if (!verificationCode) return false;
      await this.db.update(this.tables.verificationCodes).set({ used: true }).where(eq(this.tables.verificationCodes.id, verificationCode.id));
      return true;
    } catch (error) {
      console.error("\u9A8C\u8BC1\u7801\u9A8C\u8BC1\u5931\u8D25:", error);
      throw error;
    }
  }
  async resetPassword(phone, newPassword) {
    try {
      const hashedPassword = await bcrypt.hash(newPassword, this.saltRounds);
      await this.db.update(this.tables.users).set({ password: hashedPassword }).where(eq(this.tables.users.phone, phone));
    } catch (error) {
      console.error("\u5BC6\u7801\u91CD\u7F6E\u5931\u8D25:", error);
      throw error;
    }
  }
  async cleanupExpiredVerificationCodes() {
    try {
      const now = /* @__PURE__ */ new Date();
      await this.db.delete(this.tables.verificationCodes).where(lt(this.tables.verificationCodes.expiresAt, now)).returning();
    } catch (error) {
      console.error("\u6E05\u7406\u8FC7\u671F\u9A8C\u8BC1\u7801\u5931\u8D25:", error);
    }
  }
};

export { LegacyAuthDbService, legacyUserSessions, legacyUserSessionsRelations, legacyUsers, legacyUsersRelations, legacyVerificationCodes };
//# sourceMappingURL=index.mjs.map
//# sourceMappingURL=index.mjs.map